1from PyObjCTools.TestSupport import *
2import objc
3import re
4import sys
5import operator
6import os
7
8from Foundation import *
9
10PLIST=u"""\
11<?xml version="1.0" encoding="UTF-8"?>
12<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
13<plist version="1.0">
14<dict>
15\t<key>bool</key>
16\t<true/>
17\t<key>plain</key>
18\t<integer>1</integer>
19</dict>
20</plist>
21"""
22
23def stripDocType(val):
24    """
25    Strip non-significant information. This is needed because the proplists
26    on MacOS X 10.1 are slightly different from the ones on MacOS X 10.2 (
27    different DOCTYPE and version).
28    """
29    r =  re.sub(u'<!DOCTYPE [^>]*>', u'<!DOCTYPE>', val)
30    return r.replace(u'version="0.9"', u'version="1.0"')
31
32
33class TestNSNumber( TestCase ):
34    def testSimple(self):
35        self.assertEquals(NSNumber.numberWithFloat_(1.0), 1,0)
36        self.assertEquals(NSNumber.numberWithInt_(1), 1)
37        self.assertEquals(NSNumber.numberWithFloat_(-0.5), -0.5)
38        self.assertEquals(NSNumber.numberWithInt_(-4), -4)
39        self.assertEquals(NSNumber.numberWithInt_(0), 0)
40        self.assertEquals(NSNumber.numberWithFloat_(0.0), 0.0)
41
42    def testReadOnly(self):
43        n = NSNumber.numberWithFloat_(1.2)
44        self.assertRaises(AttributeError, setattr, n, 'foo', 2)
45
46        n = NSNumber.numberWithInt_(1)
47        self.assertRaises(AttributeError, setattr, n, 'foo', 2)
48
49        n = NSNumber.numberWithLongLong_(sys.maxint + 2)
50        self.assertRaises(AttributeError, setattr, n, 'foo', 2)
51
52    def testUseAsBasicType(self):
53        lstValue = list(range(0, 20, 2))
54        for idx, v in enumerate(lstValue):
55            self.assertEquals(v, lstValue[NSNumber.numberWithInt_(idx)])
56            self.assertEquals(v, lstValue[NSNumber.numberWithLong_(idx)])
57            self.assertEquals(v, lstValue[NSNumber.numberWithLongLong_(idx)])
58
59        self.assertRaises(TypeError, operator.getitem, lstValue,
60                NSNumber.numberWithFloat_(2.0))
61
62    def testUnsignedIssues(self):
63        # NSNumber stores unsigned numbers as signed numbers
64        # This is a bug in Cocoa... (RADAR #4007594), fixed in 10.5
65        if sdkForPython() < (10, 5):
66		self.assertEquals(NSNumber.numberWithUnsignedInt_(sys.maxint+1),
67			    -sys.maxint-1)
68	else:
69		self.assertEquals(NSNumber.numberWithUnsignedInt_(sys.maxint+1),
70			    sys.maxint+1)
71
72    def testMethods(self):
73        v = NSNumber.numberWithUnsignedInt_(sys.maxint+1)
74
75        self.assertEquals(v.unsignedIntValue(), sys.maxint+1)
76        self.assertEquals(v.intValue(), -sys.maxint-1)
77
78        v = NSNumber.numberWithInt_(10)
79        self.assertEquals(v.doubleValue(), float(10))
80
81    def testMath(self):
82        Xs = list(range(10, 40, 3))
83        Ys = list(range(-12, 44, 5))
84
85        self.assert_(0 not in Ys)
86        self.assert_(0 not in Xs)
87
88        for x in Xs:
89            for y in Ys:
90                Nx = NSNumber.numberWithInt_(x)
91                Ny = NSNumber.numberWithInt_(y)
92
93                self.assertEquals(x + y, Nx + Ny)
94                self.assertEquals(x - y, Nx - Ny)
95                self.assertEquals(x * y, Nx * Ny)
96                self.assertEquals(x / y, Nx / Ny)
97                self.assertEquals(x % y, Nx % Ny)
98                self.assertEquals(x ** y, Nx ** Ny)
99
100                Nx = NSNumber.numberWithFloat_(x+0.5)
101                Ny = NSNumber.numberWithFloat_(y+0.5)
102
103                self.assertEquals((x+0.5) + (y+0.5), Nx + Ny)
104                self.assertEquals((x+0.5) - (y+0.5), Nx - Ny)
105                self.assertEquals((x+0.5) * (y+0.5), Nx * Ny)
106                self.assertEquals((x+0.5) / (y+0.5), Nx / Ny)
107                self.assertEquals((x+0.5) % (y+0.5), Nx % Ny)
108                self.assertEquals((x+0.5) ** (y+0.5), Nx ** Ny)
109
110                Nx = NSNumber.numberWithLongLong_(x)
111                Ny = NSNumber.numberWithLongLong_(y)
112
113                self.assertEquals(long(x) + long(y), Nx + Ny)
114                self.assertEquals(long(x) - long(y), Nx - Ny)
115                self.assertEquals(long(x) * long(y), Nx * Ny)
116                self.assertEquals(long(x) / long(y), Nx / Ny)
117                self.assertEquals(long(x) % long(y), Nx % Ny)
118                self.assertEquals(long(x) ** long(y), Nx ** Ny)
119
120
121    def testTyping(self):
122        # Thanks to some tricks and a cooperating Python runtime,
123        # NSNumber "instances" seem to be subclasses of both NSNumber and
124        # the corresponding Python number type.
125        #
126
127        n = NSNumber.numberWithInt_(10)
128        self.assert_(isinstance(n, (int, long)))
129        self.assert_(isinstance(n, NSNumber))
130
131        n = NSNumber.numberWithUnsignedInt_(10)
132        self.assert_(isinstance(n, (int, long)))
133        self.assert_(isinstance(n, NSNumber))
134
135        n = NSNumber.numberWithLong_(10)
136        self.assert_(isinstance(n, (int, long)))
137        self.assert_(isinstance(n, NSNumber))
138
139        n = NSNumber.numberWithUnsignedLong_(10)
140        self.assert_(isinstance(n, (int, long)))
141        self.assert_(isinstance(n, NSNumber))
142
143        n = NSNumber.numberWithLongLong_(sys.maxint * 1024L)
144        self.assertEquals(n, sys.maxint * 1024L)
145        self.assert_(isinstance(n, (int, long)))
146        self.assert_(isinstance(n, NSNumber))
147
148        n = NSNumber.numberWithUnsignedLongLong_(sys.maxint + 100)
149        self.assertEquals(n, sys.maxint + 100)
150        self.assert_(isinstance(n, (int, long)))
151        self.assert_(isinstance(n, NSNumber))
152
153        n = NSNumber.numberWithFloat_(10)
154        self.assert_(isinstance(n, float))
155        self.assert_(isinstance(n, NSNumber))
156
157        n = NSNumber.numberWithDouble_(10)
158        self.assert_(isinstance(n, float))
159        self.assert_(isinstance(n, NSNumber))
160
161
162if objc.platform == 'MACOSX':
163    class TestPropList (TestCase):
164        #Test if numbers are stored properly in property-list. The most
165        #important part of the testcase are boolean values.
166        #
167        # NOTE: GNUstep uses the old NeXT property lists, and these tests
168        # will fail.
169
170        def testPropertyList1(self):
171            d = NSMutableDictionary.dictionary()
172
173            # Python 2.3 only...
174            d[u'plain'] = 1
175            d[u'bool'] = objc.YES
176
177            self.assertEquals(d.writeToFile_atomically_(
178                u"/tmp/pyobjctest.plist", 0), 1)
179
180            fd = open(u'/tmp/pyobjctest.plist', 'ru')
181            data = fd.read().decode('utf8')
182            fd.close()
183
184            self.assertEquals(stripDocType(data), stripDocType(PLIST))
185
186        def testPropertyList2(self):
187            d = NSMutableDictionary.dictionary()
188
189            d[u'plain'] = NSNumber.numberWithLong_(1)
190            d[u'bool'] = NSNumber.numberWithBool_(1)
191
192            self.assertEquals(d.writeToFile_atomically_(
193                u"/tmp/pyobjctest.plist", 0), 1)
194
195            fd = open(u'/tmp/pyobjctest.plist', 'ru')
196            data = fd.read().decode('utf8')
197            fd.close()
198
199            self.assertEquals(stripDocType(data), stripDocType(PLIST))
200
201class TestDecimalNumber (TestCase):
202    def testProxy (self):
203        one = NSDecimalNumber.decimalNumberWithString_(u"1.00")
204        self.assert_(isinstance(one, NSDecimalNumber))
205
206        two = NSDecimalNumber.decimalNumberWithString_(u"2.00")
207        self.assert_(isinstance(two, NSDecimalNumber))
208
209        three = NSDecimalNumber.decimalNumberWithString_(u"3.00")
210        self.assert_(isinstance(three, NSDecimalNumber))
211
212        six = NSDecimalNumber.decimalNumberWithString_(u"6.00")
213        self.assert_(isinstance(six, NSDecimalNumber))
214
215        one_half = NSDecimalNumber.decimalNumberWithString_(u"0.50")
216        self.assert_(isinstance(one_half, NSDecimalNumber))
217
218
219        self.failUnlessEqual(one + two, three)
220        self.failUnlessEqual(three - one, two)
221        self.failUnlessEqual(three * two, six)
222        self.failUnlessEqual(one / two, one_half)
223
224
225
226if __name__ == '__main__':
227    main( )
228