1#
2# Some tests for NSDecimal (C type) and NSDecimalNumber (Objective-C class)
3#
4from PyObjCTools.TestSupport import *
5from Foundation import *
6import operator
7import objc
8import sys
9
10try:
11    long
12except NameError:
13    long = int
14
15if 0:
16    class TestNSDecimal (TestCase):
17        def testConstants(self):
18            self.assertEqual(NSRoundPlain, 0)
19            self.assertEqual(NSRoundDown, 1)
20            self.assertEqual(NSRoundUp, 2)
21            self.assertEqual(NSRoundBankers, 3)
22
23            self.assertEqual(NSCalculationNoError, 0)
24            self.assertEqual(NSCalculationLossOfPrecision, 1)
25            self.assertEqual(NSCalculationUnderflow, 2)
26            self.assertEqual(NSCalculationOverflow, 3)
27            self.assertEqual(NSCalculationDivideByZero, 4)
28
29            self.assertEqual(NSDecimalMaxSize, 8)
30            self.assertEqual(NSDecimalNoScale, (2**15)-1)
31
32        def testCreation(self):
33            o = NSDecimal(b"1.25".decode('ascii'))
34            self.assert_(isinstance(o, NSDecimal))
35            self.assertEqual(str(o), b"1.25".decode('ascii'))
36
37            o = NSDecimal(12345, -2, objc.YES)
38            self.assert_(isinstance(o, NSDecimal))
39            self.assertEqual(str(o), b"-123.45".decode('ascii'))
40
41            o = NSDecimal()
42            self.assert_(isinstance(o, NSDecimal))
43            self.assert_(str(o) in (b"0".decode('ascii'), b"0.0".decode('ascii')))
44
45            o = NSDecimal(1234)
46            self.assert_(isinstance(o, NSDecimal))
47            self.assertEqual(str(o), b"1234".decode('ascii'))
48
49            o = NSDecimal(-1234)
50            self.assert_(isinstance(o, NSDecimal))
51            self.assertEqual(str(o), b"-1234".decode('ascii'))
52
53            o = NSDecimal(long(1234))
54            self.assert_(isinstance(o, NSDecimal))
55            self.assertEqual(str(o), b"1234".decode('ascii'))
56
57            o = NSDecimal(long(-1234))
58            self.assert_(isinstance(o, NSDecimal))
59            self.assertEqual(str(o), b"-1234".decode('ascii'))
60
61            o = NSDecimal(1 << 64 - 1)
62
63            # Explicit conversion is supported, but might not do
64            # what a naive user expects...
65            o = NSDecimal(1.1)
66            self.assert_(isinstance(o, NSDecimal))
67            self.assertEqual(str(o), repr(1.1))
68
69            self.assertRaises(OverflowError, NSDecimal, 1 << 128)
70            self.assertRaises(OverflowError, NSDecimal, -1 << 128)
71
72        def testFunction(self):
73            o = NSDecimal(b"1.5".decode('ascii'))
74            p = NSDecimal(12345, -2, objc.YES)
75            r = NSDecimal(b"-121.95".decode('ascii'))
76            q = NSDecimal()
77
78            NSDecimalAdd(q, o, p, NSRoundPlain)
79
80            self.assertEqual(str(q), str(r))
81
82            v = NSDecimalIsNotANumber(o)
83            self.assertIs(v, False)
84            v = NSDecimal()
85            NSDecimalCopy(v, o)
86            self.assertEqual(str(v), str(o))
87
88            NSDecimalCompact(v)
89
90            i = NSDecimalCompare(o, p)
91            self.assertIsInstance(i, (int, long))
92
93            NSDecimalRound(v, o, 0, NSRoundBankers)
94            self.assertEqual(str(v), '2')
95
96            t = NSDecimalNormalize(v, o, NSRoundBankers)
97            self.assertEqual(t, NSCalculationNoError)
98            self.assertEqual(str(v), '2.0')
99
100            t = NSDecimalPower(v, o, 3, NSRoundBankers)
101            self.assertEqual(t, NSCalculationNoError)
102            self.assertEqual(str(v), '3.375')
103
104            t = NSDecimalString(v, None)
105            self.assertEqual(t, b'3.375'.decode('ascii'))
106
107        def testCompare(self):
108            small = NSDecimal(b"1".decode('ascii'))
109            small2 = NSDecimal(b"1".decode('ascii'))
110            large = NSDecimal(b"42".decode('ascii'))
111
112            self.assert_(small == small2)
113            self.assert_(not (small == large))
114            self.assert_(not (small != small2))
115            self.assert_(small < large)
116            self.assert_(not(large < small))
117            self.assert_(not(small < small))
118            self.assert_(small <= large)
119            self.assert_(small <= small)
120            self.assert_(not(large <= small))
121            self.assert_(large > small)
122            self.assert_(not(small > large))
123            self.assert_(not(large > large))
124            self.assert_(large >= small)
125            self.assert_(large >= large)
126            self.assert_(not(small >= large))
127
128        def testConversion(self):
129            o = NSDecimal(b"1234.44".decode('ascii'))
130            self.assertEqual(o.as_int(), 1234)
131
132            o = NSDecimal(b"1.5".decode('ascii'))
133            self.assertEqual(o.as_float(), 1.5)
134
135            self.assertRaises(TypeError, int, o)
136            self.assertRaises(TypeError, float, o)
137
138        def testCreateFromFloat(self):
139            o = NSDecimal(1.1)
140            self.assertAlmostEquals(o.as_float(), 1.1)
141
142        if not hasattr(TestCase, 'assertAlmostEquals'):
143            def assertAlmostEquals(self, val1, val2, eta=0.000001):
144                self.assert_(abs(val1 - val2) < eta)
145
146
147    class TestNSDecimalNumber (TestCase):
148        def testCreation1(self):
149            o = NSDecimalNumber.decimalNumberWithString_(b"1.1234".decode('ascii'))
150            self.assertEqual(o.description(), b"1.1234".decode('ascii'))
151
152            p = o.decimalValue()
153            self.assert_(isinstance(p, NSDecimal))
154            self.assertEqual(str(p), b"1.1234".decode('ascii'))
155
156        def testCreation2(self):
157            p = NSDecimal(b"1.1234".decode('ascii'))
158            o = NSDecimalNumber.decimalNumberWithDecimal_(p)
159            self.assertEqual(o.description(), b"1.1234".decode('ascii'))
160
161        def testCreation3(self):
162            p = NSDecimal(b"1.1234".decode('ascii'))
163            o = NSDecimalNumber.alloc().initWithDecimal_(p)
164            self.assertEqual(o.description(), b"1.1234".decode('ascii'))
165
166    class NSDecimalOperators (TestCase):
167        def testCoerce(self):
168            r = NSDecimal(1)
169
170            v = coerce(r, r)
171            self.assertEqual(v, (r, r))
172
173            v = coerce(r, 2)
174            self.assertEqual(v, (r, NSDecimal(2)))
175
176            v = coerce(2, r)
177            self.assertEqual(v, (NSDecimal(2), r))
178
179            v = coerce(r, sys.maxint+2)
180            self.assertEqual(v, (r, NSDecimal(sys.maxint+2)))
181
182            v = coerce(sys.maxint+2, r)
183            self.assertEqual(v, (NSDecimal(sys.maxint+2), r))
184
185            t = NSDecimal(4).__pyobjc_object__
186            self.assert_(isinstance(t, NSObject))
187            v = coerce(t, r)
188            self.assertEqual(v, (NSDecimal(4), r))
189
190            v = coerce(r, t)
191            self.assertEqual(v, (r, NSDecimal(4)))
192
193            self.assertRaises(TypeError, coerce, 1.0, r)
194            self.assertRaises(TypeError, coerce, r, 1.0)
195            self.assertRaises(TypeError, coerce, "1.0", r)
196            self.assertRaises(TypeError, coerce, r, "1.0")
197            self.assertRaises(TypeError, coerce, b"1.0".decode('ascii'), r)
198            self.assertRaises(TypeError, coerce, r, b"1.0".decode('ascii'))
199            self.assertRaises(TypeError, coerce, (), r)
200            self.assertRaises(TypeError, coerce, r, ())
201
202
203        def testAddition(self):
204            r = NSDecimal()
205            o = NSDecimal(1)
206            p = NSDecimal(2)
207
208            O = o.__pyobjc_object__
209            P = p.__pyobjc_object__
210            self.assert_(isinstance(P, NSObject))
211            self.assert_(isinstance(O, NSObject))
212
213            NSDecimalAdd(r, o, p, NSRoundPlain)
214            self.assertEqual(o+p, r)
215            self.assertEqual(o+P, r)
216            self.assertEqual(O+p, r)
217            self.assertEqual(o+2, r)
218            self.assertEqual(o+long(2), r)
219            self.assertEqual(p+1, r)
220            self.assertEqual(1+p, r)
221
222            self.assertRaises(TypeError, operator.add, o, 1.2)
223            self.assertRaises(TypeError, operator.add, 1.2, o)
224            self.assertRaises(TypeError, operator.add, o, "1.2")
225            self.assertRaises(TypeError, operator.add, "1.2", o)
226            self.assertRaises(TypeError, operator.add, o, b"1.2".decode('ascii'))
227            self.assertRaises(TypeError, operator.add, b"1.2".decode('ascii'), o)
228            self.assertRaises(TypeError, operator.add, o, [])
229            self.assertRaises(TypeError, operator.add, [], o)
230
231        def testSubtraction(self):
232            r = NSDecimal()
233            o = NSDecimal(1)
234            p = NSDecimal(2)
235
236            P = p.__pyobjc_object__
237            O = o.__pyobjc_object__
238            self.assert_(isinstance(P, NSObject))
239            self.assert_(isinstance(O, NSObject))
240
241
242            NSDecimalSubtract(r, o, p, NSRoundPlain)
243            self.assertEqual(o-p, r)
244            self.assertEqual(O-p, r)
245            self.assertEqual(o-P, r)
246            self.assertEqual(o-2, r)
247            self.assertEqual(o-long(2), r)
248            self.assertEqual(1-p, r)
249            self.assertEqual(1-p, r)
250
251            self.assertRaises(TypeError, operator.sub, o, 1.2)
252            self.assertRaises(TypeError, operator.sub, 1.2, o)
253            self.assertRaises(TypeError, operator.sub, o, "1.2")
254            self.assertRaises(TypeError, operator.sub, "1.2", o)
255            self.assertRaises(TypeError, operator.sub, o, b"1.2".decode('ascii'))
256            self.assertRaises(TypeError, operator.sub, b"1.2".decode('ascii'), o)
257            self.assertRaises(TypeError, operator.sub, o, ())
258            self.assertRaises(TypeError, operator.sub, (), o)
259
260        def testMultiplication(self):
261            r = NSDecimal()
262            o = NSDecimal(2)
263            p = NSDecimal(3)
264
265            P = p.__pyobjc_object__
266            O = o.__pyobjc_object__
267            self.assert_(isinstance(P, NSObject))
268            self.assert_(isinstance(O, NSObject))
269
270            NSDecimalMultiply(r, o, p, NSRoundPlain)
271            self.assertEqual(o*p, r)
272            self.assertEqual(O*p, r)
273            self.assertEqual(o*P, r)
274            self.assertEqual(o*3, r)
275            self.assertEqual(o*long(3), r)
276            self.assertEqual(2*p, r)
277            self.assertEqual(2*p, r)
278
279            self.assertRaises(TypeError, operator.mul, o, 1.2)
280            self.assertRaises(TypeError, operator.mul, 1.2, o)
281
282            NSDecimalMultiplyByPowerOf10(r, o, 4, NSRoundPlain)
283            self.assertEqual(r, NSDecimal(20000))
284
285        def testDivision(self):
286            r = NSDecimal()
287            o = NSDecimal(2)
288            p = NSDecimal(3)
289
290            P = p.__pyobjc_object__
291            O = o.__pyobjc_object__
292            self.assert_(isinstance(P, NSObject))
293            self.assert_(isinstance(O, NSObject))
294
295            NSDecimalDivide(r, o, p, NSRoundPlain)
296            self.assertEqual(o/p, r)
297            self.assertEqual(O/p, r)
298            self.assertEqual(o/P, r)
299            self.assertEqual(o/3, r)
300            self.assertEqual(o/long(3), r)
301            self.assertEqual(2/p, r)
302            self.assertEqual(2/p, r)
303
304            self.assertRaises(TypeError, operator.div, o, 1.2)
305            self.assertRaises(TypeError, operator.div, 1.2, o)
306
307        def testPositive(self):
308            o = NSDecimal(2)
309            p = NSDecimal(-2)
310
311            self.assertEqual(+o, o)
312            self.assertEqual(+p, p)
313
314        def testNegative(self):
315            o = NSDecimal(2)
316            p = NSDecimal(-2)
317
318            self.assertEqual(-o, p)
319            self.assertEqual(-p, o)
320
321        def testAbs(self):
322            o = NSDecimal(2)
323            p = NSDecimal(-2)
324
325            self.assertEqual(abs(o), o)
326            self.assertEqual(abs(p), o)
327
328        def testBitwise(self):
329            o = NSDecimal(2)
330            p = NSDecimal(3)
331
332            self.assertRaises(TypeError, operator.and_, o, p)
333            self.assertRaises(TypeError, operator.or_, o, p)
334            self.assertRaises(TypeError, operator.not_, o, p)
335
336        def testPow(self):
337            o = NSDecimal(2)
338            p = NSDecimal(3)
339
340            self.assertRaises(TypeError, pow, o, p)
341            self.assertRaises(TypeError, pow, o, 2)
342            self.assertRaises(TypeError, pow, 2, o)
343
344        def testDivMod(self):
345            o = NSDecimal(2)
346            p = NSDecimal(3)
347
348            self.assertRaises(TypeError, divmod, o, p)
349            self.assertRaises(TypeError, divmod, o, 2)
350            self.assertRaises(TypeError, divmod, 2, o)
351
352        def testInplaceAddition(self):
353            r = NSDecimal()
354            o = NSDecimal(1)
355            p = NSDecimal(2)
356
357            P = p.__pyobjc_object__
358            self.assert_(isinstance(P, NSObject))
359
360            NSDecimalAdd(r, o, p, NSRoundPlain)
361
362            o = NSDecimal(1)
363            o += p
364            self.assertEqual(o, r)
365
366            o = NSDecimal(1)
367            o += P
368            self.assertEqual(o, r)
369
370            o = NSDecimal(1)
371            o += 2
372            self.assertEqual(o, r)
373
374            o = NSDecimal(1)
375            o += long(2)
376            self.assertEqual(o, r)
377
378            o = 1
379            o += p
380            self.assertEqual(o, r)
381
382            o = long(1)
383            o += p
384            self.assertEqual(o, r)
385
386            try:
387                o = 1.2
388                o += p
389                self.fail()
390            except TypeError:
391                pass
392
393            try:
394                o = NSDecimal(1)
395                o += 1.2
396                self.fail()
397            except TypeError:
398                pass
399
400        def testInplaceSubtraction(self):
401            r = NSDecimal()
402            o = NSDecimal(1)
403            p = NSDecimal(2)
404
405            P = p.__pyobjc_object__
406            self.assert_(isinstance(P, NSObject))
407
408            NSDecimalSubtract(r, o, p, NSRoundPlain)
409
410            o = NSDecimal(1)
411            o -= p
412            self.assertEqual(o, r)
413
414            o = NSDecimal(1)
415            o -= P
416            self.assertEqual(o, r)
417
418
419            o = NSDecimal(1)
420            o -= 2
421            self.assertEqual(o, r)
422
423            o = NSDecimal(1)
424            o -= 2
425            self.assertEqual(o, r)
426
427            o = 1
428            o -= p
429            self.assertEqual(o, r)
430
431            o = 1
432            o -= p
433            self.assertEqual(o, r)
434
435        def testInplaceMultiplication(self):
436            r = NSDecimal()
437            o = NSDecimal(2)
438            p = NSDecimal(3)
439
440            P = p.__pyobjc_object__
441            self.assert_(isinstance(P, NSObject))
442
443            NSDecimalMultiply(r, o, p, NSRoundPlain)
444
445            o = NSDecimal(2)
446            o *= p
447            self.assertEqual(o, r)
448
449            o = NSDecimal(2)
450            o *= P
451            self.assertEqual(o, r)
452
453            o = NSDecimal(2)
454            o *= 3
455            self.assertEqual(o, r)
456
457            o = NSDecimal(2)
458            o *= long(3)
459            self.assertEqual(o, r)
460
461            o = 2
462            o *= p
463            self.assertEqual(o, r)
464
465            o = long(2)
466            o *= p
467            self.assertEqual(o, r)
468
469        def testInplaceDivision(self):
470            r = NSDecimal()
471            o = NSDecimal(2)
472            p = NSDecimal(3)
473
474            P = p.__pyobjc_object__
475            self.assert_(isinstance(P, NSObject))
476
477            NSDecimalDivide(r, o, p, NSRoundPlain)
478
479            o = NSDecimal(2)
480            o /= p
481            self.assertEqual(o, r)
482
483            o = NSDecimal(2)
484            o /= P
485            self.assertEqual(o, r)
486
487            o = NSDecimal(2)
488            o /= 3
489            self.assertEqual(o, r)
490
491            o = NSDecimal(2)
492            o /= long(3)
493            self.assertEqual(o, r)
494
495            o = 2
496            o /= p
497            self.assertEqual(o, r)
498
499            o = long(2)
500            o /= p
501            self.assertEqual(o, r)
502
503    class NSDecimalNumberOperators (TestCase):
504        def testAddition(self):
505            r = NSDecimal()
506            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(1))
507            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
508
509            NSDecimalAdd(r, o.decimalValue(), p.decimalValue(), NSRoundPlain)
510            self.assertEqual((o+p), r)
511            self.assertEqual((o+2), r)
512            self.assertEqual((o+long(2)), r)
513            self.assertEqual((1+p), r)
514            self.assertEqual((1+p), r)
515
516            self.assertRaises(TypeError, operator.add, o, 1.2)
517            self.assertRaises(TypeError, operator.add, 1.2, o)
518
519            o = NSDecimalNumber.zero()
520            self.assertRaises(TypeError, operator.add, o, 1.2)
521
522        def testSubtraction(self):
523            r = NSDecimal()
524            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(1))
525            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
526
527            NSDecimalSubtract(r, o.decimalValue(), p.decimalValue(), NSRoundPlain)
528            self.assertEqual((o-p), r)
529            self.assertEqual((o-2), r)
530            self.assertEqual((o-long(2)), r)
531            self.assertEqual((1-p), r)
532            self.assertEqual((1-p), r)
533
534            self.assertRaises(TypeError, operator.sub, o, 1.2)
535            self.assertRaises(TypeError, operator.sub, 1.2, o)
536
537        def testMultiplication(self):
538            r = NSDecimal()
539            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
540            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(3))
541
542            NSDecimalMultiply(r, o.decimalValue(), p.decimalValue(), NSRoundPlain)
543            self.assertEqual((o*p), r)
544            self.assertEqual((o*3), r)
545            self.assertEqual((o*long(3)), r)
546            self.assertEqual((2*p), r)
547            self.assertEqual((2*p), r)
548
549            self.assertRaises(TypeError, operator.mul, o, 1.2)
550            self.assertRaises(TypeError, operator.mul, 1.2, o)
551
552        def testDivision(self):
553            r = NSDecimal()
554            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
555            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(3))
556
557            NSDecimalDivide(r, o.decimalValue(), p.decimalValue(), NSRoundPlain)
558            self.assertEqual((o/p), r)
559            self.assertEqual((o/3), r)
560            self.assertEqual((o/long(3)), r)
561            self.assertEqual((2/p), r)
562            self.assertEqual((2/p), r)
563
564            self.assertRaises(TypeError, operator.div, o, 1.2)
565            self.assertRaises(TypeError, operator.div, 1.2, o)
566
567        def testPositive(self):
568            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
569            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
570
571            self.assertEqual((+o), o.decimalValue())
572            self.assertEqual((+p), p.decimalValue())
573
574        def testNegative(self):
575            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
576            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
577
578            self.assertEqual((-o), p.decimalValue())
579            self.assertEqual((-p), o.decimalValue())
580
581        def testAbs(self):
582            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
583            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
584
585            self.assertEqual(abs(o), o.decimalValue())
586            self.assertEqual(abs(p), o.decimalValue())
587
588        def testBitwise(self):
589            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
590            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
591
592            self.assertRaises(TypeError, operator.and_, o, p)
593            self.assertRaises(TypeError, operator.or_, o, p)
594            self.assertRaises(TypeError, operator.not_, o, p)
595
596        def testPow(self):
597            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
598            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
599
600            self.assertRaises(TypeError, pow, o, p)
601            self.assertRaises(TypeError, pow, o, 2)
602            self.assertRaises(TypeError, pow, 2, o)
603
604        def testDivMod(self):
605            o = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(2))
606            p = NSDecimalNumber.decimalNumberWithDecimal_(NSDecimal(-2))
607
608            self.assertRaises(TypeError, divmod, o, p)
609            self.assertRaises(TypeError, divmod, o, 2)
610            self.assertRaises(TypeError, divmod, 2, o)
611
612
613if __name__ == "__main__":
614    main()
615