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