1from PyObjCTools.TestSupport import *
2import types
3import warnings
4import sys
5
6from Foundation import *
7
8try:
9    unicode
10except NameError:
11    unicode = str
12
13class TestNSString(TestCase):
14    def testClassTree(self):
15        self.assertTrue(issubclass(objc.pyobjc_unicode, unicode))
16
17    def testCompare(self):
18        self.assertTrue(
19            NSString.localizedCaseInsensitiveCompare_(b'foo'.decode('ascii'),b'bar'.decode('ascii')) == 1,
20            b"NSString doesn'.decode('ascii')t compare correctly")
21        self.assertTrue(
22            NSString.localizedCaseInsensitiveCompare_(b'foo'.decode('ascii'),b'Foo'.decode('ascii')) == 0,
23            b"NSString doesn'.decode('ascii')t compare correctly")
24
25    def testFormatting(self):
26        # The test on instances is slightly more verbose to avoid warnings
27        obj = NSString.alloc().initWithFormat_(b"foo %d".decode('ascii'), 42)
28        self.assertEqual(obj, b"foo 42".decode('ascii'))
29
30        obj = NSString.alloc().initWithFormat_locale_(b"foo %d".decode('ascii'), {}, 42)
31        self.assertEqual(obj, b"foo 42".decode('ascii'))
32
33
34    def testGetCString(self):
35        # Custom wrappers
36        v = NSString.stringWithString_(b"hello world".decode('ascii'))
37
38        self.assertEqual(v, b"hello world".decode('ascii'))
39
40        x = v.getCString_maxLength_(None, 16)
41        self.assertEqual(x, b"hello world")
42
43        self.assertRaises(objc.error, v.getCString_maxLength_, None, 4)
44
45        x, l = v.getCString_maxLength_range_remainingRange_(None, 4, (1, 4), None)
46        self.assertEqual(x, b"ello")
47        self.assertEqual(l.location, 5)
48        self.assertEqual(l.length, 0)
49
50
51class TestNSStringBridging(TestCase):
52    def setUp(self):
53        self.nsUniString = NSString.stringWithString_(b"unifoo".decode('ascii'))
54        self.pyUniString = b"unifoo".decode('ascii')
55
56    def testBasicComparison(self):
57        self.assertEqual(b"unifoo".decode('ascii'), NSString.stringWithString_(b"unifoo".decode('ascii')))
58
59        u = b'\xc3\xbc\xc3\xb1\xc3\xae\xc3\xa7\xc3\xb8d\xc3\xa8'.decode('latin1')
60        self.assertEqual(u, NSString.stringWithString_(u));
61
62    def testTypesAndClasses(self):
63        self.assertIsInstance(self.nsUniString, unicode)
64        self.assertIsInstance(self.pyUniString, unicode)
65
66    @onlyPython2
67    def testStrConversion(self):
68        curEnabledFlag = objc.getStrBridgeEnabled()
69        objc.setStrBridgeEnabled(True)
70        try:
71            v = NSString.stringWithString_("hello2")
72            self.assertIsInstance(v, objc.pyobjc_unicode)
73            self.assertEqual(v, b"hello2".decode('ascii'))
74
75
76            self.assertRaises(UnicodeError, unicode, "\xff")
77            # XXX: string bridge now uses the default NSString encoding
78            # self.assertRaises(UnicodeError, NSString.stringWithString_, '\xff')
79
80            objc.setStrBridgeEnabled(False)
81
82            warnings.filterwarnings('error', category=objc.PyObjCStrBridgeWarning)
83            try:
84                #v = NSString.stringWithString_("hello")
85
86                # we need to make sure that the str is unique
87                # because an already bridged one might have crossed
88                # and would be cached
89                newString = type('test_str', (str,), {})('hello2')
90                self.assertRaises(objc.PyObjCStrBridgeWarning,
91                        NSString.stringWithString_, newString)
92
93            finally:
94                del warnings.filters[0]
95
96
97        finally:
98            objc.setStrBridgeEnabled(curEnabledFlag)
99
100    def testNSStringMethodAccess(self):
101        self.assertIsInstance(self.nsUniString, objc.pyobjc_unicode)
102        v = self.nsUniString.stringByAppendingString_
103        self.assertIsInstance(v, objc.selector)
104
105class TestMutable(TestCase):
106    def testSync(self):
107        """
108        Test that python and ObjC string representation are not
109        automaticly synchronized.
110        """
111        pyStr = NSMutableString.stringWithString_(b"hello".decode('ascii'))
112        ocStr= pyStr.nsstring()
113        self.assertEqual(pyStr, b"hello".decode('ascii'))
114        self.assertIsInstance(ocStr, NSMutableString)
115        ocStr.appendString_(b" world".decode('ascii'))
116        self.assertEqual(pyStr, b"hello".decode('ascii'))
117
118class TestPickle(TestCase):
119    """
120    Testcases for pickling of Objective-C strings. Those are pickled as
121    unicode strings.
122    """
123
124    def setUp(self):
125        self.strVal = NSTaskDidTerminateNotification
126
127    def testPickle(self):
128        """
129        Check that ObjC-strings pickle as unicode strings
130        """
131        import pickle
132
133        s = pickle.dumps(self.strVal, 0)
134        v = pickle.loads(s)
135        self.assertEqual(type(v), unicode)
136
137        s = pickle.dumps(self.strVal, 1)
138        v = pickle.loads(s)
139        self.assertEqual(type(v), unicode)
140
141        s = pickle.dumps(self.strVal, 2)
142        v = pickle.loads(s)
143        self.assertEqual(type(v), unicode)
144
145    @onlyPython2
146    def testCPickle(self):
147        """
148        Check that ObjC-strings pickle as unicode strings
149        """
150        import cPickle as pickle
151
152        s = pickle.dumps(self.strVal, 0)
153        v = pickle.loads(s)
154        self.assertEqual(type(v), unicode)
155
156        s = pickle.dumps(self.strVal, 1)
157        v = pickle.loads(s)
158        self.assertEqual(type(v), unicode)
159
160        s = pickle.dumps(self.strVal, 2)
161        v = pickle.loads(s)
162        self.assertEqual(type(v), unicode)
163
164    def testFormat(self):
165        v = self.strVal
166
167        d = v.stringByAppendingFormat_(b"hello".decode('ascii'))
168        self.assertEqual(d, v + b'hello'.decode('ascii'))
169
170        d = v.stringByAppendingFormat_(b"hello %s %d".decode('ascii'), b"world", 101)
171        self.assertEqual(d, v + b'hello world 101'.decode('ascii'))
172
173        v = NSString.alloc().initWithFormat_("%s %d %s", b"a", 44, b"cc")
174        self.assertEqual(v, "a 44 cc")
175
176        v = NSString.alloc().initWithFormat_locale_("%s %d %s", None, b"a", 44, b"cc")
177        self.assertEqual(v, "a 44 cc")
178
179        v = NSString.stringWithFormat_("aap %s mies", b"noot")
180        self.assertEqual(v, "aap noot mies")
181
182        v = NSString.localizedStringWithFormat_("aap %s mies", b"noot")
183        self.assertEqual(v, "aap noot mies")
184
185
186        v = NSMutableString.stringWithString_("hello")
187        v.appendFormat_(" bar %s", b"baz")
188        self.assertEqual(v.nsstring(), "hello bar baz")
189
190    @min_os_level('10.7')
191    def testConstants10_7(self):
192        self.assertEqual(NSRegularExpressionSearch, 1024)
193
194    @min_os_level('10.5')
195    def testConstants10_5(self):
196        self.assertEqual(NSMaximumStringLength, sys.maxsize)
197        self.assertEqual(NSDiacriticInsensitiveSearch, 128)
198        self.assertEqual(NSWidthInsensitiveSearch, 256)
199        self.assertEqual(NSForcedOrderingSearch, 512)
200
201        self.assertEqual(NSProprietaryStringEncoding, 65536)
202
203    def testConstants(self):
204        self.assertIsInstance(NSParseErrorException, unicode)
205        self.assertIsInstance(NSCharacterConversionException, unicode)
206
207        self.assertEqual(NSCaseInsensitiveSearch, 1)
208        self.assertEqual(NSLiteralSearch, 2)
209        self.assertEqual(NSBackwardsSearch, 4)
210        self.assertEqual(NSAnchoredSearch, 8)
211        self.assertEqual(NSNumericSearch, 64)
212        self.assertEqual(NSASCIIStringEncoding, 1)
213        self.assertEqual(NSNEXTSTEPStringEncoding, 2)
214        self.assertEqual(NSJapaneseEUCStringEncoding, 3)
215        self.assertEqual(NSUTF8StringEncoding, 4)
216        self.assertEqual(NSISOLatin1StringEncoding, 5)
217        self.assertEqual(NSSymbolStringEncoding, 6)
218        self.assertEqual(NSNonLossyASCIIStringEncoding, 7)
219        self.assertEqual(NSShiftJISStringEncoding, 8)
220        self.assertEqual(NSISOLatin2StringEncoding, 9)
221        self.assertEqual(NSUnicodeStringEncoding, 10)
222        self.assertEqual(NSWindowsCP1251StringEncoding, 11)
223        self.assertEqual(NSWindowsCP1252StringEncoding, 12)
224        self.assertEqual(NSWindowsCP1253StringEncoding, 13)
225        self.assertEqual(NSWindowsCP1254StringEncoding, 14)
226        self.assertEqual(NSWindowsCP1250StringEncoding, 15)
227        self.assertEqual(NSISO2022JPStringEncoding, 21)
228        self.assertEqual(NSMacOSRomanStringEncoding, 30)
229        self.assertEqual(NSUTF16StringEncoding, NSUnicodeStringEncoding)
230        self.assertEqual(NSUTF16BigEndianStringEncoding, cast_uint(0x90000100))
231        self.assertEqual(NSUTF16LittleEndianStringEncoding, cast_uint(0x94000100))
232        self.assertEqual(NSUTF32StringEncoding, cast_uint(0x8c000100))
233        self.assertEqual(NSUTF32BigEndianStringEncoding, cast_uint(0x98000100))
234        self.assertEqual(NSUTF32LittleEndianStringEncoding, cast_uint(0x9c000100))
235        self.assertEqual(NSStringEncodingConversionAllowLossy, 1)
236        self.assertEqual(NSStringEncodingConversionExternalRepresentation, 2)
237
238    def testMethods(self):
239        self.assertArgHasType(NSString.getCharacters_range_, 0, b'o^' + objc._C_UNICHAR)
240        self.assertArgSizeInArg(NSString.getCharacters_range_, 0, 1)
241
242        self.assertResultIsBOOL(NSString.isEqualToString_)
243        self.assertResultIsBOOL(NSString.hasPrefix_)
244        self.assertResultIsBOOL(NSString.hasSuffix_)
245        self.assertResultIsBOOL(NSString.boolValue)
246        self.assertArgIsOut(NSString.getLineStart_end_contentsEnd_forRange_, 0)
247        self.assertArgIsOut(NSString.getLineStart_end_contentsEnd_forRange_, 1)
248        self.assertArgIsOut(NSString.getLineStart_end_contentsEnd_forRange_, 2)
249        self.assertArgIsOut(NSString.getParagraphStart_end_contentsEnd_forRange_, 0)
250        self.assertArgIsOut(NSString.getParagraphStart_end_contentsEnd_forRange_, 1)
251        self.assertArgIsOut(NSString.getParagraphStart_end_contentsEnd_forRange_, 2)
252        self.assertArgIsBOOL(NSString.dataUsingEncoding_allowLossyConversion_, 1)
253        self.assertResultIsBOOL(NSString.canBeConvertedToEncoding_)
254        self.assertResultIsNullTerminated(NSString.cStringUsingEncoding_)
255        self.assertResultHasType(NSString.cStringUsingEncoding_, b'^v')
256        self.assertResultIsBOOL(NSString.getCString_maxLength_encoding_)
257        self.assertArgHasType(NSString.getCString_maxLength_encoding_, 0, b'o^v')
258        self.assertArgSizeInArg(NSString.getCString_maxLength_encoding_, 0, 1)
259
260        self.assertResultIsBOOL(NSString.getBytes_maxLength_usedLength_encoding_options_range_remainingRange_)
261        self.assertArgHasType(NSString.getBytes_maxLength_usedLength_encoding_options_range_remainingRange_, 0, b'o^v')
262        self.assertArgSizeInArg(NSString.getBytes_maxLength_usedLength_encoding_options_range_remainingRange_, 0, (1,2))
263        self.assertArgIsOut(NSString.getBytes_maxLength_usedLength_encoding_options_range_remainingRange_, 2)
264        self.assertArgIsOut(NSString.getBytes_maxLength_usedLength_encoding_options_range_remainingRange_, 6)
265
266        self.assertResultHasType(NSString.UTF8String, b'^' + objc._C_CHAR_AS_TEXT)
267        self.assertResultIsNullTerminated(NSString.UTF8String)
268        self.assertResultIsNullTerminated(NSString.availableStringEncodings)
269
270        self.assertArgHasType(NSString.initWithCharactersNoCopy_length_freeWhenDone_, 0, b'n^' + objc._C_UNICHAR)
271        self.assertArgSizeInArg(NSString.initWithCharactersNoCopy_length_freeWhenDone_, 0, 1)
272        self.assertArgIsBOOL(NSString.initWithCharactersNoCopy_length_freeWhenDone_, 2)
273        self.assertArgHasType(NSString.initWithCharacters_length_, 0, b'n^' + objc._C_UNICHAR)
274        self.assertArgSizeInArg(NSString.initWithCharacters_length_, 0, 1)
275        self.assertArgHasType(NSString.initWithUTF8String_, 0, b'n^' + objc._C_CHAR_AS_TEXT)
276        self.assertArgIsNullTerminated(NSString.initWithUTF8String_, 0)
277        self.assertArgIsPrintf(NSString.initWithFormat_, 0)
278        self.assertArgIsPrintf(NSString.initWithFormat_locale_, 0)
279
280        o = NSString.alloc()
281        self.assertArgIsIn(o.initWithBytes_length_encoding_, 0)
282        self.assertArgSizeInArg(o.initWithBytes_length_encoding_, 0, 1)
283        o = o.init()
284        self.assertArgIsIn(NSString.initWithBytesNoCopy_length_encoding_freeWhenDone_, 0)
285        self.assertArgSizeInArg(NSString.initWithBytesNoCopy_length_encoding_freeWhenDone_, 0, 1)
286        self.assertArgIsBOOL(NSString.initWithBytesNoCopy_length_encoding_freeWhenDone_, 3)
287
288        self.assertArgHasType(NSString.stringWithCharacters_length_, 0, b'n^' + objc._C_UNICHAR)
289        self.assertArgSizeInArg(NSString.stringWithCharacters_length_, 0, 1)
290        self.assertArgHasType(NSString.stringWithUTF8String_, 0, b'n^' + objc._C_CHAR_AS_TEXT)
291        self.assertArgIsNullTerminated(NSString.stringWithUTF8String_, 0)
292        self.assertArgIsPrintf(NSString.stringWithFormat_, 0)
293        self.assertArgIsPrintf(NSString.localizedStringWithFormat_, 0)
294
295        self.assertArgHasType(NSString.initWithCString_encoding_, 0, b'n^t')
296        self.assertArgIsNullTerminated(NSString.initWithCString_encoding_, 0)
297        self.assertArgHasType(NSString.stringWithCString_encoding_, 0, b'n^t')
298        self.assertArgIsNullTerminated(NSString.stringWithCString_encoding_, 0)
299
300        self.assertArgIsOut(NSString.initWithContentsOfURL_encoding_error_, 2)
301        self.assertArgIsOut(NSString.initWithContentsOfFile_encoding_error_, 2)
302        self.assertArgIsOut(NSString.stringWithContentsOfURL_encoding_error_, 2)
303        self.assertArgIsOut(NSString.stringWithContentsOfFile_encoding_error_, 2)
304
305        self.assertArgIsOut(NSString.initWithContentsOfURL_usedEncoding_error_, 1)
306        self.assertArgIsOut(NSString.initWithContentsOfURL_usedEncoding_error_, 2)
307        self.assertArgIsOut(NSString.initWithContentsOfFile_usedEncoding_error_, 1)
308        self.assertArgIsOut(NSString.initWithContentsOfFile_usedEncoding_error_, 2)
309        self.assertArgIsOut(NSString.stringWithContentsOfURL_usedEncoding_error_, 1)
310        self.assertArgIsOut(NSString.stringWithContentsOfURL_usedEncoding_error_, 2)
311        self.assertArgIsOut(NSString.stringWithContentsOfFile_usedEncoding_error_, 1)
312        self.assertArgIsOut(NSString.stringWithContentsOfFile_usedEncoding_error_, 2)
313
314        self.assertResultIsBOOL(NSString.writeToURL_atomically_encoding_error_)
315        self.assertArgIsBOOL(NSString.writeToURL_atomically_encoding_error_, 1)
316        self.assertArgIsOut(NSString.writeToURL_atomically_encoding_error_, 3)
317        self.assertResultIsBOOL(NSString.writeToFile_atomically_encoding_error_)
318        self.assertArgIsBOOL(NSString.writeToFile_atomically_encoding_error_, 1)
319        self.assertArgIsOut(NSString.writeToFile_atomically_encoding_error_, 3)
320
321        self.assertArgIsPrintf(NSMutableString.appendFormat_, 0)
322
323        self.assertResultHasType(NSString.cString, b'^t')
324        self.assertResultIsNullTerminated(NSString.cString)
325        self.assertResultHasType(NSString.lossyCString, b'^t')
326        self.assertResultIsNullTerminated(NSString.lossyCString)
327
328        self.assertArgHasType(NSString.getCString_maxLength_, 0, b'o^v')
329        self.assertArgSizeInArg(NSString.getCString_maxLength_, 0, 1)
330
331        self.assertArgHasType(NSString.getCString_maxLength_range_remainingRange_, 0, b'o^v')
332        self.assertArgSizeInArg(NSString.getCString_maxLength_range_remainingRange_, 0, 1)
333        self.assertArgIsOut(NSString.getCString_maxLength_range_remainingRange_, 3)
334
335        self.assertResultIsBOOL(NSString.writeToFile_atomically_)
336        self.assertArgIsBOOL(NSString.writeToFile_atomically_, 1)
337        self.assertResultIsBOOL(NSString.writeToURL_atomically_)
338        self.assertArgIsBOOL(NSString.writeToURL_atomically_, 1)
339
340        self.assertArgHasType(NSString.initWithCStringNoCopy_length_freeWhenDone_, 0, b'n^v')
341        self.assertArgSizeInArg(NSString.initWithCStringNoCopy_length_freeWhenDone_, 0, 1)
342        self.assertArgIsBOOL(NSString.initWithCStringNoCopy_length_freeWhenDone_, 2)
343        self.assertArgHasType(NSString.initWithCString_length_, 0, b'n^v')
344        self.assertArgSizeInArg(NSString.initWithCString_length_, 0, 1)
345        self.assertArgHasType(NSString.initWithCString_, 0, b'n^v')
346        self.assertArgIsNullTerminated(NSString.initWithCString_, 0)
347
348        self.assertArgHasType(NSString.stringWithCString_length_, 0, b'n^v')
349        self.assertArgSizeInArg(NSString.stringWithCString_length_, 0, 1)
350        self.assertArgHasType(NSString.stringWithCString_, 0, b'n^v')
351        self.assertArgIsNullTerminated(NSString.stringWithCString_, 0)
352
353    @min_os_level('10.6')
354    def testConstants10_6(self):
355        self.assertEqual(NSStringEnumerationByLines, 0)
356        self.assertEqual(NSStringEnumerationByParagraphs, 1)
357        self.assertEqual(NSStringEnumerationByComposedCharacterSequences, 2)
358        self.assertEqual(NSStringEnumerationByWords, 3)
359        self.assertEqual(NSStringEnumerationBySentences, 4)
360        self.assertEqual(NSStringEnumerationReverse, 1 << 8)
361        self.assertEqual(NSStringEnumerationSubstringNotRequired, 1 << 9)
362        self.assertEqual(NSStringEnumerationLocalized, 1 << 10)
363
364    @min_os_level('10.6')
365    def testMethods10_6(self):
366        self.assertArgHasType(NSString.enumerateSubstringsInRange_options_usingBlock_, 0,
367                NSRange.__typestr__)
368        self.assertArgIsBlock(NSString.enumerateSubstringsInRange_options_usingBlock_, 2, b'v@'+NSRange.__typestr__+NSRange.__typestr__+b'o^'+objc._C_NSBOOL)
369        self.assertArgIsBlock(NSString.enumerateLinesUsingBlock_, 0, b'v@o^'+objc._C_NSBOOL)
370
371
372
373if __name__ == '__main__':
374    main()
375