PyXR

c:\python24\lib \ test \ test_decimal.py



0001 # Copyright (c) 2004 Python Software Foundation.
0002 # All rights reserved.
0003 
0004 # Written by Eric Price <eprice at tjhsst.edu>
0005 #    and Facundo Batista <facundo at taniquetil.com.ar>
0006 #    and Raymond Hettinger <python at rcn.com>
0007 #    and Aahz (aahz at pobox.com)
0008 #    and Tim Peters
0009 
0010 """
0011 These are the test cases for the Decimal module.
0012 
0013 There are two groups of tests, Arithmetic and Behaviour. The former test
0014 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
0015 test the pythonic behaviour according to PEP 327.
0016 
0017 Cowlishaw's tests can be downloaded from:
0018 
0019    www2.hursley.ibm.com/decimal/dectest.zip
0020 
0021 This test module can be called from command line with one parameter (Arithmetic
0022 or Behaviour) to test each part, or without parameter to test both parts. If
0023 you're working through IDLE, you can import this test module and call test_main()
0024 with the corresponding argument.
0025 """
0026 
0027 from __future__ import division
0028 
0029 import unittest
0030 import glob
0031 import os, sys
0032 import pickle, copy
0033 from decimal import *
0034 from test.test_support import TestSkipped, run_unittest, run_doctest, is_resource_enabled
0035 import threading
0036 import random
0037 
0038 # Useful Test Constant
0039 Signals = getcontext().flags.keys()
0040 
0041 # Tests are built around these assumed context defaults
0042 DefaultContext.prec=9
0043 DefaultContext.rounding=ROUND_HALF_EVEN
0044 DefaultContext.traps=dict.fromkeys(Signals, 0)
0045 setcontext(DefaultContext)
0046 
0047 
0048 TESTDATADIR = 'decimaltestdata'
0049 if __name__ == '__main__':
0050     file = sys.argv[0]
0051 else:
0052     file = __file__
0053 testdir = os.path.dirname(file) or os.curdir
0054 dir = testdir + os.sep + TESTDATADIR + os.sep
0055 
0056 skip_expected = not os.path.isdir(dir)
0057 
0058 # Make sure it actually raises errors when not expected and caught in flags
0059 # Slower, since it runs some things several times.
0060 EXTENDEDERRORTEST = False
0061 
0062 
0063 #Map the test cases' error names to the actual errors
0064 
0065 ErrorNames = {'clamped' : Clamped,
0066               'conversion_syntax' : InvalidOperation,
0067               'division_by_zero' : DivisionByZero,
0068               'division_impossible' : InvalidOperation,
0069               'division_undefined' : InvalidOperation,
0070               'inexact' : Inexact,
0071               'invalid_context' : InvalidOperation,
0072               'invalid_operation' : InvalidOperation,
0073               'overflow' : Overflow,
0074               'rounded' : Rounded,
0075               'subnormal' : Subnormal,
0076               'underflow' : Underflow}
0077 
0078 
0079 def Nonfunction(*args):
0080     """Doesn't do anything."""
0081     return None
0082 
0083 RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
0084                 'down' : ROUND_DOWN,
0085                 'floor' : ROUND_FLOOR,
0086                 'half_down' : ROUND_HALF_DOWN,
0087                 'half_even' : ROUND_HALF_EVEN,
0088                 'half_up' : ROUND_HALF_UP,
0089                 'up' : ROUND_UP}
0090 
0091 # Name adapter to be able to change the Decimal and Context
0092 # interface without changing the test files from Cowlishaw
0093 nameAdapter = {'toeng':'to_eng_string',
0094                'tosci':'to_sci_string',
0095                'samequantum':'same_quantum',
0096                'tointegral':'to_integral',
0097                'remaindernear':'remainder_near',
0098                'divideint':'divide_int',
0099                'squareroot':'sqrt',
0100                'apply':'_apply',
0101               }
0102 
0103 class DecimalTest(unittest.TestCase):
0104     """Class which tests the Decimal class against the test cases.
0105 
0106     Changed for unittest.
0107     """
0108     def setUp(self):
0109         global dir
0110         self.context = Context()
0111         for key in DefaultContext.traps.keys():
0112             DefaultContext.traps[key] = 1
0113         self.ignore_list = ['#']
0114         # Basically, a # means return NaN InvalidOperation.
0115         # Different from a sNaN in trim
0116 
0117         self.ChangeDict = {'precision' : self.change_precision,
0118                       'rounding' : self.change_rounding_method,
0119                       'maxexponent' : self.change_max_exponent,
0120                       'minexponent' : self.change_min_exponent,
0121                       'clamp' : self.change_clamp}
0122 
0123     def tearDown(self):
0124         """Cleaning up enviroment."""
0125         # leaving context in original state
0126         for key in DefaultContext.traps.keys():
0127             DefaultContext.traps[key] = 0
0128         return
0129 
0130     def eval_file(self, file):
0131         global skip_expected
0132         if skip_expected:
0133             raise TestSkipped
0134             return
0135         for line in open(file).xreadlines():
0136             line = line.replace('\r\n', '').replace('\n', '')
0137             #print line
0138             try:
0139                 t = self.eval_line(line)
0140             except InvalidOperation:
0141                 print 'Error in test cases:'
0142                 print line
0143                 continue
0144             except DecimalException, exception:
0145                 #Exception raised where there shoudn't have been one.
0146                 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
0147 
0148         return
0149 
0150     def eval_line(self, s):
0151         if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
0152             s = (s.split('->')[0] + '->' +
0153                  s.split('->')[1].split('--')[0]).strip()
0154         else:
0155             s = s.split('--')[0].strip()
0156 
0157         for ignore in self.ignore_list:
0158             if s.find(ignore) >= 0:
0159                 #print s.split()[0], 'NotImplemented--', ignore
0160                 return
0161         if not s:
0162             return
0163         elif ':' in s:
0164             return self.eval_directive(s)
0165         else:
0166             return self.eval_equation(s)
0167 
0168     def eval_directive(self, s):
0169         funct, value = map(lambda x: x.strip().lower(), s.split(':'))
0170         if funct == 'rounding':
0171             value = RoundingDict[value]
0172         else:
0173             try:
0174                 value = int(value)
0175             except ValueError:
0176                 pass
0177 
0178         funct = self.ChangeDict.get(funct, Nonfunction)
0179         funct(value)
0180 
0181     def eval_equation(self, s):
0182         #global DEFAULT_PRECISION
0183         #print DEFAULT_PRECISION
0184 
0185         if not TEST_ALL and random.random() < 0.90:
0186             return
0187 
0188         try:
0189             Sides = s.split('->')
0190             L = Sides[0].strip().split()
0191             id = L[0]
0192 #            print id,
0193             funct = L[1].lower()
0194             valstemp = L[2:]
0195             L = Sides[1].strip().split()
0196             ans = L[0]
0197             exceptions = L[1:]
0198         except (TypeError, AttributeError, IndexError):
0199             raise InvalidOperation
0200         def FixQuotes(val):
0201             val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
0202             val = val.replace("'", '').replace('"', '')
0203             val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
0204             return val
0205         fname = nameAdapter.get(funct, funct)
0206         if fname == 'rescale':
0207             return
0208         funct = getattr(self.context, fname)
0209         vals = []
0210         conglomerate = ''
0211         quote = 0
0212         theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
0213 
0214         for exception in Signals:
0215             self.context.traps[exception] = 1 #Catch these bugs...
0216         for exception in theirexceptions:
0217             self.context.traps[exception] = 0
0218         for i, val in enumerate(valstemp):
0219             if val.count("'") % 2 == 1:
0220                 quote = 1 - quote
0221             if quote:
0222                 conglomerate = conglomerate + ' ' + val
0223                 continue
0224             else:
0225                 val = conglomerate + val
0226                 conglomerate = ''
0227             v = FixQuotes(val)
0228             if fname in ('to_sci_string', 'to_eng_string'):
0229                 if EXTENDEDERRORTEST:
0230                     for error in theirexceptions:
0231                         self.context.traps[error] = 1
0232                         try:
0233                             funct(self.context.create_decimal(v))
0234                         except error:
0235                             pass
0236                         except Signals, e:
0237                             self.fail("Raised %s in %s when %s disabled" % \
0238                                       (e, s, error))
0239                         else:
0240                             self.fail("Did not raise %s in %s" % (error, s))
0241                         self.context.traps[error] = 0
0242                 v = self.context.create_decimal(v)
0243             else:
0244                 v = Decimal(v)
0245             vals.append(v)
0246 
0247         ans = FixQuotes(ans)
0248 
0249         if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
0250             for error in theirexceptions:
0251                 self.context.traps[error] = 1
0252                 try:
0253                     funct(*vals)
0254                 except error:
0255                     pass
0256                 except Signals, e:
0257                     self.fail("Raised %s in %s when %s disabled" % \
0258                               (e, s, error))
0259                 else:
0260                     self.fail("Did not raise %s in %s" % (error, s))
0261                 self.context.traps[error] = 0
0262         try:
0263             result = str(funct(*vals))
0264             if fname == 'same_quantum':
0265                 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
0266         except Signals, error:
0267             self.fail("Raised %s in %s" % (error, s))
0268         except: #Catch any error long enough to state the test case.
0269             print "ERROR:", s
0270             raise
0271 
0272         myexceptions = self.getexceptions()
0273         self.context.clear_flags()
0274 
0275         myexceptions.sort()
0276         theirexceptions.sort()
0277 
0278         self.assertEqual(result, ans,
0279                          'Incorrect answer for ' + s + ' -- got ' + result)
0280         self.assertEqual(myexceptions, theirexceptions,
0281                          'Incorrect flags set in ' + s + ' -- got ' \
0282                          + str(myexceptions))
0283         return
0284 
0285     def getexceptions(self):
0286         return [e for e in Signals if self.context.flags[e]]
0287 
0288     def change_precision(self, prec):
0289         self.context.prec = prec
0290     def change_rounding_method(self, rounding):
0291         self.context.rounding = rounding
0292     def change_min_exponent(self, exp):
0293         self.context.Emin = exp
0294     def change_max_exponent(self, exp):
0295         self.context.Emax = exp
0296     def change_clamp(self, clamp):
0297         self.context._clamp = clamp
0298 
0299 # Dynamically build custom test definition for each file in the test
0300 # directory and add the definitions to the DecimalTest class.  This
0301 # procedure insures that new files do not get skipped.
0302 for filename in os.listdir(dir):
0303     if '.decTest' not in filename:
0304         continue
0305     head, tail = filename.split('.')
0306     tester = lambda self, f=filename: self.eval_file(dir + f)
0307     setattr(DecimalTest, 'test_' + head, tester)
0308     del filename, head, tail, tester
0309 
0310 
0311 
0312 # The following classes test the behaviour of Decimal according to PEP 327
0313 
0314 class DecimalExplicitConstructionTest(unittest.TestCase):
0315     '''Unit tests for Explicit Construction cases of Decimal.'''
0316 
0317     def test_explicit_empty(self):
0318         self.assertEqual(Decimal(), Decimal("0"))
0319 
0320     def test_explicit_from_None(self):
0321         self.assertRaises(TypeError, Decimal, None)
0322 
0323     def test_explicit_from_int(self):
0324 
0325         #positive
0326         d = Decimal(45)
0327         self.assertEqual(str(d), '45')
0328 
0329         #very large positive
0330         d = Decimal(500000123)
0331         self.assertEqual(str(d), '500000123')
0332 
0333         #negative
0334         d = Decimal(-45)
0335         self.assertEqual(str(d), '-45')
0336 
0337         #zero
0338         d = Decimal(0)
0339         self.assertEqual(str(d), '0')
0340 
0341     def test_explicit_from_string(self):
0342 
0343         #empty
0344         self.assertEqual(str(Decimal('')), 'NaN')
0345 
0346         #int
0347         self.assertEqual(str(Decimal('45')), '45')
0348 
0349         #float
0350         self.assertEqual(str(Decimal('45.34')), '45.34')
0351 
0352         #engineer notation
0353         self.assertEqual(str(Decimal('45e2')), '4.5E+3')
0354 
0355         #just not a number
0356         self.assertEqual(str(Decimal('ugly')), 'NaN')
0357 
0358     def test_explicit_from_tuples(self):
0359 
0360         #zero
0361         d = Decimal( (0, (0,), 0) )
0362         self.assertEqual(str(d), '0')
0363 
0364         #int
0365         d = Decimal( (1, (4, 5), 0) )
0366         self.assertEqual(str(d), '-45')
0367 
0368         #float
0369         d = Decimal( (0, (4, 5, 3, 4), -2) )
0370         self.assertEqual(str(d), '45.34')
0371 
0372         #weird
0373         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
0374         self.assertEqual(str(d), '-4.34913534E-17')
0375 
0376         #wrong number of items
0377         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
0378 
0379         #bad sign
0380         self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
0381 
0382         #bad exp
0383         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
0384 
0385         #bad coefficients
0386         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
0387         self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
0388 
0389     def test_explicit_from_Decimal(self):
0390 
0391         #positive
0392         d = Decimal(45)
0393         e = Decimal(d)
0394         self.assertEqual(str(e), '45')
0395         self.assertNotEqual(id(d), id(e))
0396 
0397         #very large positive
0398         d = Decimal(500000123)
0399         e = Decimal(d)
0400         self.assertEqual(str(e), '500000123')
0401         self.assertNotEqual(id(d), id(e))
0402 
0403         #negative
0404         d = Decimal(-45)
0405         e = Decimal(d)
0406         self.assertEqual(str(e), '-45')
0407         self.assertNotEqual(id(d), id(e))
0408 
0409         #zero
0410         d = Decimal(0)
0411         e = Decimal(d)
0412         self.assertEqual(str(e), '0')
0413         self.assertNotEqual(id(d), id(e))
0414 
0415     def test_explicit_context_create_decimal(self):
0416 
0417         nc = copy.copy(getcontext())
0418         nc.prec = 3
0419 
0420         # empty
0421         d = Decimal()
0422         self.assertEqual(str(d), '0')
0423         d = nc.create_decimal()
0424         self.assertEqual(str(d), '0')
0425 
0426         # from None
0427         self.assertRaises(TypeError, nc.create_decimal, None)
0428 
0429         # from int
0430         d = nc.create_decimal(456)
0431         self.failUnless(isinstance(d, Decimal))
0432         self.assertEqual(nc.create_decimal(45678),
0433                          nc.create_decimal('457E+2'))
0434 
0435         # from string
0436         d = Decimal('456789')
0437         self.assertEqual(str(d), '456789')
0438         d = nc.create_decimal('456789')
0439         self.assertEqual(str(d), '4.57E+5')
0440 
0441         # from tuples
0442         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
0443         self.assertEqual(str(d), '-4.34913534E-17')
0444         d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
0445         self.assertEqual(str(d), '-4.35E-17')
0446 
0447         # from Decimal
0448         prevdec = Decimal(500000123)
0449         d = Decimal(prevdec)
0450         self.assertEqual(str(d), '500000123')
0451         d = nc.create_decimal(prevdec)
0452         self.assertEqual(str(d), '5.00E+8')
0453 
0454 
0455 class DecimalImplicitConstructionTest(unittest.TestCase):
0456     '''Unit tests for Implicit Construction cases of Decimal.'''
0457 
0458     def test_implicit_from_None(self):
0459         self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
0460 
0461     def test_implicit_from_int(self):
0462         #normal
0463         self.assertEqual(str(Decimal(5) + 45), '50')
0464         #exceeding precision
0465         self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
0466 
0467     def test_implicit_from_string(self):
0468         self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
0469 
0470     def test_implicit_from_float(self):
0471         self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
0472 
0473     def test_implicit_from_Decimal(self):
0474         self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
0475 
0476 
0477 class DecimalArithmeticOperatorsTest(unittest.TestCase):
0478     '''Unit tests for all arithmetic operators, binary and unary.'''
0479 
0480     def test_addition(self):
0481 
0482         d1 = Decimal('-11.1')
0483         d2 = Decimal('22.2')
0484 
0485         #two Decimals
0486         self.assertEqual(d1+d2, Decimal('11.1'))
0487         self.assertEqual(d2+d1, Decimal('11.1'))
0488 
0489         #with other type, left
0490         c = d1 + 5
0491         self.assertEqual(c, Decimal('-6.1'))
0492         self.assertEqual(type(c), type(d1))
0493 
0494         #with other type, right
0495         c = 5 + d1
0496         self.assertEqual(c, Decimal('-6.1'))
0497         self.assertEqual(type(c), type(d1))
0498 
0499         #inline with decimal
0500         d1 += d2
0501         self.assertEqual(d1, Decimal('11.1'))
0502 
0503         #inline with other type
0504         d1 += 5
0505         self.assertEqual(d1, Decimal('16.1'))
0506 
0507     def test_subtraction(self):
0508 
0509         d1 = Decimal('-11.1')
0510         d2 = Decimal('22.2')
0511 
0512         #two Decimals
0513         self.assertEqual(d1-d2, Decimal('-33.3'))
0514         self.assertEqual(d2-d1, Decimal('33.3'))
0515 
0516         #with other type, left
0517         c = d1 - 5
0518         self.assertEqual(c, Decimal('-16.1'))
0519         self.assertEqual(type(c), type(d1))
0520 
0521         #with other type, right
0522         c = 5 - d1
0523         self.assertEqual(c, Decimal('16.1'))
0524         self.assertEqual(type(c), type(d1))
0525 
0526         #inline with decimal
0527         d1 -= d2
0528         self.assertEqual(d1, Decimal('-33.3'))
0529 
0530         #inline with other type
0531         d1 -= 5
0532         self.assertEqual(d1, Decimal('-38.3'))
0533 
0534     def test_multiplication(self):
0535 
0536         d1 = Decimal('-5')
0537         d2 = Decimal('3')
0538 
0539         #two Decimals
0540         self.assertEqual(d1*d2, Decimal('-15'))
0541         self.assertEqual(d2*d1, Decimal('-15'))
0542 
0543         #with other type, left
0544         c = d1 * 5
0545         self.assertEqual(c, Decimal('-25'))
0546         self.assertEqual(type(c), type(d1))
0547 
0548         #with other type, right
0549         c = 5 * d1
0550         self.assertEqual(c, Decimal('-25'))
0551         self.assertEqual(type(c), type(d1))
0552 
0553         #inline with decimal
0554         d1 *= d2
0555         self.assertEqual(d1, Decimal('-15'))
0556 
0557         #inline with other type
0558         d1 *= 5
0559         self.assertEqual(d1, Decimal('-75'))
0560 
0561     def test_division(self):
0562 
0563         d1 = Decimal('-5')
0564         d2 = Decimal('2')
0565 
0566         #two Decimals
0567         self.assertEqual(d1/d2, Decimal('-2.5'))
0568         self.assertEqual(d2/d1, Decimal('-0.4'))
0569 
0570         #with other type, left
0571         c = d1 / 4
0572         self.assertEqual(c, Decimal('-1.25'))
0573         self.assertEqual(type(c), type(d1))
0574 
0575         #with other type, right
0576         c = 4 / d1
0577         self.assertEqual(c, Decimal('-0.8'))
0578         self.assertEqual(type(c), type(d1))
0579 
0580         #inline with decimal
0581         d1 /= d2
0582         self.assertEqual(d1, Decimal('-2.5'))
0583 
0584         #inline with other type
0585         d1 /= 4
0586         self.assertEqual(d1, Decimal('-0.625'))
0587 
0588     def test_floor_division(self):
0589 
0590         d1 = Decimal('5')
0591         d2 = Decimal('2')
0592 
0593         #two Decimals
0594         self.assertEqual(d1//d2, Decimal('2'))
0595         self.assertEqual(d2//d1, Decimal('0'))
0596 
0597         #with other type, left
0598         c = d1 // 4
0599         self.assertEqual(c, Decimal('1'))
0600         self.assertEqual(type(c), type(d1))
0601 
0602         #with other type, right
0603         c = 7 // d1
0604         self.assertEqual(c, Decimal('1'))
0605         self.assertEqual(type(c), type(d1))
0606 
0607         #inline with decimal
0608         d1 //= d2
0609         self.assertEqual(d1, Decimal('2'))
0610 
0611         #inline with other type
0612         d1 //= 2
0613         self.assertEqual(d1, Decimal('1'))
0614 
0615     def test_powering(self):
0616 
0617         d1 = Decimal('5')
0618         d2 = Decimal('2')
0619 
0620         #two Decimals
0621         self.assertEqual(d1**d2, Decimal('25'))
0622         self.assertEqual(d2**d1, Decimal('32'))
0623 
0624         #with other type, left
0625         c = d1 ** 4
0626         self.assertEqual(c, Decimal('625'))
0627         self.assertEqual(type(c), type(d1))
0628 
0629         #with other type, right
0630         c = 7 ** d1
0631         self.assertEqual(c, Decimal('16807'))
0632         self.assertEqual(type(c), type(d1))
0633 
0634         #inline with decimal
0635         d1 **= d2
0636         self.assertEqual(d1, Decimal('25'))
0637 
0638         #inline with other type
0639         d1 **= 4
0640         self.assertEqual(d1, Decimal('390625'))
0641 
0642     def test_module(self):
0643 
0644         d1 = Decimal('5')
0645         d2 = Decimal('2')
0646 
0647         #two Decimals
0648         self.assertEqual(d1%d2, Decimal('1'))
0649         self.assertEqual(d2%d1, Decimal('2'))
0650 
0651         #with other type, left
0652         c = d1 % 4
0653         self.assertEqual(c, Decimal('1'))
0654         self.assertEqual(type(c), type(d1))
0655 
0656         #with other type, right
0657         c = 7 % d1
0658         self.assertEqual(c, Decimal('2'))
0659         self.assertEqual(type(c), type(d1))
0660 
0661         #inline with decimal
0662         d1 %= d2
0663         self.assertEqual(d1, Decimal('1'))
0664 
0665         #inline with other type
0666         d1 %= 4
0667         self.assertEqual(d1, Decimal('1'))
0668 
0669     def test_floor_div_module(self):
0670 
0671         d1 = Decimal('5')
0672         d2 = Decimal('2')
0673 
0674         #two Decimals
0675         (p, q) = divmod(d1, d2)
0676         self.assertEqual(p, Decimal('2'))
0677         self.assertEqual(q, Decimal('1'))
0678         self.assertEqual(type(p), type(d1))
0679         self.assertEqual(type(q), type(d1))
0680 
0681         #with other type, left
0682         (p, q) = divmod(d1, 4)
0683         self.assertEqual(p, Decimal('1'))
0684         self.assertEqual(q, Decimal('1'))
0685         self.assertEqual(type(p), type(d1))
0686         self.assertEqual(type(q), type(d1))
0687 
0688         #with other type, right
0689         (p, q) = divmod(7, d1)
0690         self.assertEqual(p, Decimal('1'))
0691         self.assertEqual(q, Decimal('2'))
0692         self.assertEqual(type(p), type(d1))
0693         self.assertEqual(type(q), type(d1))
0694 
0695     def test_unary_operators(self):
0696         self.assertEqual(+Decimal(45), Decimal(+45))           #  +
0697         self.assertEqual(-Decimal(45), Decimal(-45))           #  -
0698         self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
0699 
0700 
0701 # The following are two functions used to test threading in the next class
0702 
0703 def thfunc1(cls):
0704     d1 = Decimal(1)
0705     d3 = Decimal(3)
0706     cls.assertEqual(d1/d3, Decimal('0.333333333'))
0707     cls.synchro.wait()
0708     cls.assertEqual(d1/d3, Decimal('0.333333333'))
0709     cls.finish1.set()
0710     return
0711 
0712 def thfunc2(cls):
0713     d1 = Decimal(1)
0714     d3 = Decimal(3)
0715     cls.assertEqual(d1/d3, Decimal('0.333333333'))
0716     thiscontext = getcontext()
0717     thiscontext.prec = 18
0718     cls.assertEqual(d1/d3, Decimal('0.333333333333333333'))
0719     cls.synchro.set()
0720     cls.finish2.set()
0721     return
0722 
0723 
0724 class DecimalUseOfContextTest(unittest.TestCase):
0725     '''Unit tests for Use of Context cases in Decimal.'''
0726 
0727     import threading
0728     # Take care executing this test from IDLE, there's an issue in threading
0729     # that hangs IDLE and I couldn't find it
0730 
0731     def test_threading(self):
0732         #Test the "threading isolation" of a Context.
0733 
0734         self.synchro = threading.Event()
0735         self.finish1 = threading.Event()
0736         self.finish2 = threading.Event()
0737 
0738         th1 = threading.Thread(target=thfunc1, args=(self,))
0739         th2 = threading.Thread(target=thfunc2, args=(self,))
0740 
0741         th1.start()
0742         th2.start()
0743 
0744         self.finish1.wait()
0745         self.finish1.wait()
0746         return
0747 
0748 
0749 class DecimalUsabilityTest(unittest.TestCase):
0750     '''Unit tests for Usability cases of Decimal.'''
0751 
0752     def test_comparison_operators(self):
0753 
0754         da = Decimal('23.42')
0755         db = Decimal('23.42')
0756         dc = Decimal('45')
0757 
0758         #two Decimals
0759         self.failUnless(dc > da)
0760         self.failUnless(dc >= da)
0761         self.failUnless(da < dc)
0762         self.failUnless(da <= dc)
0763         self.failUnless(da == db)
0764         self.failUnless(da != dc)
0765         self.failUnless(da <= db)
0766         self.failUnless(da >= db)
0767         self.assertEqual(cmp(dc,da), 1)
0768         self.assertEqual(cmp(da,dc), -1)
0769         self.assertEqual(cmp(da,db), 0)
0770 
0771         #a Decimal and an int
0772         self.failUnless(dc > 23)
0773         self.failUnless(23 < dc)
0774         self.failUnless(dc == 45)
0775         self.assertEqual(cmp(dc,23), 1)
0776         self.assertEqual(cmp(23,dc), -1)
0777         self.assertEqual(cmp(dc,45), 0)
0778 
0779         #a Decimal and uncomparable
0780         self.assertNotEqual(da, 'ugly')
0781         self.assertNotEqual(da, 32.7)
0782         self.assertNotEqual(da, object())
0783         self.assertNotEqual(da, object)
0784 
0785         # sortable
0786         a = map(Decimal, xrange(100))
0787         b =  a[:]
0788         random.shuffle(a)
0789         a.sort()
0790         self.assertEqual(a, b)
0791 
0792     def test_copy_and_deepcopy_methods(self):
0793         d = Decimal('43.24')
0794         c = copy.copy(d)
0795         self.assertEqual(id(c), id(d))
0796         dc = copy.deepcopy(d)
0797         self.assertEqual(id(dc), id(d))
0798 
0799     def test_hash_method(self):
0800         #just that it's hashable
0801         hash(Decimal(23))
0802         #the same hash that to an int
0803         self.assertEqual(hash(Decimal(23)), hash(23))
0804 
0805     def test_min_and_max_methods(self):
0806 
0807         d1 = Decimal('15.32')
0808         d2 = Decimal('28.5')
0809         l1 = 15
0810         l2 = 28
0811 
0812         #between Decimals
0813         self.failUnless(min(d1,d2) is d1)
0814         self.failUnless(min(d2,d1) is d1)
0815         self.failUnless(max(d1,d2) is d2)
0816         self.failUnless(max(d2,d1) is d2)
0817 
0818         #between Decimal and long
0819         self.failUnless(min(d1,l2) is d1)
0820         self.failUnless(min(l2,d1) is d1)
0821         self.failUnless(max(l1,d2) is d2)
0822         self.failUnless(max(d2,l1) is d2)
0823 
0824     def test_as_nonzero(self):
0825         #as false
0826         self.failIf(Decimal(0))
0827         #as true
0828         self.failUnless(Decimal('0.372'))
0829 
0830     def test_tostring_methods(self):
0831         #Test str and repr methods.
0832 
0833         d = Decimal('15.32')
0834         self.assertEqual(str(d), '15.32')               # str
0835         self.assertEqual(repr(d), 'Decimal("15.32")')   # repr
0836 
0837     def test_tonum_methods(self):
0838         #Test float, int and long methods.
0839 
0840         d1 = Decimal('66')
0841         d2 = Decimal('15.32')
0842 
0843         #int
0844         self.assertEqual(int(d1), 66)
0845         self.assertEqual(int(d2), 15)
0846 
0847         #long
0848         self.assertEqual(long(d1), 66)
0849         self.assertEqual(long(d2), 15)
0850 
0851         #float
0852         self.assertEqual(float(d1), 66)
0853         self.assertEqual(float(d2), 15.32)
0854 
0855     def test_eval_round_trip(self):
0856 
0857         #with zero
0858         d = Decimal( (0, (0,), 0) )
0859         self.assertEqual(d, eval(repr(d)))
0860 
0861         #int
0862         d = Decimal( (1, (4, 5), 0) )
0863         self.assertEqual(d, eval(repr(d)))
0864 
0865         #float
0866         d = Decimal( (0, (4, 5, 3, 4), -2) )
0867         self.assertEqual(d, eval(repr(d)))
0868 
0869         #weird
0870         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
0871         self.assertEqual(d, eval(repr(d)))
0872 
0873     def test_as_tuple(self):
0874 
0875         #with zero
0876         d = Decimal(0)
0877         self.assertEqual(d.as_tuple(), (0, (0,), 0) )
0878 
0879         #int
0880         d = Decimal(-45)
0881         self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
0882 
0883         #complicated string
0884         d = Decimal("-4.34913534E-17")
0885         self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
0886 
0887         #inf
0888         d = Decimal("Infinity")
0889         self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
0890 
0891     def test_immutability_operations(self):
0892         # Do operations and check that it didn't change change internal objects.
0893 
0894         d1 = Decimal('-25e55')
0895         b1 = Decimal('-25e55')
0896         d2 = Decimal('33e-33')
0897         b2 = Decimal('33e-33')
0898 
0899         def checkSameDec(operation, useOther=False):
0900             if useOther:
0901                 eval("d1." + operation + "(d2)")
0902                 self.assertEqual(d1._sign, b1._sign)
0903                 self.assertEqual(d1._int, b1._int)
0904                 self.assertEqual(d1._exp, b1._exp)
0905                 self.assertEqual(d2._sign, b2._sign)
0906                 self.assertEqual(d2._int, b2._int)
0907                 self.assertEqual(d2._exp, b2._exp)
0908             else:
0909                 eval("d1." + operation + "()")
0910                 self.assertEqual(d1._sign, b1._sign)
0911                 self.assertEqual(d1._int, b1._int)
0912                 self.assertEqual(d1._exp, b1._exp)
0913             return
0914 
0915         Decimal(d1)
0916         self.assertEqual(d1._sign, b1._sign)
0917         self.assertEqual(d1._int, b1._int)
0918         self.assertEqual(d1._exp, b1._exp)
0919 
0920         checkSameDec("__abs__")
0921         checkSameDec("__add__", True)
0922         checkSameDec("__div__", True)
0923         checkSameDec("__divmod__", True)
0924         checkSameDec("__cmp__", True)
0925         checkSameDec("__float__")
0926         checkSameDec("__floordiv__", True)
0927         checkSameDec("__hash__")
0928         checkSameDec("__int__")
0929         checkSameDec("__long__")
0930         checkSameDec("__mod__", True)
0931         checkSameDec("__mul__", True)
0932         checkSameDec("__neg__")
0933         checkSameDec("__nonzero__")
0934         checkSameDec("__pos__")
0935         checkSameDec("__pow__", True)
0936         checkSameDec("__radd__", True)
0937         checkSameDec("__rdiv__", True)
0938         checkSameDec("__rdivmod__", True)
0939         checkSameDec("__repr__")
0940         checkSameDec("__rfloordiv__", True)
0941         checkSameDec("__rmod__", True)
0942         checkSameDec("__rmul__", True)
0943         checkSameDec("__rpow__", True)
0944         checkSameDec("__rsub__", True)
0945         checkSameDec("__str__")
0946         checkSameDec("__sub__", True)
0947         checkSameDec("__truediv__", True)
0948         checkSameDec("adjusted")
0949         checkSameDec("as_tuple")
0950         checkSameDec("compare", True)
0951         checkSameDec("max", True)
0952         checkSameDec("min", True)
0953         checkSameDec("normalize")
0954         checkSameDec("quantize", True)
0955         checkSameDec("remainder_near", True)
0956         checkSameDec("same_quantum", True)
0957         checkSameDec("sqrt")
0958         checkSameDec("to_eng_string")
0959         checkSameDec("to_integral")
0960 
0961 class DecimalPythonAPItests(unittest.TestCase):
0962 
0963     def test_pickle(self):
0964         d = Decimal('-3.141590000')
0965         p = pickle.dumps(d)
0966         e = pickle.loads(p)
0967         self.assertEqual(d, e)
0968 
0969     def test_int(self):
0970         data = '1.0 1.1 1.9 2.0 0.0 -1.0 -1.1 -1.9 -2.0'.split()
0971         for s in data:
0972             # should work the same as for floats
0973             self.assertEqual(int(Decimal(s)), int(float(s)))
0974             # should work the same as ROUND_DOWN
0975             d = Decimal(s)
0976             r = Context(prec=1, rounding=ROUND_DOWN).create_decimal(s)
0977             self.assertEqual(Decimal(int(d)), r)
0978 
0979 class ContextAPItests(unittest.TestCase):
0980 
0981     def test_pickle(self):
0982         c = Context()
0983         e = pickle.loads(pickle.dumps(c))
0984         for k in vars(c):
0985             v1 = vars(c)[k]
0986             v2 = vars(e)[k]
0987             self.assertEqual(v1, v2)
0988 
0989     def test_equality_with_other_types(self):
0990         self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
0991         self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
0992 
0993     def test_copy(self):
0994         # All copies should be deep
0995         c = Context()
0996         d = c.copy()
0997         self.assertNotEqual(id(c), id(d))
0998         self.assertNotEqual(id(c.flags), id(d.flags))
0999         self.assertNotEqual(id(c.traps), id(d.traps))
1000 
1001 def test_main(arith=False, verbose=None):
1002     """ Execute the tests.
1003 
1004     Runs all arithmetic tests if arith is True or if the "decimal" resource
1005     is enabled in regrtest.py
1006     """
1007 
1008     global TEST_ALL
1009     TEST_ALL = arith or is_resource_enabled('decimal')
1010 
1011     test_classes = [
1012         DecimalExplicitConstructionTest,
1013         DecimalImplicitConstructionTest,
1014         DecimalArithmeticOperatorsTest,
1015         DecimalUseOfContextTest,
1016         DecimalUsabilityTest,
1017         DecimalPythonAPItests,
1018         ContextAPItests,
1019         DecimalTest,
1020     ]
1021 
1022     run_unittest(*test_classes)
1023     import decimal as DecimalModule
1024     run_doctest(DecimalModule, verbose)
1025 
1026 
1027 if __name__ == '__main__':
1028     # Calling with no arguments runs all tests.
1029     # Calling with "Skip" will skip over 90% of the arithmetic tests.
1030     if len(sys.argv) == 1:
1031         test_main(arith=True, verbose=True)
1032     elif len(sys.argv) == 2:
1033         arith = sys.argv[1].lower() != 'skip'
1034         test_main(arith=arith, verbose=True)
1035     else:
1036         raise ValueError("test called with wrong arguments, use test_Decimal [Skip]")
1037 

Generated by PyXR 0.9.4
SourceForge.net Logo