1# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5#    and Facundo Batista <facundo at taniquetil.com.ar>
6#    and Raymond Hettinger <python at rcn.com>
7#    and Aahz (aahz at pobox.com)
8#    and Tim Peters
9
10"""
11These are the test cases for the Decimal and Cdecimal modules.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
19   www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
27from __future__ import with_statement
28
29import math
30import os, sys
31import pickle, copy
32import unittest
33from cdecimal import *
34from test.test_support import (run_unittest, run_doctest, is_resource_enabled)
35import random
36try:
37    import threading
38except ImportError:
39    threading = None
40
41py_minor = sys.version_info[1]
42assert py_minor == 5, "These tests are for version 2.5 only."
43HAVE_CDECIMAL= True
44HAVE_CONFIG_64 = (MAX_EMAX == 999999999999999999)
45
46# Useful Test Constant
47Signals = getcontext().flags.keys()
48
49# Tests are built around these assumed context defaults.
50# test_main() restores the original context.
51def init():
52    global ORIGINAL_CONTEXT
53    ORIGINAL_CONTEXT = getcontext().copy()
54    DefaultTestContext = Context(
55        prec = 9,
56        rounding = ROUND_HALF_EVEN,
57        traps = dict.fromkeys(Signals, 0)
58        )
59    setcontext(DefaultTestContext)
60
61
62# The official limits for the 32-bit version are -425000000
63# and 425000000. The following values are safe for all tests
64# in the test suite.
65readcontext = Context()
66readcontext.unsafe_setprec(1070000000)
67readcontext.unsafe_setemax(1070000000)
68readcontext.unsafe_setemin(-1070000000)
69readcontext._traps = 0
70
71
72TESTDATADIR = 'decimaltestdata'
73if __name__ == '__main__':
74    file = sys.argv[0]
75else:
76    file = __file__
77testdir = os.path.dirname(file) or os.curdir
78directory = testdir + os.sep + TESTDATADIR + os.sep
79
80skip_expected = not os.path.isdir(directory)
81
82# list of individual .decTest test ids that correspond to tests that
83# we're skipping for one reason or another.
84skipped_test_ids = [
85    'scbx164',  # skipping apparently implementation-specific scaleb
86    'scbx165',  # tests, pending clarification of scaleb rules.
87]
88
89# XXX: BEGIN FASTDEC SKIPS
90status_cases = {}
91if HAVE_CONFIG_64:
92    # 64 bit version: With a reduced working precision in mpd_qpow()
93    # the status matches.
94    status_cases = {
95        "pwsx803": ([Inexact, Rounded, Subnormal, Underflow], [Inexact, Rounded]),
96        "pwsx805": ([Inexact, Rounded, Subnormal, Underflow], [Inexact, Rounded])
97    }
98
99# These are skipped for decNumber, too. They might as well be added to
100# the ULP cases.
101skip_cases = {
102    "powx4302": ("1.000000", "1.000001"),
103    "powx4303": ("1.000000", "1.000001"),
104    "powx4342": ("1.000000", "0.9999999"),
105    "powx4343": ("1.000000", "0.9999999")
106}
107
108# Disagreements:
109# pwmx325 power 0 1 1234567890 -> NaN Invalid_operation -- got 0
110disagree = ['pwmx325', 'pwmx326']
111# END FASTDEC SKIPS
112
113
114# Make sure it actually raises errors when not expected and caught in flags
115# Slower, since it runs some things several times.
116EXTENDEDERRORTEST = True
117
118#Map the test cases' error names to the actual errors
119ErrorNames = {'clamped' : Clamped,
120              'conversion_syntax' : InvalidOperation,
121              'division_by_zero' : DivisionByZero,
122              'division_impossible' : InvalidOperation,
123              'division_undefined' : InvalidOperation,
124              'inexact' : Inexact,
125              'invalid_context' : InvalidOperation,
126              'invalid_operation' : InvalidOperation,
127              'overflow' : Overflow,
128              'rounded' : Rounded,
129              'subnormal' : Subnormal,
130              'underflow' : Underflow}
131
132
133def Nonfunction(*args):
134    """Doesn't do anything."""
135    return None
136
137RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
138                'down' : ROUND_DOWN,
139                'floor' : ROUND_FLOOR,
140                'half_down' : ROUND_HALF_DOWN,
141                'half_even' : ROUND_HALF_EVEN,
142                'half_up' : ROUND_HALF_UP,
143                'up' : ROUND_UP,
144                '05up' : ROUND_05UP}
145
146# Name adapter to be able to change the Decimal and Context
147# interface without changing the test files from Cowlishaw
148nameAdapter = {'and':'logical_and',
149               'apply':'_apply',
150               'class':'number_class',
151               'comparesig':'compare_signal',
152               'comparetotal':'compare_total',
153               'comparetotmag':'compare_total_mag',
154               'copy':'copy_decimal',
155               'copyabs':'copy_abs',
156               'copynegate':'copy_negate',
157               'copysign':'copy_sign',
158               'divideint':'divide_int',
159               'invert':'logical_invert',
160               'iscanonical':'is_canonical',
161               'isfinite':'is_finite',
162               'isinfinite':'is_infinite',
163               'isnan':'is_nan',
164               'isnormal':'is_normal',
165               'isqnan':'is_qnan',
166               'issigned':'is_signed',
167               'issnan':'is_snan',
168               'issubnormal':'is_subnormal',
169               'iszero':'is_zero',
170               'maxmag':'max_mag',
171               'minmag':'min_mag',
172               'nextminus':'next_minus',
173               'nextplus':'next_plus',
174               'nexttoward':'next_toward',
175               'or':'logical_or',
176               'reduce':'normalize',
177               'remaindernear':'remainder_near',
178               'samequantum':'same_quantum',
179               'squareroot':'sqrt',
180               'toeng':'to_eng_string',
181               'tointegral':'to_integral_value',
182               'tointegralx':'to_integral_exact',
183               'tosci':'to_sci_string',
184               'xor':'logical_xor',
185              }
186
187# The following functions return True/False rather than a Decimal instance
188
189LOGICAL_FUNCTIONS = (
190    'is_canonical',
191    'is_finite',
192    'is_infinite',
193    'is_nan',
194    'is_normal',
195    'is_qnan',
196    'is_signed',
197    'is_snan',
198    'is_subnormal',
199    'is_zero',
200    'same_quantum',
201    )
202
203# For some operations (currently exp, ln, log10, power), the decNumber
204# reference implementation imposes additional restrictions on the
205# context and operands.  These restrictions are not part of the
206# specification; however, the effect of these restrictions does show
207# up in some of the testcases.  We skip testcases that violate these
208# restrictions, since Decimal behaves differently from decNumber for
209# these testcases so these testcases would otherwise fail.
210
211decNumberRestricted = ('power', 'ln', 'log10', 'exp')
212DEC_MAX_MATH = 999999
213def outside_decNumber_bounds(v, context):
214    if (context.prec > DEC_MAX_MATH or
215        context.Emax > DEC_MAX_MATH or
216        -context.Emin > DEC_MAX_MATH):
217        return True
218    if not v.is_special() and v and (
219        v.adjusted() > DEC_MAX_MATH or
220        v.adjusted() < 1-2*DEC_MAX_MATH):
221        return True
222    return False
223
224class DecimalTest(unittest.TestCase):
225    """Class which tests the Decimal class against the test cases.
226
227    Changed for unittest.
228    """
229    def setUp(self):
230        self.context = Context()
231        self.ignore_list = ['#']
232        # Basically, a # means return NaN InvalidOperation.
233        # Different from a sNaN in trim
234
235        self.ChangeDict = {'precision' : self.change_precision,
236                      'rounding' : self.change_rounding_method,
237                      'maxexponent' : self.change_max_exponent,
238                      'minexponent' : self.change_min_exponent,
239                      'clamp' : self.change_clamp}
240
241    def eval_file(self, file):
242        global skip_expected
243        if skip_expected:
244            raise unittest.SkipTest
245            return
246        with open(file) as f:
247            for line in f:
248                line = line.replace('\r\n', '').replace('\n', '')
249                #print line
250                try:
251                    t = self.eval_line(line)
252                except DecimalException, exception:
253                    #Exception raised where there shoudn't have been one.
254                    self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
255
256        return
257
258    def eval_line(self, s):
259        if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
260            s = (s.split('->')[0] + '->' +
261                 s.split('->')[1].split('--')[0]).strip()
262        else:
263            s = s.split('--')[0].strip()
264
265        for ignore in self.ignore_list:
266            if s.find(ignore) >= 0:
267                #print s.split()[0], 'NotImplemented--', ignore
268                return
269        if not s:
270            return
271        elif ':' in s:
272            return self.eval_directive(s)
273        else:
274            return self.eval_equation(s)
275
276    def eval_directive(self, s):
277        funct, value = map(lambda x: x.strip().lower(), s.split(':'))
278        if funct == 'rounding':
279            value = RoundingDict[value]
280        else:
281            try:
282                value = int(value)
283            except ValueError:
284                pass
285
286        funct = self.ChangeDict.get(funct, Nonfunction)
287        funct(value)
288
289    def eval_equation(self, s):
290        #global DEFAULT_PRECISION
291        #print DEFAULT_PRECISION
292
293        if not TEST_ALL and random.random() < 0.90:
294            return
295
296        try:
297            Sides = s.split('->')
298            L = Sides[0].strip().split()
299            id = L[0]
300            if DEBUG:
301                print "Test ", id,
302            funct = L[1].lower()
303            valstemp = L[2:]
304            L = Sides[1].strip().split()
305            ans = L[0]
306            exceptions = L[1:]
307        except (TypeError, AttributeError, IndexError):
308            raise InvalidOperation
309        def FixQuotes(val):
310            val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
311            val = val.replace("'", '').replace('"', '')
312            val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
313            return val
314
315        if id in skipped_test_ids:
316            return
317
318        fname = nameAdapter.get(funct, funct)
319        if fname == 'rescale':
320            return
321        funct = getattr(self.context, fname)
322
323
324        vals = []
325        conglomerate = ''
326        quote = 0
327        theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
328        # XXX STATUS CASES
329        if status_cases.has_key(id):
330            t = status_cases[id]
331            theirexceptions = t[0]
332
333        for exception in Signals:
334            self.context.traps[exception] = 1 #Catch these bugs...
335        for exception in theirexceptions:
336            self.context.traps[exception] = 0
337        for i, val in enumerate(valstemp):
338            if val.count("'") % 2 == 1:
339                quote = 1 - quote
340            if quote:
341                conglomerate = conglomerate + ' ' + val
342                continue
343            else:
344                val = conglomerate + val
345                conglomerate = ''
346            v = FixQuotes(val)
347            if fname in ('to_sci_string', 'to_eng_string'):
348                if EXTENDEDERRORTEST:
349                    for error in theirexceptions:
350                        self.context.traps[error] = 1
351                        try:
352                            funct(self.context.create_decimal(v))
353                        except error:
354                            pass
355                        except Signals, e:
356                            self.fail("Raised %s in %s when %s disabled" % \
357                                      (e, s, error))
358                        else:
359                            self.fail("Did not raise %s in %s" % (error, s))
360                        self.context.traps[error] = 0
361                v = self.context.create_decimal(v)
362            else:
363                # 32-bit version has limits +-425000000
364                savetraps = self.context._traps
365                self.context._traps = 0
366                vv = v
367                v = Decimal(vv, self.context)
368                if self.context._flags & 0x100: # MPD_Invalid_operation
369                    v = readcontext.create_decimal(vv)
370                    self.context._flags = 0
371                self.context._traps = savetraps
372            vals.append(v)
373
374        ans = FixQuotes(ans)
375
376        # XXX: Shortcuts, disagreements between cdecimal and decimal
377        if id in disagree:
378            return
379        if fname == 'power' and len(vals) == 3:
380            # name is different
381            fname = 'powmod'
382            funct = getattr(self.context, fname)
383
384        # skip tests that are related to bounds imposed in the decNumber
385        # reference implementation
386        if fname in decNumberRestricted:
387            if fname == 'power':
388                if not (vals[1].is_integer() and
389                        -1999999997 <= vals[1] <= 999999999):
390                    if outside_decNumber_bounds(vals[0], self.context) or \
391                            outside_decNumber_bounds(vals[1], self.context):
392                        #print "Skipping test %s" % s
393                        return
394            else:
395                if outside_decNumber_bounds(vals[0], self.context):
396                    #print "Skipping test %s" % s
397                    return
398
399
400        if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
401            for error in theirexceptions:
402                self.context.traps[error] = 1
403                try:
404                    funct(*vals)
405                except error:
406                    pass
407                except Signals, e:
408                    self.fail("Raised %s in %s when %s disabled" % \
409                              (e, s, error))
410                else:
411                    self.fail("Did not raise %s in %s" % (error, s))
412                self.context.traps[error] = 0
413        if DEBUG:
414            print "--", self.context
415        try:
416            result = str(funct(*vals))
417            if fname in LOGICAL_FUNCTIONS:
418                result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
419        except Signals, error:
420            self.fail("Raised %s in %s" % (error, s))
421        except: #Catch any error long enough to state the test case.
422            print "ERROR:", s
423            raise
424
425        myexceptions = self.getexceptions()
426        self.context.clear_flags()
427
428        myexceptions.sort()
429        theirexceptions.sort()
430
431        # XXX SKIPS
432        if skip_cases.has_key(id):
433            t = skip_cases[id]
434            self.assertTrue(result == t[0] and ans == t[1])
435        else:
436            self.assertEqual(result, ans,
437                             'Incorrect answer for ' + s + ' -- got ' + result)
438
439        self.assertEqual(myexceptions, theirexceptions,
440              'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
441        return
442
443    def getexceptions(self):
444        return [e for e in Signals if self.context.flags[e]]
445
446    def change_precision(self, prec):
447        if HAVE_CONFIG_64:
448            self.context.prec = prec
449        else:
450            self.context.unsafe_setprec(prec)
451    def change_rounding_method(self, rounding):
452        self.context.rounding = rounding
453    def change_min_exponent(self, exp):
454        if HAVE_CONFIG_64:
455            self.context.Emin = exp
456        else:
457            self.context.unsafe_setemin(exp)
458    def change_max_exponent(self, exp):
459        if HAVE_CONFIG_64:
460            self.context.Emax = exp
461        else:
462            self.context.unsafe_setemax(exp)
463    def change_clamp(self, clamp):
464        self.context._clamp = clamp
465
466
467
468# The following classes test the behaviour of Decimal according to PEP 327
469
470class DecimalExplicitConstructionTest(unittest.TestCase):
471    '''Unit tests for Explicit Construction cases of Decimal.'''
472
473    def test_explicit_empty(self):
474        self.assertEqual(Decimal(), Decimal("0"))
475
476    def test_explicit_from_None(self):
477        self.assertRaises(TypeError, Decimal, None)
478
479    def test_explicit_from_int(self):
480
481        #positive
482        d = Decimal(45)
483        self.assertEqual(str(d), '45')
484
485        #very large positive
486        d = Decimal(500000123)
487        self.assertEqual(str(d), '500000123')
488
489        #negative
490        d = Decimal(-45)
491        self.assertEqual(str(d), '-45')
492
493        #zero
494        d = Decimal(0)
495        self.assertEqual(str(d), '0')
496
497    def test_explicit_from_string(self):
498
499        #empty
500        self.assertEqual(str(Decimal('')), 'NaN')
501
502        #int
503        self.assertEqual(str(Decimal('45')), '45')
504
505        #float
506        self.assertEqual(str(Decimal('45.34')), '45.34')
507
508        #engineer notation
509        self.assertEqual(str(Decimal('45e2')), '4.5E+3')
510
511        #just not a number
512        self.assertEqual(str(Decimal('ugly')), 'NaN')
513
514        #leading and trailing whitespace permitted
515        self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
516        self.assertEqual(str(Decimal('  -7.89')), '-7.89')
517
518        #unicode strings should be permitted
519        self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
520        self.assertEqual(str(Decimal(u'45')), '45')
521        self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
522        self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
523
524    def test_explicit_from_tuples(self):
525
526        #zero
527        d = Decimal( (0, (0,), 0) )
528        self.assertEqual(str(d), '0')
529
530        #int
531        d = Decimal( (1, (4, 5), 0) )
532        self.assertEqual(str(d), '-45')
533
534        #float
535        d = Decimal( (0, (4, 5, 3, 4), -2) )
536        self.assertEqual(str(d), '45.34')
537
538        #weird
539        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
540        self.assertEqual(str(d), '-4.34913534E-17')
541
542        #wrong number of items
543        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
544
545        #bad sign
546        self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
547        self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
548        self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
549
550        #bad exp
551        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
552        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
553        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
554
555        #bad coefficients
556        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
557        self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
558        self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
559        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
560
561    def test_explicit_from_Decimal(self):
562
563        #positive
564        d = Decimal(45)
565        e = Decimal(d)
566        self.assertEqual(str(e), '45')
567        # XXX cdecimal has behaviour of int()
568        # self.assertNotEqual(id(d), id(e))
569        self.assertEqual(id(d), id(e))
570
571        #very large positive
572        d = Decimal(500000123)
573        e = Decimal(d)
574        self.assertEqual(str(e), '500000123')
575        self.assertEqual(id(d), id(e))
576
577        #negative
578        d = Decimal(-45)
579        e = Decimal(d)
580        self.assertEqual(str(e), '-45')
581        self.assertEqual(id(d), id(e))
582
583        #zero
584        d = Decimal(0)
585        e = Decimal(d)
586        self.assertEqual(str(e), '0')
587        self.assertEqual(id(d), id(e))
588
589    def test_explicit_from_float(self):
590        if not float.__getformat__("double").startswith("IEEE"):
591            return
592        if HAVE_CDECIMAL:
593            if py_minor <= 6:
594                with localcontext() as c:
595                    # TypeError in 2.6
596                    c.clear_flags()
597                    self.assertRaises(TypeError, Decimal, 7.5)
598                    self.assertFalse(c.flags[FloatOperation])
599
600                    c.traps[FloatOperation] = True
601                    self.assertRaises(TypeError, Decimal, 7.5)
602                    self.assertFalse(c.flags[FloatOperation])
603                    return
604            else:
605                with localcontext() as c:
606                    c.clear_flags()
607                    self.assertEqual(Decimal(7.5), 7.5)
608                    self.assertTrue(c.flags[FloatOperation])
609
610                    c.traps[FloatOperation] = True
611                    self.assertRaises(FloatOperation, Decimal, 7.5)
612                    self.assertTrue(c.flags[FloatOperation])
613
614        r = Decimal(0.1)
615        self.assertEqual(type(r), Decimal)
616        self.assertEqual(str(r),
617                '0.1000000000000000055511151231257827021181583404541015625')
618        self.assertTrue(Decimal(float('nan')).is_qnan())
619        self.assertTrue(Decimal(float('inf')).is_infinite())
620        self.assertTrue(Decimal(float('-inf')).is_infinite())
621        self.assertEqual(str(Decimal(float('nan'))),
622                         str(Decimal('NaN')))
623        self.assertEqual(str(Decimal(float('inf'))),
624                         str(Decimal('Infinity')))
625        self.assertEqual(str(Decimal(float('-inf'))),
626                         str(Decimal('-Infinity')))
627        self.assertEqual(str(Decimal(float('-0.0'))),
628                         str(Decimal('-0')))
629        for i in range(200):
630            x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
631            self.assertEqual(x, float(Decimal(x))) # roundtrip
632
633    def test_explicit_context_create_decimal(self):
634
635        nc = copy.copy(getcontext())
636        nc.prec = 3
637
638        # empty
639        d = Decimal()
640        self.assertEqual(str(d), '0')
641        d = nc.create_decimal()
642        self.assertEqual(str(d), '0')
643
644        # from None
645        self.assertRaises(TypeError, nc.create_decimal, None)
646
647        # from int
648        d = nc.create_decimal(456)
649        self.assertTrue(isinstance(d, Decimal))
650        self.assertEqual(nc.create_decimal(45678),
651                         nc.create_decimal('457E+2'))
652
653        # from string
654        d = Decimal('456789')
655        self.assertEqual(str(d), '456789')
656        d = nc.create_decimal('456789')
657        self.assertEqual(str(d), '4.57E+5')
658        # leading and trailing whitespace should result in a NaN;
659        # spaces are already checked in Cowlishaw's test-suite, so
660        # here we just check that a trailing newline results in a NaN
661        self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
662
663        # from tuples
664        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
665        self.assertEqual(str(d), '-4.34913534E-17')
666        d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
667        self.assertEqual(str(d), '-4.35E-17')
668
669        # from Decimal
670        prevdec = Decimal(500000123)
671        d = Decimal(prevdec)
672        self.assertEqual(str(d), '500000123')
673        d = nc.create_decimal(prevdec)
674        self.assertEqual(str(d), '5.00E+8')
675
676    def test_unicode_digits(self):
677        test_values = {
678            u'\uff11': '1',
679            u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
680            u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
681            }
682        for input, expected in test_values.items():
683            self.assertEqual(str(Decimal(input)), expected)
684
685
686class DecimalImplicitConstructionTest(unittest.TestCase):
687    '''Unit tests for Implicit Construction cases of Decimal.'''
688
689    def test_implicit_from_None(self):
690        self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
691
692    def test_implicit_from_int(self):
693        #normal
694        self.assertEqual(str(Decimal(5) + 45), '50')
695        #exceeding precision
696        self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
697
698    def test_implicit_from_string(self):
699        self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
700
701    def test_implicit_from_float(self):
702        self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
703
704    def test_implicit_from_Decimal(self):
705        self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
706
707    def test_rop(self):
708        # Allow other classes to be trained to interact with Decimals
709        class E:
710            def __divmod__(self, other):
711                return 'divmod ' + str(other)
712            def __rdivmod__(self, other):
713                return str(other) + ' rdivmod'
714            def __lt__(self, other):
715                return 'lt ' + str(other)
716            def __gt__(self, other):
717                return 'gt ' + str(other)
718            def __le__(self, other):
719                return 'le ' + str(other)
720            def __ge__(self, other):
721                return 'ge ' + str(other)
722            def __eq__(self, other):
723                return 'eq ' + str(other)
724            def __ne__(self, other):
725                return 'ne ' + str(other)
726
727        self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
728        self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
729        self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
730        self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
731        self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
732        self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
733        self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
734        self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
735
736        # insert operator methods and then exercise them
737        oplist = [
738            ('+', '__add__', '__radd__'),
739            ('-', '__sub__', '__rsub__'),
740            ('*', '__mul__', '__rmul__'),
741            ('%', '__mod__', '__rmod__'),
742            ('//', '__floordiv__', '__rfloordiv__'),
743            ('**', '__pow__', '__rpow__')
744        ]
745        if 1/2 == 0:
746            # testing with classic division, so add __div__
747            oplist.append(('/', '__div__', '__rdiv__'))
748        else:
749            # testing with -Qnew, so add __truediv__
750            oplist.append(('/', '__truediv__', '__rtruediv__'))
751
752        for sym, lop, rop in oplist:
753            setattr(E, lop, lambda self, other: 'str' + lop + str(other))
754            setattr(E, rop, lambda self, other: str(other) + rop + 'str')
755            self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
756                             'str' + lop + '10')
757            self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
758                             '10' + rop + 'str')
759
760class DecimalArithmeticOperatorsTest(unittest.TestCase):
761    '''Unit tests for all arithmetic operators, binary and unary.'''
762
763    def test_addition(self):
764
765        d1 = Decimal('-11.1')
766        d2 = Decimal('22.2')
767
768        #two Decimals
769        self.assertEqual(d1+d2, Decimal('11.1'))
770        self.assertEqual(d2+d1, Decimal('11.1'))
771
772        #with other type, left
773        c = d1 + 5
774        self.assertEqual(c, Decimal('-6.1'))
775        self.assertEqual(type(c), type(d1))
776
777        #with other type, right
778        c = 5 + d1
779        self.assertEqual(c, Decimal('-6.1'))
780        self.assertEqual(type(c), type(d1))
781
782        #inline with decimal
783        d1 += d2
784        self.assertEqual(d1, Decimal('11.1'))
785
786        #inline with other type
787        d1 += 5
788        self.assertEqual(d1, Decimal('16.1'))
789
790    def test_subtraction(self):
791
792        d1 = Decimal('-11.1')
793        d2 = Decimal('22.2')
794
795        #two Decimals
796        self.assertEqual(d1-d2, Decimal('-33.3'))
797        self.assertEqual(d2-d1, Decimal('33.3'))
798
799        #with other type, left
800        c = d1 - 5
801        self.assertEqual(c, Decimal('-16.1'))
802        self.assertEqual(type(c), type(d1))
803
804        #with other type, right
805        c = 5 - d1
806        self.assertEqual(c, Decimal('16.1'))
807        self.assertEqual(type(c), type(d1))
808
809        #inline with decimal
810        d1 -= d2
811        self.assertEqual(d1, Decimal('-33.3'))
812
813        #inline with other type
814        d1 -= 5
815        self.assertEqual(d1, Decimal('-38.3'))
816
817    def test_multiplication(self):
818
819        d1 = Decimal('-5')
820        d2 = Decimal('3')
821
822        #two Decimals
823        self.assertEqual(d1*d2, Decimal('-15'))
824        self.assertEqual(d2*d1, Decimal('-15'))
825
826        #with other type, left
827        c = d1 * 5
828        self.assertEqual(c, Decimal('-25'))
829        self.assertEqual(type(c), type(d1))
830
831        #with other type, right
832        c = 5 * d1
833        self.assertEqual(c, Decimal('-25'))
834        self.assertEqual(type(c), type(d1))
835
836        #inline with decimal
837        d1 *= d2
838        self.assertEqual(d1, Decimal('-15'))
839
840        #inline with other type
841        d1 *= 5
842        self.assertEqual(d1, Decimal('-75'))
843
844    def test_division(self):
845
846        d1 = Decimal('-5')
847        d2 = Decimal('2')
848
849        #two Decimals
850        self.assertEqual(d1/d2, Decimal('-2.5'))
851        self.assertEqual(d2/d1, Decimal('-0.4'))
852
853        #with other type, left
854        c = d1 / 4
855        self.assertEqual(c, Decimal('-1.25'))
856        self.assertEqual(type(c), type(d1))
857
858        #with other type, right
859        c = 4 / d1
860        self.assertEqual(c, Decimal('-0.8'))
861        self.assertEqual(type(c), type(d1))
862
863        #inline with decimal
864        d1 /= d2
865        self.assertEqual(d1, Decimal('-2.5'))
866
867        #inline with other type
868        d1 /= 4
869        self.assertEqual(d1, Decimal('-0.625'))
870
871    def test_floor_division(self):
872
873        d1 = Decimal('5')
874        d2 = Decimal('2')
875
876        #two Decimals
877        self.assertEqual(d1//d2, Decimal('2'))
878        self.assertEqual(d2//d1, Decimal('0'))
879
880        #with other type, left
881        c = d1 // 4
882        self.assertEqual(c, Decimal('1'))
883        self.assertEqual(type(c), type(d1))
884
885        #with other type, right
886        c = 7 // d1
887        self.assertEqual(c, Decimal('1'))
888        self.assertEqual(type(c), type(d1))
889
890        #inline with decimal
891        d1 //= d2
892        self.assertEqual(d1, Decimal('2'))
893
894        #inline with other type
895        d1 //= 2
896        self.assertEqual(d1, Decimal('1'))
897
898    def test_powering(self):
899
900        d1 = Decimal('5')
901        d2 = Decimal('2')
902
903        #two Decimals
904        self.assertEqual(d1**d2, Decimal('25'))
905        self.assertEqual(d2**d1, Decimal('32'))
906
907        #with other type, left
908        c = d1 ** 4
909        self.assertEqual(c, Decimal('625'))
910        self.assertEqual(type(c), type(d1))
911
912        #with other type, right
913        c = 7 ** d1
914        self.assertEqual(c, Decimal('16807'))
915        self.assertEqual(type(c), type(d1))
916
917        #inline with decimal
918        d1 **= d2
919        self.assertEqual(d1, Decimal('25'))
920
921        #inline with other type
922        d1 **= 4
923        self.assertEqual(d1, Decimal('390625'))
924
925    def test_module(self):
926
927        d1 = Decimal('5')
928        d2 = Decimal('2')
929
930        #two Decimals
931        self.assertEqual(d1%d2, Decimal('1'))
932        self.assertEqual(d2%d1, Decimal('2'))
933
934        #with other type, left
935        c = d1 % 4
936        self.assertEqual(c, Decimal('1'))
937        self.assertEqual(type(c), type(d1))
938
939        #with other type, right
940        c = 7 % d1
941        self.assertEqual(c, Decimal('2'))
942        self.assertEqual(type(c), type(d1))
943
944        #inline with decimal
945        d1 %= d2
946        self.assertEqual(d1, Decimal('1'))
947
948        #inline with other type
949        d1 %= 4
950        self.assertEqual(d1, Decimal('1'))
951
952    def test_floor_div_module(self):
953
954        d1 = Decimal('5')
955        d2 = Decimal('2')
956
957        #two Decimals
958        (p, q) = divmod(d1, d2)
959        self.assertEqual(p, Decimal('2'))
960        self.assertEqual(q, Decimal('1'))
961        self.assertEqual(type(p), type(d1))
962        self.assertEqual(type(q), type(d1))
963
964        #with other type, left
965        (p, q) = divmod(d1, 4)
966        self.assertEqual(p, Decimal('1'))
967        self.assertEqual(q, Decimal('1'))
968        self.assertEqual(type(p), type(d1))
969        self.assertEqual(type(q), type(d1))
970
971        #with other type, right
972        (p, q) = divmod(7, d1)
973        self.assertEqual(p, Decimal('1'))
974        self.assertEqual(q, Decimal('2'))
975        self.assertEqual(type(p), type(d1))
976        self.assertEqual(type(q), type(d1))
977
978    def test_unary_operators(self):
979        self.assertEqual(+Decimal(45), Decimal(+45))           #  +
980        self.assertEqual(-Decimal(45), Decimal(-45))           #  -
981        self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
982
983    def test_nan_comparisons(self):
984        n = Decimal('NaN')
985        s = Decimal('sNaN')
986        i = Decimal('Inf')
987        f = Decimal('2')
988        for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
989                     (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
990            self.assertTrue(x != y)
991            self.assertTrue(not (x == y))
992            self.assertTrue(not (x < y))
993            self.assertTrue(not (x <= y))
994            self.assertTrue(not (x > y))
995            self.assertTrue(not (x >= y))
996
997    def test_copy_sign(self):
998        d = Decimal(1).copy_sign(Decimal(-2))
999
1000        self.assertEqual(Decimal(1).copy_sign(-2), d)
1001        self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1002
1003# The following are two functions used to test threading in the next class
1004
1005def thfunc1(cls):
1006    d1 = Decimal(1)
1007    d3 = Decimal(3)
1008    test1 = d1/d3
1009
1010    cls.finish1.set()
1011    cls.synchro.wait()
1012
1013    test2 = d1/d3
1014    with localcontext() as c2:
1015        cls.assertTrue(c2.flags[Inexact])
1016        cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1017        cls.assertTrue(c2.flags[DivisionByZero])
1018        with localcontext() as c3:
1019            cls.assertTrue(c3.flags[Inexact])
1020            cls.assertTrue(c3.flags[DivisionByZero])
1021            cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1022            cls.assertTrue(c3.flags[InvalidOperation])
1023            del c3
1024        cls.assertFalse(c2.flags[InvalidOperation])
1025        del c2
1026
1027    cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1028    cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1029
1030    c1 = getcontext()
1031    cls.assertTrue(c1.flags[Inexact])
1032    for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1033        cls.assertFalse(c1.flags[sig])
1034    return
1035
1036def thfunc2(cls):
1037    d1 = Decimal(1)
1038    d3 = Decimal(3)
1039    test1 = d1/d3
1040
1041    thiscontext = getcontext()
1042    thiscontext.prec = 18
1043    test2 = d1/d3
1044
1045    with localcontext() as c2:
1046        cls.assertTrue(c2.flags[Inexact])
1047        cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1048        cls.assertTrue(c2.flags[Overflow])
1049        with localcontext(thiscontext) as c3:
1050            cls.assertTrue(c3.flags[Inexact])
1051            cls.assertFalse(c3.flags[Overflow])
1052            c3.traps[Underflow] = True
1053            cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1054            cls.assertTrue(c3.flags[Underflow])
1055            del c3
1056        cls.assertFalse(c2.flags[Underflow])
1057        cls.assertFalse(c2.traps[Underflow])
1058        del c2
1059
1060    cls.synchro.set()
1061    cls.finish2.set()
1062
1063    cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1064    cls.assertEqual(test2, Decimal('0.333333333333333333'))
1065
1066    cls.assertFalse(thiscontext.traps[Underflow])
1067    cls.assertTrue(thiscontext.flags[Inexact])
1068    for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1069        cls.assertFalse(thiscontext.flags[sig])
1070    return
1071
1072class DecimalUseOfContextTest(unittest.TestCase):
1073    '''Unit tests for Use of Context cases in Decimal.'''
1074
1075    # Take care executing this test from IDLE, there's an issue in threading
1076    # that hangs IDLE and I couldn't find it
1077
1078    def test_threading(self):
1079        if threading is None:
1080            return
1081        if not HAVE_THREADS:
1082            return
1083        # Test the "threading isolation" of a Context. Also test changing
1084        # the DefaultContext, which acts as a template for the thread-local
1085        # contexts.
1086        save_prec = DefaultContext.prec
1087        save_emax = DefaultContext.Emax
1088        save_emin = DefaultContext.Emin
1089        DefaultContext.prec = 24
1090        DefaultContext.Emax = 425000000
1091        DefaultContext.Emin = -425000000
1092
1093        self.synchro = threading.Event()
1094        self.finish1 = threading.Event()
1095        self.finish2 = threading.Event()
1096
1097        th1 = threading.Thread(target=thfunc1, args=(self,))
1098        th2 = threading.Thread(target=thfunc2, args=(self,))
1099
1100        th1.start()
1101        th2.start()
1102
1103        self.finish1.wait()
1104        self.finish2.wait()
1105
1106        for sig in (Inexact, Overflow, Underflow, DivisionByZero,
1107                    InvalidOperation):
1108            self.assertFalse(DefaultContext.flags[sig])
1109
1110        DefaultContext.prec = save_prec
1111        DefaultContext.Emax = save_emax
1112        DefaultContext.Emin = save_emin
1113        return
1114
1115class DecimalUsabilityTest(unittest.TestCase):
1116    '''Unit tests for Usability cases of Decimal.'''
1117
1118    def test_comparison_operators(self):
1119
1120        da = Decimal('23.42')
1121        db = Decimal('23.42')
1122        dc = Decimal('45')
1123
1124        #two Decimals
1125        self.assertTrue(dc > da)
1126        self.assertTrue(dc >= da)
1127        self.assertTrue(da < dc)
1128        self.assertTrue(da <= dc)
1129        self.assertTrue(da == db)
1130        self.assertTrue(da != dc)
1131        self.assertTrue(da <= db)
1132        self.assertTrue(da >= db)
1133        self.assertEqual(cmp(dc,da), 1)
1134        self.assertEqual(cmp(da,dc), -1)
1135        self.assertEqual(cmp(da,db), 0)
1136
1137        #a Decimal and an int
1138        self.assertTrue(dc > 23)
1139        self.assertTrue(23 < dc)
1140        self.assertTrue(dc == 45)
1141        self.assertEqual(cmp(dc,23), 1)
1142        self.assertEqual(cmp(23,dc), -1)
1143        self.assertEqual(cmp(dc,45), 0)
1144
1145        #a Decimal and uncomparable
1146        self.assertNotEqual(da, 'ugly')
1147        self.assertNotEqual(da, 32.7)
1148        self.assertNotEqual(da, object())
1149        self.assertNotEqual(da, object)
1150
1151        # sortable
1152        a = map(Decimal, xrange(100))
1153        b =  a[:]
1154        random.shuffle(a)
1155        a.sort()
1156        self.assertEqual(a, b)
1157
1158        # with None
1159        self.assertFalse(Decimal(1) < None)
1160        self.assertTrue(Decimal(1) > None)
1161
1162    def test_decimal_float_comparison(self):
1163        def assert_attr(a, b, attr, context, signal=None):
1164            context.clear_flags()
1165            f = getattr(a, attr)
1166            if HAVE_CDECIMAL:
1167                if signal == FloatOperation:
1168                    self.assertRaises(signal, f, b)
1169                elif py_minor <= 6:
1170                    self.assertTrue(f(b) is NotImplemented)
1171                else:
1172                    self.assertTrue(f(b) is True)
1173                self.assertTrue(context.flags[FloatOperation])
1174            else:
1175                self.assertTrue(f(b) is True)
1176
1177        small_d = Decimal('0.25')
1178        big_d = Decimal('3.0')
1179        small_f = 0.25
1180        big_f = 3.0
1181
1182        zero_d = Decimal('0.0')
1183        neg_zero_d = Decimal('-0.0')
1184        zero_f = 0.0
1185        neg_zero_f = -0.0
1186
1187        inf_d = Decimal('Infinity')
1188        neg_inf_d = Decimal('-Infinity')
1189        inf_f = float('inf')
1190        neg_inf_f = float('-inf')
1191
1192        def doit(c, signal=None):
1193            # Order
1194            for attr in '__lt__', '__le__':
1195                assert_attr(small_d, big_f, attr, c, signal)
1196
1197            for attr in '__gt__', '__ge__':
1198                assert_attr(big_d, small_f, attr, c, signal)
1199
1200            # Equality
1201            assert_attr(small_d, small_f, '__eq__', c, None)
1202
1203            assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
1204            assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
1205
1206            assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
1207            assert_attr(zero_d, zero_f, '__eq__', c, None)
1208
1209            assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
1210            assert_attr(inf_d, inf_f, '__eq__', c, None)
1211
1212            # Inequality
1213            assert_attr(small_d, big_f, '__ne__', c, None)
1214
1215            assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
1216
1217            assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
1218            assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
1219
1220            assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
1221
1222        def test_containers(c, signal):
1223           c.clear_flags()
1224           s = set([100.0, Decimal('100.0')])
1225           expected_len = 2 if py_minor <= 6 else 1
1226           self.assertEqual(len(s), expected_len)
1227           self.assertTrue(c.flags[FloatOperation])
1228
1229           c.clear_flags()
1230           if signal:
1231               self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
1232           else:
1233               s = sorted([10.0, Decimal('10.0')])
1234           self.assertTrue(c.flags[FloatOperation])
1235
1236           c.clear_flags()
1237           b = 10.0 in [Decimal('10.0'), 1.0]
1238           self.assertTrue(c.flags[FloatOperation])
1239
1240           c.clear_flags()
1241           b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
1242           self.assertTrue(c.flags[FloatOperation])
1243
1244        if HAVE_CDECIMAL:
1245            nc = Context()
1246            if py_minor <= 6:
1247                with localcontext(nc) as c:
1248                    self.assertFalse(c.traps[FloatOperation])
1249                    doit(c, signal=None)
1250                    test_containers(c, None)
1251
1252                    c.traps[FloatOperation] = True
1253                    doit(c, signal=FloatOperation)
1254                    test_containers(c, FloatOperation)
1255            else:
1256                with localcontext(nc) as c:
1257                    # In 3.2 the FloatOperation signal is off by default.
1258                    self.assertFalse(c.traps[FloatOperation])
1259                    doit(c, signal=None)
1260                    test_containers(c, None)
1261
1262                    c.traps[FloatOperation] = True
1263                    doit(c, signal=FloatOperation)
1264                    test_containers(c, FloatOperation)
1265        else:
1266            # decimal.py does not have the FloatOperation signal.
1267            nc = Context()
1268            with localcontext(nc) as c:
1269                doit(c, signal=False)
1270
1271    def test_copy_and_deepcopy_methods(self):
1272        d = Decimal('43.24')
1273        c = copy.copy(d)
1274        self.assertEqual(id(c), id(d))
1275        dc = copy.deepcopy(d)
1276        self.assertEqual(id(dc), id(d))
1277
1278    def test_hash_method(self):
1279        def hashit(d):
1280            a = hash(d)
1281            b = d.__hash__()
1282            self.assertEqual(a, b)
1283            return a
1284
1285        #just that it's hashable
1286        hashit(Decimal(23))
1287        hashit(Decimal('Infinity'))
1288        hashit(Decimal('-Infinity'))
1289        if py_minor >= 7:
1290            hashit(Decimal('nan123'))
1291            hashit(Decimal('-NaN'))
1292
1293        test_values = [Decimal(sign*(2**m + n))
1294                       for m in [0, 14, 15, 16, 17, 30, 31,
1295                                 32, 33, 61, 62, 63, 64, 65, 66]
1296                       for n in range(-10, 10)
1297                       for sign in [-1, 1]]
1298        test_values.extend([
1299                Decimal("-1"), # ==> -2
1300                Decimal("-0"), # zeros
1301                Decimal("0.00"),
1302                Decimal("-0.000"),
1303                Decimal("0E10"),
1304                Decimal("-0E12"),
1305                Decimal("10.0"), # negative exponent
1306                Decimal("-23.00000"),
1307                Decimal("1230E100"), # positive exponent
1308                Decimal("-4.5678E50"),
1309                # a value for which hash(n) != hash(n % (2**64-1))
1310                # in Python pre-2.6
1311                Decimal(2**64 + 2**32 - 1),
1312                # selection of values which fail with the old (before
1313                # version 2.6) long.__hash__
1314                Decimal("1.634E100"),
1315                Decimal("90.697E100"),
1316                Decimal("188.83E100"),
1317                Decimal("1652.9E100"),
1318                Decimal("56531E100"),
1319                ])
1320
1321        # check that hash(d) == hash(int(d)) for integral values
1322        for value in test_values:
1323            self.assertEqual(hashit(value), hashit(int(value)))
1324
1325        #the same hash that to an int
1326        self.assertEqual(hashit(Decimal(23)), hashit(23))
1327        self.assertRaises(TypeError, hash, Decimal('sNaN'))
1328        self.assertTrue(hashit(Decimal('Inf')))
1329        self.assertTrue(hashit(Decimal('-Inf')))
1330
1331        if py_minor >= 7:
1332            # check that the hashes of a Decimal float match when they
1333            # represent exactly the same values
1334            test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1335                            '34.0', '2.5', '112390.625', '-0.515625']
1336            for s in test_strings:
1337                f = float(s)
1338                d = Decimal(s)
1339                self.assertEqual(hashit(f), hashit(d))
1340
1341        # check that the value of the hash doesn't depend on the
1342        # current context (issue #1757)
1343        c = getcontext()
1344        old_precision = c.prec
1345        x = Decimal("123456789.1")
1346
1347        c.prec = 6
1348        h1 = hashit(x)
1349        c.prec = 10
1350        h2 = hashit(x)
1351        c.prec = 16
1352        h3 = hashit(x)
1353
1354        self.assertEqual(h1, h2)
1355        self.assertEqual(h1, h3)
1356        c.prec = old_precision
1357
1358    def test_min_and_max_methods(self):
1359
1360        d1 = Decimal('15.32')
1361        d2 = Decimal('28.5')
1362        l1 = 15
1363        l2 = 28
1364
1365        #between Decimals
1366        self.assertTrue(min(d1,d2) is d1)
1367        self.assertTrue(min(d2,d1) is d1)
1368        self.assertTrue(max(d1,d2) is d2)
1369        self.assertTrue(max(d2,d1) is d2)
1370
1371        #between Decimal and long
1372        self.assertTrue(min(d1,l2) is d1)
1373        self.assertTrue(min(l2,d1) is d1)
1374        self.assertTrue(max(l1,d2) is d2)
1375        self.assertTrue(max(d2,l1) is d2)
1376
1377    def test_as_nonzero(self):
1378        #as false
1379        self.assertFalse(Decimal(0))
1380        #as true
1381        self.assertTrue(Decimal('0.372'))
1382
1383    def test_tostring_methods(self):
1384        #Test str and repr methods.
1385
1386        d = Decimal('15.32')
1387        self.assertEqual(str(d), '15.32')               # str
1388        self.assertEqual(repr(d), "Decimal('15.32')")   # repr
1389
1390        # result type of string methods should be str, not unicode
1391        unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1392                          u'-0.0E100', u'-NaN001', u'-Inf']
1393
1394        for u in unicode_inputs:
1395            d = Decimal(u)
1396            self.assertEqual(type(str(d)), str)
1397            self.assertEqual(type(repr(d)), str)
1398            self.assertEqual(type(d.to_eng_string()), str)
1399
1400    def test_tonum_methods(self):
1401        #Test float, int and long methods.
1402
1403        d1 = Decimal('66')
1404        d2 = Decimal('15.32')
1405
1406        #int
1407        self.assertEqual(int(d1), 66)
1408        self.assertEqual(int(d2), 15)
1409
1410        #long
1411        self.assertEqual(long(d1), 66)
1412        self.assertEqual(long(d2), 15)
1413
1414        #float
1415        self.assertEqual(float(d1), 66)
1416        self.assertEqual(float(d2), 15.32)
1417
1418    def test_eval_round_trip(self):
1419
1420        #with zero
1421        d = Decimal( (0, (0,), 0) )
1422        self.assertEqual(d, eval(repr(d)))
1423
1424        #int
1425        d = Decimal( (1, (4, 5), 0) )
1426        self.assertEqual(d, eval(repr(d)))
1427
1428        #float
1429        d = Decimal( (0, (4, 5, 3, 4), -2) )
1430        self.assertEqual(d, eval(repr(d)))
1431
1432        #weird
1433        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1434        self.assertEqual(d, eval(repr(d)))
1435
1436    def test_as_tuple(self):
1437
1438        #with zero
1439        d = Decimal(0)
1440        self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1441
1442        #int
1443        d = Decimal(-45)
1444        self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1445
1446        #complicated string
1447        d = Decimal("-4.34913534E-17")
1448        self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1449
1450        # XXX empty tuple, like in the NaN case
1451        d = Decimal("Infinity")
1452        self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1453
1454        #leading zeros in coefficient should be stripped
1455        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1456        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1457        d = Decimal( (1, (0, 0, 0), 37) )
1458        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1459        d = Decimal( (1, (), 37) )
1460        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1461
1462        #leading zeros in NaN diagnostic info should be stripped
1463        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1464        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1465        d = Decimal( (1, (0, 0, 0), 'N') )
1466        self.assertEqual(d.as_tuple(), (1, (), 'N') )
1467        d = Decimal( (1, (), 'n') )
1468        self.assertEqual(d.as_tuple(), (1, (), 'n') )
1469
1470        # XXX coefficient in infinity should raise an error
1471        # d = Decimal( (0, (4, 5, 3, 4), 'F') )
1472        # self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1473        # d = Decimal( (1, (0, 2, 7, 1), 'F') )
1474        # self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1475
1476    def XXX_test_immutability_operations(self):
1477        # XXX Checked extensively in the library runtest.
1478        # Do operations and check that it didn't change change internal objects.
1479
1480        d1 = Decimal('-25e55')
1481        b1 = Decimal('-25e55')
1482        d2 = Decimal('33e+33')
1483        b2 = Decimal('33e+33')
1484
1485        def checkSameDec(operation, useOther=False):
1486            if useOther:
1487                eval("d1." + operation + "(d2)")
1488                self.assertEqual(d1._sign, b1._sign)
1489                self.assertEqual(d1._int, b1._int)
1490                self.assertEqual(d1._exp, b1._exp)
1491                self.assertEqual(d2._sign, b2._sign)
1492                self.assertEqual(d2._int, b2._int)
1493                self.assertEqual(d2._exp, b2._exp)
1494            else:
1495                eval("d1." + operation + "()")
1496                self.assertEqual(d1._sign, b1._sign)
1497                self.assertEqual(d1._int, b1._int)
1498                self.assertEqual(d1._exp, b1._exp)
1499            return
1500
1501        Decimal(d1)
1502        self.assertEqual(d1._sign, b1._sign)
1503        self.assertEqual(d1._int, b1._int)
1504        self.assertEqual(d1._exp, b1._exp)
1505
1506        checkSameDec("__abs__")
1507        checkSameDec("__add__", True)
1508        checkSameDec("__div__", True)
1509        checkSameDec("__divmod__", True)
1510        checkSameDec("__eq__", True)
1511        checkSameDec("__ne__", True)
1512        checkSameDec("__le__", True)
1513        checkSameDec("__lt__", True)
1514        checkSameDec("__ge__", True)
1515        checkSameDec("__gt__", True)
1516        checkSameDec("__float__")
1517        checkSameDec("__floordiv__", True)
1518        checkSameDec("__hash__")
1519        checkSameDec("__int__")
1520        checkSameDec("__trunc__")
1521        checkSameDec("__long__")
1522        checkSameDec("__mod__", True)
1523        checkSameDec("__mul__", True)
1524        checkSameDec("__neg__")
1525        checkSameDec("__nonzero__")
1526        checkSameDec("__pos__")
1527        checkSameDec("__pow__", True)
1528        checkSameDec("__radd__", True)
1529        checkSameDec("__rdiv__", True)
1530        checkSameDec("__rdivmod__", True)
1531        checkSameDec("__repr__")
1532        checkSameDec("__rfloordiv__", True)
1533        checkSameDec("__rmod__", True)
1534        checkSameDec("__rmul__", True)
1535        checkSameDec("__rpow__", True)
1536        checkSameDec("__rsub__", True)
1537        checkSameDec("__str__")
1538        checkSameDec("__sub__", True)
1539        checkSameDec("__truediv__", True)
1540        checkSameDec("adjusted")
1541        checkSameDec("as_tuple")
1542        checkSameDec("compare", True)
1543        checkSameDec("max", True)
1544        checkSameDec("min", True)
1545        checkSameDec("normalize")
1546        checkSameDec("quantize", True)
1547        checkSameDec("remainder_near", True)
1548        checkSameDec("same_quantum", True)
1549        checkSameDec("sqrt")
1550        checkSameDec("to_eng_string")
1551        checkSameDec("to_integral")
1552
1553    def test_subclassing(self):
1554        # Different behaviours when subclassing Decimal
1555
1556        class MyDecimal(Decimal):
1557            pass
1558
1559        d1 = MyDecimal(1)
1560        d2 = MyDecimal(2)
1561        d = d1 + d2
1562        self.assertTrue(type(d) is Decimal)
1563
1564        d = d1.max(d2)
1565        self.assertTrue(type(d) is Decimal)
1566
1567    def test_implicit_context(self):
1568        # Check results when context given implicitly.  (Issue 2478)
1569        c = getcontext()
1570        self.assertEqual(str(Decimal(0).sqrt()),
1571                         str(c.sqrt(Decimal(0))))
1572
1573    def test_conversions_from_int(self):
1574        # Check that methods taking a second Decimal argument will
1575        # always accept an integer in place of a Decimal.
1576        self.assertEqual(Decimal(4).compare(3),
1577                         Decimal(4).compare(Decimal(3)))
1578        self.assertEqual(Decimal(4).compare_signal(3),
1579                         Decimal(4).compare_signal(Decimal(3)))
1580        self.assertEqual(Decimal(4).compare_total(3),
1581                         Decimal(4).compare_total(Decimal(3)))
1582        self.assertEqual(Decimal(4).compare_total_mag(3),
1583                         Decimal(4).compare_total_mag(Decimal(3)))
1584        self.assertEqual(Decimal(10101).logical_and(1001),
1585                         Decimal(10101).logical_and(Decimal(1001)))
1586        self.assertEqual(Decimal(10101).logical_or(1001),
1587                         Decimal(10101).logical_or(Decimal(1001)))
1588        self.assertEqual(Decimal(10101).logical_xor(1001),
1589                         Decimal(10101).logical_xor(Decimal(1001)))
1590        self.assertEqual(Decimal(567).max(123),
1591                         Decimal(567).max(Decimal(123)))
1592        self.assertEqual(Decimal(567).max_mag(123),
1593                         Decimal(567).max_mag(Decimal(123)))
1594        self.assertEqual(Decimal(567).min(123),
1595                         Decimal(567).min(Decimal(123)))
1596        self.assertEqual(Decimal(567).min_mag(123),
1597                         Decimal(567).min_mag(Decimal(123)))
1598        self.assertEqual(Decimal(567).next_toward(123),
1599                         Decimal(567).next_toward(Decimal(123)))
1600        self.assertEqual(Decimal(1234).quantize(100),
1601                         Decimal(1234).quantize(Decimal(100)))
1602        self.assertEqual(Decimal(768).remainder_near(1234),
1603                         Decimal(768).remainder_near(Decimal(1234)))
1604        self.assertEqual(Decimal(123).rotate(1),
1605                         Decimal(123).rotate(Decimal(1)))
1606        self.assertEqual(Decimal(1234).same_quantum(1000),
1607                         Decimal(1234).same_quantum(Decimal(1000)))
1608        self.assertEqual(Decimal('9.123').scaleb(-100),
1609                         Decimal('9.123').scaleb(Decimal(-100)))
1610        self.assertEqual(Decimal(456).shift(-1),
1611                         Decimal(456).shift(Decimal(-1)))
1612
1613        self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1614                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1615        self.assertEqual(Decimal(-12).fma(45, 67),
1616                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1617        self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1618                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1619
1620class DecimalPythonAPItests(unittest.TestCase):
1621
1622    def test_pickle(self):
1623        d = Decimal('-3.141590000')
1624        p = pickle.dumps(d)
1625        e = pickle.loads(p)
1626        self.assertEqual(d, e)
1627
1628    def test_int(self):
1629        for x in range(-250, 250):
1630            s = '%0.2f' % (x / 100.0)
1631            # should work the same as for floats
1632            self.assertEqual(int(Decimal(s)), int(float(s)))
1633            # should work the same as to_integral in the ROUND_DOWN mode
1634            d = Decimal(s)
1635            r = d.to_integral(ROUND_DOWN)
1636            self.assertEqual(Decimal(int(d)), r)
1637
1638        self.assertRaises(ValueError, int, Decimal('-nan'))
1639        self.assertRaises(ValueError, int, Decimal('snan'))
1640        self.assertRaises(OverflowError, int, Decimal('inf'))
1641        self.assertRaises(OverflowError, int, Decimal('-inf'))
1642
1643        self.assertRaises(ValueError, long, Decimal('-nan'))
1644        self.assertRaises(ValueError, long, Decimal('snan'))
1645        self.assertRaises(OverflowError, long, Decimal('inf'))
1646        self.assertRaises(OverflowError, long, Decimal('-inf'))
1647
1648    def test_quantize(self):
1649        c = Context(Emax=99999, Emin=-99999)
1650        self.assertEqual(
1651            Decimal('7.335').quantize(Decimal('.01')),
1652            Decimal('7.34')
1653        )
1654        self.assertEqual(
1655            Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
1656            Decimal('7.33')
1657        )
1658        self.assertRaises(
1659            InvalidOperation,
1660            Decimal("10e99999").quantize, Decimal('1e100000'), context=c
1661        )
1662        if HAVE_CDECIMAL:
1663            self.assertRaises(
1664                TypeError,
1665                Decimal("1.23456789").quantize, Decimal('1e-100000'), []
1666            )
1667            self.assertRaises(
1668                TypeError,
1669                Decimal("1.23456789").quantize, Decimal('1e-100000'), c
1670            )
1671            self.assertRaises(
1672                TypeError,
1673                Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
1674            )
1675            self.assertRaises(
1676                TypeError,
1677                Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
1678            )
1679
1680class ContextAPItests(unittest.TestCase):
1681
1682    def test_pickle(self):
1683        c = Context()
1684        e = pickle.loads(pickle.dumps(c))
1685        # XXX some are getters/setters
1686        #for k in vars(c):
1687        #    v1 = vars(c)[k]
1688        #    v2 = vars(e)[k]
1689        #    self.assertEqual(v1, v2)
1690        self.assertEqual(c.prec, e.prec)
1691        self.assertEqual(c.Emin, e.Emin)
1692        self.assertEqual(c.Emax, e.Emax)
1693        self.assertEqual(c.rounding, e.rounding)
1694        self.assertEqual(c.capitals, e.capitals)
1695        self.assertEqual(c.traps, e.traps)
1696        self.assertEqual(c.flags, e.flags)
1697        self.assertEqual(c._clamp, e._clamp)
1698
1699    def test_equality_with_other_types(self):
1700        self.assertTrue(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1701        self.assertTrue(Decimal(10) not in ['a', 1.0, (1,2), {}])
1702
1703    def test_copy(self):
1704        # All copies should be deep
1705        c = Context()
1706        d = c.copy()
1707        self.assertNotEqual(id(c), id(d))
1708        self.assertNotEqual(id(c.flags), id(d.flags))
1709        self.assertNotEqual(id(c.traps), id(d.traps))
1710        self.assertEqual(c.flags, d.flags)
1711
1712    def test_abs(self):
1713        c = Context()
1714        d = c.abs(Decimal(-1))
1715        self.assertEqual(c.abs(-1), d)
1716        self.assertRaises(TypeError, c.abs, '-1')
1717
1718    def test_add(self):
1719        c = Context()
1720        d = c.add(Decimal(1), Decimal(1))
1721        self.assertEqual(c.add(1, 1), d)
1722        self.assertEqual(c.add(Decimal(1), 1), d)
1723        self.assertEqual(c.add(1, Decimal(1)), d)
1724        self.assertRaises(TypeError, c.add, '1', 1)
1725        self.assertRaises(TypeError, c.add, 1, '1')
1726
1727    def test_compare(self):
1728        c = Context()
1729        d = c.compare(Decimal(1), Decimal(1))
1730        self.assertEqual(c.compare(1, 1), d)
1731        self.assertEqual(c.compare(Decimal(1), 1), d)
1732        self.assertEqual(c.compare(1, Decimal(1)), d)
1733        self.assertRaises(TypeError, c.compare, '1', 1)
1734        self.assertRaises(TypeError, c.compare, 1, '1')
1735
1736    def test_compare_signal(self):
1737        c = Context()
1738        d = c.compare_signal(Decimal(1), Decimal(1))
1739        self.assertEqual(c.compare_signal(1, 1), d)
1740        self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1741        self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1742        self.assertRaises(TypeError, c.compare_signal, '1', 1)
1743        self.assertRaises(TypeError, c.compare_signal, 1, '1')
1744
1745    def test_compare_total(self):
1746        c = Context()
1747        d = c.compare_total(Decimal(1), Decimal(1))
1748        self.assertEqual(c.compare_total(1, 1), d)
1749        self.assertEqual(c.compare_total(Decimal(1), 1), d)
1750        self.assertEqual(c.compare_total(1, Decimal(1)), d)
1751        self.assertRaises(TypeError, c.compare_total, '1', 1)
1752        self.assertRaises(TypeError, c.compare_total, 1, '1')
1753
1754    def test_compare_total_mag(self):
1755        c = Context()
1756        d = c.compare_total_mag(Decimal(1), Decimal(1))
1757        self.assertEqual(c.compare_total_mag(1, 1), d)
1758        self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1759        self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1760        self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1761        self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1762
1763    def test_copy_abs(self):
1764        c = Context()
1765        d = c.copy_abs(Decimal(-1))
1766        self.assertEqual(c.copy_abs(-1), d)
1767        self.assertRaises(TypeError, c.copy_abs, '-1')
1768
1769    def test_copy_decimal(self):
1770        c = Context()
1771        d = c.copy_decimal(Decimal(-1))
1772        self.assertEqual(c.copy_decimal(-1), d)
1773        self.assertRaises(TypeError, c.copy_decimal, '-1')
1774
1775    def test_copy_negate(self):
1776        c = Context()
1777        d = c.copy_negate(Decimal(-1))
1778        self.assertEqual(c.copy_negate(-1), d)
1779        self.assertRaises(TypeError, c.copy_negate, '-1')
1780
1781    def test_copy_sign(self):
1782        c = Context()
1783        d = c.copy_sign(Decimal(1), Decimal(-2))
1784        self.assertEqual(c.copy_sign(1, -2), d)
1785        self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1786        self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1787        self.assertRaises(TypeError, c.copy_sign, '1', -2)
1788        self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1789
1790    def test_divide(self):
1791        c = Context()
1792        d = c.divide(Decimal(1), Decimal(2))
1793        self.assertEqual(c.divide(1, 2), d)
1794        self.assertEqual(c.divide(Decimal(1), 2), d)
1795        self.assertEqual(c.divide(1, Decimal(2)), d)
1796        self.assertRaises(TypeError, c.divide, '1', 2)
1797        self.assertRaises(TypeError, c.divide, 1, '2')
1798
1799    def test_divide_int(self):
1800        c = Context()
1801        d = c.divide_int(Decimal(1), Decimal(2))
1802        self.assertEqual(c.divide_int(1, 2), d)
1803        self.assertEqual(c.divide_int(Decimal(1), 2), d)
1804        self.assertEqual(c.divide_int(1, Decimal(2)), d)
1805        self.assertRaises(TypeError, c.divide_int, '1', 2)
1806        self.assertRaises(TypeError, c.divide_int, 1, '2')
1807
1808    def test_divmod(self):
1809        c = Context()
1810        d = c.divmod(Decimal(1), Decimal(2))
1811        self.assertEqual(c.divmod(1, 2), d)
1812        self.assertEqual(c.divmod(Decimal(1), 2), d)
1813        self.assertEqual(c.divmod(1, Decimal(2)), d)
1814        self.assertRaises(TypeError, c.divmod, '1', 2)
1815        self.assertRaises(TypeError, c.divmod, 1, '2')
1816
1817    def test_exp(self):
1818        c = Context()
1819        d = c.exp(Decimal(10))
1820        self.assertEqual(c.exp(10), d)
1821        self.assertRaises(TypeError, c.exp, '10')
1822
1823    def test_fma(self):
1824        c = Context()
1825        d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1826        self.assertEqual(c.fma(2, 3, 4), d)
1827        self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1828        self.assertEqual(c.fma(2, Decimal(3), 4), d)
1829        self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1830        self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1831        self.assertRaises(TypeError, c.fma, '2', 3, 4)
1832        self.assertRaises(TypeError, c.fma, 2, '3', 4)
1833        self.assertRaises(TypeError, c.fma, 2, 3, '4')
1834
1835    def test_is_finite(self):
1836        c = Context()
1837        d = c.is_finite(Decimal(10))
1838        self.assertEqual(c.is_finite(10), d)
1839        self.assertRaises(TypeError, c.is_finite, '10')
1840
1841    def test_is_infinite(self):
1842        c = Context()
1843        d = c.is_infinite(Decimal(10))
1844        self.assertEqual(c.is_infinite(10), d)
1845        self.assertRaises(TypeError, c.is_infinite, '10')
1846
1847    def test_is_nan(self):
1848        c = Context()
1849        d = c.is_nan(Decimal(10))
1850        self.assertEqual(c.is_nan(10), d)
1851        self.assertRaises(TypeError, c.is_nan, '10')
1852
1853    def test_is_normal(self):
1854        c = Context()
1855        d = c.is_normal(Decimal(10))
1856        self.assertEqual(c.is_normal(10), d)
1857        self.assertRaises(TypeError, c.is_normal, '10')
1858
1859    def test_is_qnan(self):
1860        c = Context()
1861        d = c.is_qnan(Decimal(10))
1862        self.assertEqual(c.is_qnan(10), d)
1863        self.assertRaises(TypeError, c.is_qnan, '10')
1864
1865    def test_is_signed(self):
1866        c = Context()
1867        d = c.is_signed(Decimal(10))
1868        self.assertEqual(c.is_signed(10), d)
1869        self.assertRaises(TypeError, c.is_signed, '10')
1870
1871    def test_is_snan(self):
1872        c = Context()
1873        d = c.is_snan(Decimal(10))
1874        self.assertEqual(c.is_snan(10), d)
1875        self.assertRaises(TypeError, c.is_snan, '10')
1876
1877    def test_is_subnormal(self):
1878        c = Context()
1879        d = c.is_subnormal(Decimal(10))
1880        self.assertEqual(c.is_subnormal(10), d)
1881        self.assertRaises(TypeError, c.is_subnormal, '10')
1882
1883    def test_is_zero(self):
1884        c = Context()
1885        d = c.is_zero(Decimal(10))
1886        self.assertEqual(c.is_zero(10), d)
1887        self.assertRaises(TypeError, c.is_zero, '10')
1888
1889    def test_ln(self):
1890        c = Context()
1891        d = c.ln(Decimal(10))
1892        self.assertEqual(c.ln(10), d)
1893        self.assertRaises(TypeError, c.ln, '10')
1894
1895    def test_log10(self):
1896        c = Context()
1897        d = c.log10(Decimal(10))
1898        self.assertEqual(c.log10(10), d)
1899        self.assertRaises(TypeError, c.log10, '10')
1900
1901    def test_logb(self):
1902        c = Context()
1903        d = c.logb(Decimal(10))
1904        self.assertEqual(c.logb(10), d)
1905        self.assertRaises(TypeError, c.logb, '10')
1906
1907    def test_logical_and(self):
1908        c = Context()
1909        d = c.logical_and(Decimal(1), Decimal(1))
1910        self.assertEqual(c.logical_and(1, 1), d)
1911        self.assertEqual(c.logical_and(Decimal(1), 1), d)
1912        self.assertEqual(c.logical_and(1, Decimal(1)), d)
1913        self.assertRaises(TypeError, c.logical_and, '1', 1)
1914        self.assertRaises(TypeError, c.logical_and, 1, '1')
1915
1916    def test_logical_invert(self):
1917        c = Context()
1918        d = c.logical_invert(Decimal(1000))
1919        self.assertEqual(c.logical_invert(1000), d)
1920        self.assertRaises(TypeError, c.logical_invert, '1000')
1921
1922    def test_logical_or(self):
1923        c = Context()
1924        d = c.logical_or(Decimal(1), Decimal(1))
1925        self.assertEqual(c.logical_or(1, 1), d)
1926        self.assertEqual(c.logical_or(Decimal(1), 1), d)
1927        self.assertEqual(c.logical_or(1, Decimal(1)), d)
1928        self.assertRaises(TypeError, c.logical_or, '1', 1)
1929        self.assertRaises(TypeError, c.logical_or, 1, '1')
1930
1931    def test_logical_xor(self):
1932        c = Context()
1933        d = c.logical_xor(Decimal(1), Decimal(1))
1934        self.assertEqual(c.logical_xor(1, 1), d)
1935        self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1936        self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1937        self.assertRaises(TypeError, c.logical_xor, '1', 1)
1938        self.assertRaises(TypeError, c.logical_xor, 1, '1')
1939
1940    def test_max(self):
1941        c = Context()
1942        d = c.max(Decimal(1), Decimal(2))
1943        self.assertEqual(c.max(1, 2), d)
1944        self.assertEqual(c.max(Decimal(1), 2), d)
1945        self.assertEqual(c.max(1, Decimal(2)), d)
1946        self.assertRaises(TypeError, c.max, '1', 2)
1947        self.assertRaises(TypeError, c.max, 1, '2')
1948
1949    def test_max_mag(self):
1950        c = Context()
1951        d = c.max_mag(Decimal(1), Decimal(2))
1952        self.assertEqual(c.max_mag(1, 2), d)
1953        self.assertEqual(c.max_mag(Decimal(1), 2), d)
1954        self.assertEqual(c.max_mag(1, Decimal(2)), d)
1955        self.assertRaises(TypeError, c.max_mag, '1', 2)
1956        self.assertRaises(TypeError, c.max_mag, 1, '2')
1957
1958    def test_min(self):
1959        c = Context()
1960        d = c.min(Decimal(1), Decimal(2))
1961        self.assertEqual(c.min(1, 2), d)
1962        self.assertEqual(c.min(Decimal(1), 2), d)
1963        self.assertEqual(c.min(1, Decimal(2)), d)
1964        self.assertRaises(TypeError, c.min, '1', 2)
1965        self.assertRaises(TypeError, c.min, 1, '2')
1966
1967    def test_min_mag(self):
1968        c = Context()
1969        d = c.min_mag(Decimal(1), Decimal(2))
1970        self.assertEqual(c.min_mag(1, 2), d)
1971        self.assertEqual(c.min_mag(Decimal(1), 2), d)
1972        self.assertEqual(c.min_mag(1, Decimal(2)), d)
1973        self.assertRaises(TypeError, c.min_mag, '1', 2)
1974        self.assertRaises(TypeError, c.min_mag, 1, '2')
1975
1976    def test_minus(self):
1977        c = Context()
1978        d = c.minus(Decimal(10))
1979        self.assertEqual(c.minus(10), d)
1980        self.assertRaises(TypeError, c.minus, '10')
1981
1982    def test_multiply(self):
1983        c = Context()
1984        d = c.multiply(Decimal(1), Decimal(2))
1985        self.assertEqual(c.multiply(1, 2), d)
1986        self.assertEqual(c.multiply(Decimal(1), 2), d)
1987        self.assertEqual(c.multiply(1, Decimal(2)), d)
1988        self.assertRaises(TypeError, c.multiply, '1', 2)
1989        self.assertRaises(TypeError, c.multiply, 1, '2')
1990
1991    def test_next_minus(self):
1992        c = Context()
1993        d = c.next_minus(Decimal(10))
1994        self.assertEqual(c.next_minus(10), d)
1995        self.assertRaises(TypeError, c.next_minus, '10')
1996
1997    def test_next_plus(self):
1998        c = Context()
1999        d = c.next_plus(Decimal(10))
2000        self.assertEqual(c.next_plus(10), d)
2001        self.assertRaises(TypeError, c.next_plus, '10')
2002
2003    def test_next_toward(self):
2004        c = Context()
2005        d = c.next_toward(Decimal(1), Decimal(2))
2006        self.assertEqual(c.next_toward(1, 2), d)
2007        self.assertEqual(c.next_toward(Decimal(1), 2), d)
2008        self.assertEqual(c.next_toward(1, Decimal(2)), d)
2009        self.assertRaises(TypeError, c.next_toward, '1', 2)
2010        self.assertRaises(TypeError, c.next_toward, 1, '2')
2011
2012    def test_normalize(self):
2013        c = Context()
2014        d = c.normalize(Decimal(10))
2015        self.assertEqual(c.normalize(10), d)
2016        self.assertRaises(TypeError, c.normalize, '10')
2017
2018    def test_number_class(self):
2019        c = Context()
2020        self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2021        self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2022        self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2023
2024    def test_powmod(self):
2025        c = Context()
2026        d = c.powmod(Decimal(1), Decimal(4), Decimal(2))
2027        self.assertEqual(c.powmod(1, 4, 2), d)
2028        self.assertEqual(c.powmod(Decimal(1), 4, 2), d)
2029        self.assertEqual(c.powmod(1, Decimal(4), 2), d)
2030        self.assertEqual(c.powmod(1, 4, Decimal(2)), d)
2031        self.assertEqual(c.powmod(Decimal(1), Decimal(4), 2), d)
2032        self.assertRaises(TypeError, c.powmod, '1', 4, 2)
2033        self.assertRaises(TypeError, c.powmod, 1, '4', 2)
2034        self.assertRaises(TypeError, c.powmod, 1, 4, '2')
2035
2036    def test_plus(self):
2037        c = Context()
2038        d = c.plus(Decimal(10))
2039        self.assertEqual(c.plus(10), d)
2040        self.assertRaises(TypeError, c.plus, '10')
2041
2042    def test_quantize(self):
2043        c = Context()
2044        d = c.quantize(Decimal(1), Decimal(2))
2045        self.assertEqual(c.quantize(1, 2), d)
2046        self.assertEqual(c.quantize(Decimal(1), 2), d)
2047        self.assertEqual(c.quantize(1, Decimal(2)), d)
2048        self.assertRaises(TypeError, c.quantize, '1', 2)
2049        self.assertRaises(TypeError, c.quantize, 1, '2')
2050
2051    def test_remainder(self):
2052        c = Context()
2053        d = c.remainder(Decimal(1), Decimal(2))
2054        self.assertEqual(c.remainder(1, 2), d)
2055        self.assertEqual(c.remainder(Decimal(1), 2), d)
2056        self.assertEqual(c.remainder(1, Decimal(2)), d)
2057        self.assertRaises(TypeError, c.remainder, '1', 2)
2058        self.assertRaises(TypeError, c.remainder, 1, '2')
2059
2060    def test_remainder_near(self):
2061        c = Context()
2062        d = c.remainder_near(Decimal(1), Decimal(2))
2063        self.assertEqual(c.remainder_near(1, 2), d)
2064        self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2065        self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2066        self.assertRaises(TypeError, c.remainder_near, '1', 2)
2067        self.assertRaises(TypeError, c.remainder_near, 1, '2')
2068
2069    def test_rotate(self):
2070        c = Context()
2071        d = c.rotate(Decimal(1), Decimal(2))
2072        self.assertEqual(c.rotate(1, 2), d)
2073        self.assertEqual(c.rotate(Decimal(1), 2), d)
2074        self.assertEqual(c.rotate(1, Decimal(2)), d)
2075        self.assertRaises(TypeError, c.rotate, '1', 2)
2076        self.assertRaises(TypeError, c.rotate, 1, '2')
2077
2078    def test_sqrt(self):
2079        c = Context()
2080        d = c.sqrt(Decimal(10))
2081        self.assertEqual(c.sqrt(10), d)
2082        self.assertRaises(TypeError, c.sqrt, '10')
2083
2084    def test_same_quantum(self):
2085        c = Context()
2086        d = c.same_quantum(Decimal(1), Decimal(2))
2087        self.assertEqual(c.same_quantum(1, 2), d)
2088        self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2089        self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2090        self.assertRaises(TypeError, c.same_quantum, '1', 2)
2091        self.assertRaises(TypeError, c.same_quantum, 1, '2')
2092
2093    def test_scaleb(self):
2094        c = Context()
2095        d = c.scaleb(Decimal(1), Decimal(2))
2096        self.assertEqual(c.scaleb(1, 2), d)
2097        self.assertEqual(c.scaleb(Decimal(1), 2), d)
2098        self.assertEqual(c.scaleb(1, Decimal(2)), d)
2099        self.assertRaises(TypeError, c.scaleb, '1', 2)
2100        self.assertRaises(TypeError, c.scaleb, 1, '2')
2101
2102    def test_shift(self):
2103        c = Context()
2104        d = c.shift(Decimal(1), Decimal(2))
2105        self.assertEqual(c.shift(1, 2), d)
2106        self.assertEqual(c.shift(Decimal(1), 2), d)
2107        self.assertEqual(c.shift(1, Decimal(2)), d)
2108        self.assertRaises(TypeError, c.shift, '1', 2)
2109        self.assertRaises(TypeError, c.shift, 1, '2')
2110
2111    def test_subtract(self):
2112        c = Context()
2113        d = c.subtract(Decimal(1), Decimal(2))
2114        self.assertEqual(c.subtract(1, 2), d)
2115        self.assertEqual(c.subtract(Decimal(1), 2), d)
2116        self.assertEqual(c.subtract(1, Decimal(2)), d)
2117        self.assertRaises(TypeError, c.subtract, '1', 2)
2118        self.assertRaises(TypeError, c.subtract, 1, '2')
2119
2120    def test_to_eng_string(self):
2121        c = Context()
2122        d = c.to_eng_string(Decimal(10))
2123        self.assertEqual(c.to_eng_string(10), d)
2124        self.assertRaises(TypeError, c.to_eng_string, '10')
2125
2126    def test_to_sci_string(self):
2127        c = Context()
2128        d = c.to_sci_string(Decimal(10))
2129        self.assertEqual(c.to_sci_string(10), d)
2130        self.assertRaises(TypeError, c.to_sci_string, '10')
2131
2132    def test_to_integral_exact(self):
2133        c = Context()
2134        d = c.to_integral_exact(Decimal(10))
2135        self.assertEqual(c.to_integral_exact(10), d)
2136        self.assertRaises(TypeError, c.to_integral_exact, '10')
2137
2138    def test_to_integral_value(self):
2139        c = Context()
2140        d = c.to_integral_value(Decimal(10))
2141        self.assertEqual(c.to_integral_value(10), d)
2142        self.assertRaises(TypeError, c.to_integral_value, '10')
2143
2144class WithStatementTest(unittest.TestCase):
2145    # Can't do these as docstrings until Python 2.6
2146    # as doctest can't handle __future__ statements
2147
2148    def test_localcontext(self):
2149        # Use a copy of the current context in the block
2150        orig_ctx = getcontext()
2151        with localcontext() as enter_ctx:
2152            set_ctx = getcontext()
2153        final_ctx = getcontext()
2154        self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2155        self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2156        self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
2157
2158    def test_localcontextarg(self):
2159        # Use a copy of the supplied context in the block
2160        orig_ctx = getcontext()
2161        new_ctx = Context(prec=42)
2162        with localcontext(new_ctx) as enter_ctx:
2163            set_ctx = getcontext()
2164        final_ctx = getcontext()
2165        self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2166        self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2167        self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2168        self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
2169
2170    def test_nested_with_statements(self):
2171        # Use a copy of the supplied context in the block
2172        orig_ctx = getcontext()
2173        orig_ctx.clear_flags()
2174        new_ctx = Context(Emax=384)
2175        with localcontext() as c1:
2176            self.assertEqual(c1.flags, orig_ctx.flags)
2177            self.assertEqual(c1.traps, orig_ctx.traps)
2178            c1.traps[Clamped] = True
2179            c1.Emin = -383
2180            self.assertRaises(Clamped, c1.create_decimal, '0e-999')
2181            self.assertTrue(c1.flags[Clamped])
2182            with localcontext(new_ctx) as c2:
2183                self.assertEqual(c2.flags, new_ctx.flags)
2184                self.assertEqual(c2.traps, new_ctx.traps)
2185                self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
2186                self.assertFalse(c2.flags[Clamped])
2187                self.assertTrue(c2.flags[Overflow])
2188                del c2
2189            self.assertFalse(c1.flags[Overflow])
2190            del c1
2191        self.assertNotEqual(orig_ctx.Emin, -383)
2192        self.assertFalse(orig_ctx.flags[Clamped])
2193        self.assertFalse(orig_ctx.flags[Overflow])
2194        self.assertFalse(new_ctx.flags[Clamped])
2195        self.assertFalse(new_ctx.flags[Overflow])
2196
2197    def test_with_statements_gc1(self):
2198        with localcontext() as c1:
2199            del c1
2200            with localcontext() as c2:
2201                del c2
2202                with localcontext() as c3:
2203                    del c3
2204                    with localcontext() as c4:
2205                        del c4
2206
2207    def test_with_statements_gc2(self):
2208        with localcontext() as c1:
2209            with localcontext(c1) as c2:
2210                del c1
2211                with localcontext(c2) as c3:
2212                    del c2
2213                    with localcontext(c3) as c4:
2214                        del c3
2215                        del c4
2216
2217    def test_with_statements_gc3(self):
2218        with localcontext() as c1:
2219            del c1
2220            n1 = Context(prec=1)
2221            setcontext(n1)
2222            with localcontext(n1) as c2:
2223                del n1
2224                self.assertEqual(c2.prec, 1)
2225                del c2
2226                n2 = Context(prec=2)
2227                setcontext(n2)
2228                del n2
2229                self.assertEqual(getcontext().prec, 2)
2230                n3 = Context(prec=3)
2231                setcontext(n3)
2232                self.assertEqual(getcontext().prec, 3)
2233                with localcontext(n3) as c3:
2234                    del n3
2235                    self.assertEqual(c3.prec, 3)
2236                    del c3
2237                    n4 = Context(prec=4)
2238                    setcontext(n4)
2239                    del n4
2240                    self.assertEqual(getcontext().prec, 4)
2241                    with localcontext() as c4:
2242                        self.assertEqual(c4.prec, 4)
2243                        del c4
2244
2245class ContextFlags(unittest.TestCase):
2246    def test_flags_irrelevant(self):
2247        # check that the result (numeric result + flags raised) of an
2248        # arithmetic operation doesn't depend on the current flags
2249
2250        # XXX 32-bit limits
2251        context = Context(prec=9, Emin=-425000000, Emax=425000000,
2252                    rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2253
2254        # operations that raise various flags, in the form (function, arglist)
2255        operations = [
2256            (context._apply, [Decimal("100E-425000010")]),
2257            (context.sqrt, [Decimal(2)]),
2258            (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2259            (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2260            (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2261            ]
2262
2263        # try various flags individually, then a whole lot at once
2264        flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2265                    [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2266
2267        for fn, args in operations:
2268            # find answer and flags raised using a clean context
2269            context.clear_flags()
2270            ans = fn(*args)
2271            flags = [k for k, v in context.flags.items() if v]
2272
2273            for extra_flags in flagsets:
2274                # set flags, before calling operation
2275                context.clear_flags()
2276                for flag in extra_flags:
2277                    # XXX _raise_error
2278                    # context._raise_error(flag)
2279                    context.flags[flag] = True
2280                new_ans = fn(*args)
2281
2282                # flags that we expect to be set after the operation
2283                expected_flags = list(flags)
2284                for flag in extra_flags:
2285                    if flag not in expected_flags:
2286                        expected_flags.append(flag)
2287                expected_flags.sort()
2288
2289                # flags we actually got
2290                new_flags = [k for k,v in context.flags.items() if v]
2291                new_flags.sort()
2292
2293                self.assertEqual(ans, new_ans,
2294                                 "operation produces different answers depending on flags set: " +
2295                                 "expected %s, got %s." % (ans, new_ans))
2296                self.assertEqual(new_flags, expected_flags,
2297                                  "operation raises different flags depending on flags set: " +
2298                                  "expected %s, got %s" % (expected_flags, new_flags))
2299
2300class SpecialContexts(unittest.TestCase):
2301    def test_context_templates(self):
2302        self.assertEqual(
2303            BasicContext._traps,
2304            DecIEEEInvalidOperation|DecDivisionByZero|DecOverflow|
2305            DecUnderflow|DecClamped
2306        )
2307
2308        basic_context_prec = BasicContext.prec
2309        extended_context_prec = ExtendedContext.prec
2310
2311        BasicContext.prec = ExtendedContext.prec = 441
2312
2313        for template in BasicContext, ExtendedContext:
2314            setcontext(template)
2315            c = getcontext()
2316            self.assertFalse(c is template)
2317            self.assertEqual(c.prec, 441)
2318
2319        BasicContext.prec = basic_context_prec
2320        ExtendedContext.prec = extended_context_prec
2321
2322    def test_default_context(self):
2323        self.assertEqual(
2324            DefaultContext._traps,
2325            DecIEEEInvalidOperation|DecDivisionByZero|DecOverflow
2326        )
2327
2328        default_context_prec = DefaultContext.prec
2329
2330        c = getcontext()
2331        saveprec = c.prec
2332
2333        DefaultContext.prec = 961
2334        c = getcontext()
2335        self.assertEqual(c.prec, saveprec)
2336
2337        setcontext(DefaultContext)
2338        c = getcontext()
2339        self.assertFalse(c is DefaultContext)
2340        self.assertEqual(c.prec, 961)
2341
2342        DefaultContext.prec = default_context_prec
2343
2344    def test_ieee_context(self):
2345        def assert_rest(self, context):
2346            self.assertEqual(context.clamp, 1)
2347            for v in context.traps.values():
2348                self.assertFalse(v)
2349            for v in context.flags.values():
2350                self.assertFalse(v)
2351
2352        c = IEEEContext(DECIMAL32)
2353        self.assertEqual(c.prec, 7)
2354        self.assertEqual(c.Emax, 96)
2355        self.assertEqual(c.Emin, -95)
2356        assert_rest(self, c)
2357
2358        c = IEEEContext(DECIMAL64)
2359        self.assertEqual(c.prec, 16)
2360        self.assertEqual(c.Emax, 384)
2361        self.assertEqual(c.Emin, -383)
2362        assert_rest(self, c)
2363
2364        c = IEEEContext(DECIMAL128)
2365        self.assertEqual(c.prec, 34)
2366        self.assertEqual(c.Emax, 6144)
2367        self.assertEqual(c.Emin, -6143)
2368        assert_rest(self, c)
2369
2370class Coverage(unittest.TestCase):
2371
2372    def test_bignum(self):
2373        b1 = 10**35
2374        b2 = 10**36
2375        with localcontext() as c:
2376            c.prec = 1000000
2377            for i in range(5):
2378                a = random.randrange(b1, b2)
2379                b = random.randrange(1000, 1200)
2380                x = a ** b
2381                y = Decimal(a) ** Decimal(b)
2382                self.assertEqual(x, y)
2383
2384def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
2385    """ Execute the tests.
2386
2387    Runs all arithmetic tests if arith is True or if the "decimal" resource
2388    is enabled in regrtest.py
2389    """
2390
2391    init()
2392    global TEST_ALL, DEBUG
2393    TEST_ALL = arith or is_resource_enabled('decimal')
2394    DEBUG = debug
2395
2396    if todo_tests is None:
2397        test_classes = [
2398            DecimalExplicitConstructionTest,
2399            DecimalImplicitConstructionTest,
2400            DecimalArithmeticOperatorsTest,
2401            DecimalUseOfContextTest,
2402            DecimalUsabilityTest,
2403            DecimalPythonAPItests,
2404            ContextAPItests,
2405            DecimalTest,
2406            WithStatementTest,
2407            ContextFlags,
2408            SpecialContexts,
2409            Coverage
2410        ]
2411    else:
2412        test_classes = [DecimalTest]
2413
2414    # Dynamically build custom test definition for each file in the test
2415    # directory and add the definitions to the DecimalTest class.  This
2416    # procedure insures that new files do not get skipped.
2417    for filename in os.listdir(directory):
2418        if '.decTest' not in filename or filename.startswith("."):
2419            continue
2420        head, tail = filename.split('.')
2421        if todo_tests is not None and head not in todo_tests:
2422            continue
2423        tester = lambda self, f=filename: self.eval_file(directory + f)
2424        setattr(DecimalTest, 'test_' + head, tester)
2425        del filename, head, tail, tester
2426
2427
2428    try:
2429        run_unittest(*test_classes)
2430        if todo_tests is None:
2431            import cdecimal as DecimalModule
2432    finally:
2433        setcontext(ORIGINAL_CONTEXT)
2434
2435if __name__ == '__main__':
2436    import optparse
2437    p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2438    p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2439    p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2440    (opt, args) = p.parse_args()
2441
2442    if opt.skip:
2443        test_main(arith=False, verbose=True)
2444    elif args:
2445        test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
2446    else:
2447        test_main(arith=True, verbose=True)
2448