blob: e9fbad44ca8e29aaea10d2c09bb245c574e7f225 [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# 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 module.
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
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000027import glob
Christian Heimes400adb02008-02-01 08:12:03 +000028import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000029import os, sys
30import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Benjamin Petersone549ead2009-03-28 21:42:05 +000034from test.support import run_unittest, run_doctest, is_resource_enabled
Raymond Hettinger0aeac102004-07-05 22:53:03 +000035import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000036try:
37 import threading
38except ImportError:
39 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000040
Raymond Hettingerfed52962004-07-14 15:41:57 +000041# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000042Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000043
Mark Dickinsonece06972010-05-04 14:37:14 +000044# Signals ordered with respect to precedence: when an operation
45# produces multiple signals, signals occurring later in the list
46# should be handled before those occurring earlier in the list.
47OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
48 Underflow, Overflow, DivisionByZero, InvalidOperation)
49
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000050# Tests are built around these assumed context defaults.
51# test_main() restores the original context.
52def init():
53 global ORIGINAL_CONTEXT
54 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000055 DefaultTestContext = Context(
56 prec = 9,
57 rounding = ROUND_HALF_EVEN,
58 traps = dict.fromkeys(Signals, 0)
59 )
60 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000061
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000062TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000063if __name__ == '__main__':
64 file = sys.argv[0]
65else:
66 file = __file__
67testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000068directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000069
Raymond Hettinger267b8682005-03-27 10:47:39 +000070skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000071
Mark Dickinsond08fb832009-10-08 16:33:06 +000072# list of individual .decTest test ids that correspond to tests that
73# we're skipping for one reason or another.
Mark Dickinson0390f502010-07-08 19:21:59 +000074skipped_test_ids = set([
75 # Skip implementation-specific scaleb tests.
76 'scbx164',
77 'scbx165',
78
79 # For some operations (currently exp, ln, log10, power), the decNumber
80 # reference implementation imposes additional restrictions on the context
81 # and operands. These restrictions are not part of the specification;
82 # however, the effect of these restrictions does show up in some of the
83 # testcases. We skip testcases that violate these restrictions, since
84 # Decimal behaves differently from decNumber for these testcases so these
85 # testcases would otherwise fail.
86 'expx901',
87 'expx902',
88 'expx903',
89 'expx905',
90 'lnx901',
91 'lnx902',
92 'lnx903',
93 'lnx905',
94 'logx901',
95 'logx902',
96 'logx903',
97 'logx905',
98 'powx1183',
99 'powx1184',
100 'powx4001',
101 'powx4002',
102 'powx4003',
103 'powx4005',
104 'powx4008',
105 'powx4010',
106 'powx4012',
107 'powx4014',
108 ])
Mark Dickinsond08fb832009-10-08 16:33:06 +0000109
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000110# Make sure it actually raises errors when not expected and caught in flags
111# Slower, since it runs some things several times.
112EXTENDEDERRORTEST = False
113
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000114#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000116 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000118 'division_impossible' : InvalidOperation,
119 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000120 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000121 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122 'invalid_operation' : InvalidOperation,
123 'overflow' : Overflow,
124 'rounded' : Rounded,
125 'subnormal' : Subnormal,
126 'underflow' : Underflow}
127
128
129def Nonfunction(*args):
130 """Doesn't do anything."""
131 return None
132
133RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
134 'down' : ROUND_DOWN,
135 'floor' : ROUND_FLOOR,
136 'half_down' : ROUND_HALF_DOWN,
137 'half_even' : ROUND_HALF_EVEN,
138 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000139 'up' : ROUND_UP,
140 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000141
142# Name adapter to be able to change the Decimal and Context
143# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000144nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000145 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 'class':'number_class',
147 'comparesig':'compare_signal',
148 'comparetotal':'compare_total',
149 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000150 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000151 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000152 'copynegate':'copy_negate',
153 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000154 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000155 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000156 'iscanonical':'is_canonical',
157 'isfinite':'is_finite',
158 'isinfinite':'is_infinite',
159 'isnan':'is_nan',
160 'isnormal':'is_normal',
161 'isqnan':'is_qnan',
162 'issigned':'is_signed',
163 'issnan':'is_snan',
164 'issubnormal':'is_subnormal',
165 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000166 'maxmag':'max_mag',
167 'minmag':'min_mag',
168 'nextminus':'next_minus',
169 'nextplus':'next_plus',
170 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000171 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000172 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000173 'remaindernear':'remainder_near',
174 'samequantum':'same_quantum',
175 'squareroot':'sqrt',
176 'toeng':'to_eng_string',
177 'tointegral':'to_integral_value',
178 'tointegralx':'to_integral_exact',
179 'tosci':'to_sci_string',
180 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000181 }
182
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000183# The following functions return True/False rather than a Decimal instance
184
185LOGICAL_FUNCTIONS = (
186 'is_canonical',
187 'is_finite',
188 'is_infinite',
189 'is_nan',
190 'is_normal',
191 'is_qnan',
192 'is_signed',
193 'is_snan',
194 'is_subnormal',
195 'is_zero',
196 'same_quantum',
197 )
198
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000199class DecimalTest(unittest.TestCase):
200 """Class which tests the Decimal class against the test cases.
201
202 Changed for unittest.
203 """
204 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 self.ignore_list = ['#']
207 # Basically, a # means return NaN InvalidOperation.
208 # Different from a sNaN in trim
209
210 self.ChangeDict = {'precision' : self.change_precision,
211 'rounding' : self.change_rounding_method,
212 'maxexponent' : self.change_max_exponent,
213 'minexponent' : self.change_min_exponent,
214 'clamp' : self.change_clamp}
215
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000216 def eval_file(self, file):
217 global skip_expected
218 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000219 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000220 return
Neal Norwitz70967602006-03-17 08:29:44 +0000221 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000222 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000223 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000224 try:
225 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000226 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000227 #Exception raised where there shoudn't have been one.
228 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
229
230 return
231
232 def eval_line(self, s):
233 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
234 s = (s.split('->')[0] + '->' +
235 s.split('->')[1].split('--')[0]).strip()
236 else:
237 s = s.split('--')[0].strip()
238
239 for ignore in self.ignore_list:
240 if s.find(ignore) >= 0:
241 #print s.split()[0], 'NotImplemented--', ignore
242 return
243 if not s:
244 return
245 elif ':' in s:
246 return self.eval_directive(s)
247 else:
248 return self.eval_equation(s)
249
250 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000251 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000252 if funct == 'rounding':
253 value = RoundingDict[value]
254 else:
255 try:
256 value = int(value)
257 except ValueError:
258 pass
259
260 funct = self.ChangeDict.get(funct, Nonfunction)
261 funct(value)
262
263 def eval_equation(self, s):
264 #global DEFAULT_PRECISION
265 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000266
267 if not TEST_ALL and random.random() < 0.90:
268 return
269
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000270 try:
271 Sides = s.split('->')
272 L = Sides[0].strip().split()
273 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000274 if DEBUG:
275 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000276 funct = L[1].lower()
277 valstemp = L[2:]
278 L = Sides[1].strip().split()
279 ans = L[0]
280 exceptions = L[1:]
281 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000282 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000283 def FixQuotes(val):
284 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
285 val = val.replace("'", '').replace('"', '')
286 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
287 return val
Mark Dickinsond08fb832009-10-08 16:33:06 +0000288
289 if id in skipped_test_ids:
290 return
291
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000292 fname = nameAdapter.get(funct, funct)
293 if fname == 'rescale':
294 return
295 funct = getattr(self.context, fname)
296 vals = []
297 conglomerate = ''
298 quote = 0
299 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
300
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000301 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000302 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000304 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000305 for i, val in enumerate(valstemp):
306 if val.count("'") % 2 == 1:
307 quote = 1 - quote
308 if quote:
309 conglomerate = conglomerate + ' ' + val
310 continue
311 else:
312 val = conglomerate + val
313 conglomerate = ''
314 v = FixQuotes(val)
315 if fname in ('to_sci_string', 'to_eng_string'):
316 if EXTENDEDERRORTEST:
317 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000318 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000319 try:
320 funct(self.context.create_decimal(v))
321 except error:
322 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000323 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000324 self.fail("Raised %s in %s when %s disabled" % \
325 (e, s, error))
326 else:
327 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000328 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 v = self.context.create_decimal(v)
330 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000331 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000332 vals.append(v)
333
334 ans = FixQuotes(ans)
335
336 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
337 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000338 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 try:
340 funct(*vals)
341 except error:
342 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000343 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 self.fail("Raised %s in %s when %s disabled" % \
345 (e, s, error))
346 else:
347 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000348 self.context.traps[error] = 0
Mark Dickinsonece06972010-05-04 14:37:14 +0000349
350 # as above, but add traps cumulatively, to check precedence
351 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
352 for error in ordered_errors:
353 self.context.traps[error] = 1
354 try:
355 funct(*vals)
356 except error:
357 pass
358 except Signals as e:
359 self.fail("Raised %s in %s; expected %s" %
360 (type(e), s, error))
361 else:
362 self.fail("Did not raise %s in %s" % (error, s))
363 # reset traps
364 for error in ordered_errors:
365 self.context.traps[error] = 0
366
367
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000368 if DEBUG:
369 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370 try:
371 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000372 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000374 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 self.fail("Raised %s in %s" % (error, s))
376 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000377 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378 raise
379
380 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000381 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000383 myexceptions.sort(key=repr)
384 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000385
386 self.assertEqual(result, ans,
387 'Incorrect answer for ' + s + ' -- got ' + result)
388 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000389 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390 return
391
392 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000393 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000394
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395 def change_precision(self, prec):
396 self.context.prec = prec
397 def change_rounding_method(self, rounding):
398 self.context.rounding = rounding
399 def change_min_exponent(self, exp):
400 self.context.Emin = exp
401 def change_max_exponent(self, exp):
402 self.context.Emax = exp
403 def change_clamp(self, clamp):
404 self.context._clamp = clamp
405
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406
407
408# The following classes test the behaviour of Decimal according to PEP 327
409
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000410class DecimalExplicitConstructionTest(unittest.TestCase):
411 '''Unit tests for Explicit Construction cases of Decimal.'''
412
413 def test_explicit_empty(self):
414 self.assertEqual(Decimal(), Decimal("0"))
415
416 def test_explicit_from_None(self):
417 self.assertRaises(TypeError, Decimal, None)
418
419 def test_explicit_from_int(self):
420
421 #positive
422 d = Decimal(45)
423 self.assertEqual(str(d), '45')
424
425 #very large positive
426 d = Decimal(500000123)
427 self.assertEqual(str(d), '500000123')
428
429 #negative
430 d = Decimal(-45)
431 self.assertEqual(str(d), '-45')
432
433 #zero
434 d = Decimal(0)
435 self.assertEqual(str(d), '0')
436
437 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000438
439 #empty
440 self.assertEqual(str(Decimal('')), 'NaN')
441
442 #int
443 self.assertEqual(str(Decimal('45')), '45')
444
445 #float
446 self.assertEqual(str(Decimal('45.34')), '45.34')
447
448 #engineer notation
449 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
450
451 #just not a number
452 self.assertEqual(str(Decimal('ugly')), 'NaN')
453
Christian Heimesa62da1d2008-01-12 19:39:10 +0000454 #leading and trailing whitespace permitted
455 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
456 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
457
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000458 def test_explicit_from_tuples(self):
459
460 #zero
461 d = Decimal( (0, (0,), 0) )
462 self.assertEqual(str(d), '0')
463
464 #int
465 d = Decimal( (1, (4, 5), 0) )
466 self.assertEqual(str(d), '-45')
467
468 #float
469 d = Decimal( (0, (4, 5, 3, 4), -2) )
470 self.assertEqual(str(d), '45.34')
471
472 #weird
473 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
474 self.assertEqual(str(d), '-4.34913534E-17')
475
476 #wrong number of items
477 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
478
479 #bad sign
480 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000481 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
482 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000483
484 #bad exp
485 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000486 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
487 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000488
489 #bad coefficients
490 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
491 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000492 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494
495 def test_explicit_from_Decimal(self):
496
497 #positive
498 d = Decimal(45)
499 e = Decimal(d)
500 self.assertEqual(str(e), '45')
501 self.assertNotEqual(id(d), id(e))
502
503 #very large positive
504 d = Decimal(500000123)
505 e = Decimal(d)
506 self.assertEqual(str(e), '500000123')
507 self.assertNotEqual(id(d), id(e))
508
509 #negative
510 d = Decimal(-45)
511 e = Decimal(d)
512 self.assertEqual(str(e), '-45')
513 self.assertNotEqual(id(d), id(e))
514
515 #zero
516 d = Decimal(0)
517 e = Decimal(d)
518 self.assertEqual(str(e), '0')
519 self.assertNotEqual(id(d), id(e))
520
521 def test_explicit_context_create_decimal(self):
522
523 nc = copy.copy(getcontext())
524 nc.prec = 3
525
526 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000527 d = Decimal()
528 self.assertEqual(str(d), '0')
529 d = nc.create_decimal()
530 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000531
532 # from None
533 self.assertRaises(TypeError, nc.create_decimal, None)
534
535 # from int
536 d = nc.create_decimal(456)
Georg Brandlab91fde2009-08-13 08:51:18 +0000537 self.assertTrue(isinstance(d, Decimal))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538 self.assertEqual(nc.create_decimal(45678),
539 nc.create_decimal('457E+2'))
540
541 # from string
542 d = Decimal('456789')
543 self.assertEqual(str(d), '456789')
544 d = nc.create_decimal('456789')
545 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000546 # leading and trailing whitespace should result in a NaN;
547 # spaces are already checked in Cowlishaw's test-suite, so
548 # here we just check that a trailing newline results in a NaN
549 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000550
551 # from tuples
552 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
553 self.assertEqual(str(d), '-4.34913534E-17')
554 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
555 self.assertEqual(str(d), '-4.35E-17')
556
557 # from Decimal
558 prevdec = Decimal(500000123)
559 d = Decimal(prevdec)
560 self.assertEqual(str(d), '500000123')
561 d = nc.create_decimal(prevdec)
562 self.assertEqual(str(d), '5.00E+8')
563
Mark Dickinson8d238292009-08-02 10:16:33 +0000564 def test_unicode_digits(self):
565 test_values = {
566 '\uff11': '1',
567 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
568 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
569 }
570 for input, expected in test_values.items():
571 self.assertEqual(str(Decimal(input)), expected)
572
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000573
574class DecimalImplicitConstructionTest(unittest.TestCase):
575 '''Unit tests for Implicit Construction cases of Decimal.'''
576
577 def test_implicit_from_None(self):
578 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
579
580 def test_implicit_from_int(self):
581 #normal
582 self.assertEqual(str(Decimal(5) + 45), '50')
583 #exceeding precision
584 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
585
586 def test_implicit_from_string(self):
587 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
588
589 def test_implicit_from_float(self):
590 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
591
592 def test_implicit_from_Decimal(self):
593 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
594
Raymond Hettinger267b8682005-03-27 10:47:39 +0000595 def test_rop(self):
596 # Allow other classes to be trained to interact with Decimals
597 class E:
598 def __divmod__(self, other):
599 return 'divmod ' + str(other)
600 def __rdivmod__(self, other):
601 return str(other) + ' rdivmod'
602 def __lt__(self, other):
603 return 'lt ' + str(other)
604 def __gt__(self, other):
605 return 'gt ' + str(other)
606 def __le__(self, other):
607 return 'le ' + str(other)
608 def __ge__(self, other):
609 return 'ge ' + str(other)
610 def __eq__(self, other):
611 return 'eq ' + str(other)
612 def __ne__(self, other):
613 return 'ne ' + str(other)
614
615 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
616 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
617 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
618 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
619 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
620 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
621 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
622 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
623
624 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000625 oplist = [
626 ('+', '__add__', '__radd__'),
627 ('-', '__sub__', '__rsub__'),
628 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000629 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000630 ('%', '__mod__', '__rmod__'),
631 ('//', '__floordiv__', '__rfloordiv__'),
632 ('**', '__pow__', '__rpow__')
633 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000634
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000635 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000636 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
637 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
638 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
639 'str' + lop + '10')
640 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
641 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000642
Mark Dickinson79f52032009-03-17 23:12:51 +0000643
Christian Heimesf16baeb2008-02-29 14:57:44 +0000644class DecimalFormatTest(unittest.TestCase):
645 '''Unit tests for the format function.'''
646 def test_formatting(self):
647 # triples giving a format, a Decimal, and the expected result
648 test_values = [
649 ('e', '0E-15', '0e-15'),
650 ('e', '2.3E-15', '2.3e-15'),
651 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
652 ('e', '2.30000E-15', '2.30000e-15'),
653 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
654 ('e', '1.5', '1.5e+0'),
655 ('e', '0.15', '1.5e-1'),
656 ('e', '0.015', '1.5e-2'),
657 ('e', '0.0000000000015', '1.5e-12'),
658 ('e', '15.0', '1.50e+1'),
659 ('e', '-15', '-1.5e+1'),
660 ('e', '0', '0e+0'),
661 ('e', '0E1', '0e+1'),
662 ('e', '0.0', '0e-1'),
663 ('e', '0.00', '0e-2'),
664 ('.6e', '0E-15', '0.000000e-9'),
665 ('.6e', '0', '0.000000e+6'),
666 ('.6e', '9.999999', '9.999999e+0'),
667 ('.6e', '9.9999999', '1.000000e+1'),
668 ('.6e', '-1.23e5', '-1.230000e+5'),
669 ('.6e', '1.23456789e-3', '1.234568e-3'),
670 ('f', '0', '0'),
671 ('f', '0.0', '0.0'),
672 ('f', '0E-2', '0.00'),
673 ('f', '0.00E-8', '0.0000000000'),
674 ('f', '0E1', '0'), # loses exponent information
675 ('f', '3.2E1', '32'),
676 ('f', '3.2E2', '320'),
677 ('f', '3.20E2', '320'),
678 ('f', '3.200E2', '320.0'),
679 ('f', '3.2E-6', '0.0000032'),
680 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
681 ('.6f', '0E1', '0.000000'),
682 ('.6f', '0', '0.000000'),
683 ('.0f', '0', '0'), # no decimal point
684 ('.0f', '0e-2', '0'),
685 ('.0f', '3.14159265', '3'),
686 ('.1f', '3.14159265', '3.1'),
687 ('.4f', '3.14159265', '3.1416'),
688 ('.6f', '3.14159265', '3.141593'),
689 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
690 ('.8f', '3.14159265', '3.14159265'),
691 ('.9f', '3.14159265', '3.141592650'),
692
693 ('g', '0', '0'),
694 ('g', '0.0', '0.0'),
695 ('g', '0E1', '0e+1'),
696 ('G', '0E1', '0E+1'),
697 ('g', '0E-5', '0.00000'),
698 ('g', '0E-6', '0.000000'),
699 ('g', '0E-7', '0e-7'),
700 ('g', '-0E2', '-0e+2'),
701 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
702 ('.1g', '3.14159265', '3'),
703 ('.2g', '3.14159265', '3.1'),
704 ('.5g', '3.14159265', '3.1416'),
705 ('.7g', '3.14159265', '3.141593'),
706 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
707 ('.9g', '3.14159265', '3.14159265'),
708 ('.10g', '3.14159265', '3.14159265'), # don't pad
709
710 ('%', '0E1', '0%'),
711 ('%', '0E0', '0%'),
712 ('%', '0E-1', '0%'),
713 ('%', '0E-2', '0%'),
714 ('%', '0E-3', '0.0%'),
715 ('%', '0E-4', '0.00%'),
716
717 ('.3%', '0', '0.000%'), # all zeros treated equally
718 ('.3%', '0E10', '0.000%'),
719 ('.3%', '0E-10', '0.000%'),
720 ('.3%', '2.34', '234.000%'),
721 ('.3%', '1.234567', '123.457%'),
722 ('.0%', '1.23', '123%'),
723
724 ('e', 'NaN', 'NaN'),
725 ('f', '-NaN123', '-NaN123'),
726 ('+g', 'NaN456', '+NaN456'),
727 ('.3e', 'Inf', 'Infinity'),
728 ('.16f', '-Inf', '-Infinity'),
729 ('.0g', '-sNaN', '-sNaN'),
730
731 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000732
Mark Dickinson79f52032009-03-17 23:12:51 +0000733 # test alignment and padding
Mark Dickinsonad416342009-03-17 18:10:15 +0000734 ('<6', '123', '123 '),
735 ('>6', '123', ' 123'),
736 ('^6', '123', ' 123 '),
737 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000738 ('#<10', 'NaN', 'NaN#######'),
739 ('#<10', '-4.3', '-4.3######'),
740 ('#<+10', '0.0130', '+0.0130###'),
741 ('#< 10', '0.0130', ' 0.0130###'),
742 ('@>10', '-Inf', '@-Infinity'),
743 ('#>5', '-Inf', '-Infinity'),
744 ('?^5', '123', '?123?'),
745 ('%^6', '123', '%123%%'),
746 (' ^6', '-45.6', '-45.6 '),
747 ('/=10', '-45.6', '-/////45.6'),
748 ('/=+10', '45.6', '+/////45.6'),
749 ('/= 10', '45.6', ' /////45.6'),
750
751 # thousands separator
752 (',', '1234567', '1,234,567'),
753 (',', '123456', '123,456'),
754 (',', '12345', '12,345'),
755 (',', '1234', '1,234'),
756 (',', '123', '123'),
757 (',', '12', '12'),
758 (',', '1', '1'),
759 (',', '0', '0'),
760 (',', '-1234567', '-1,234,567'),
761 (',', '-123456', '-123,456'),
762 ('7,', '123456', '123,456'),
763 ('8,', '123456', '123,456 '),
764 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
765 ('+08,', '123456', '+123,456'), # but not if there's a sign
766 (' 08,', '123456', ' 123,456'),
767 ('08,', '-123456', '-123,456'),
768 ('+09,', '123456', '+0,123,456'),
769 # ... with fractional part...
770 ('07,', '1234.56', '1,234.56'),
771 ('08,', '1234.56', '1,234.56'),
772 ('09,', '1234.56', '01,234.56'),
773 ('010,', '1234.56', '001,234.56'),
774 ('011,', '1234.56', '0,001,234.56'),
775 ('012,', '1234.56', '0,001,234.56'),
776 ('08,.1f', '1234.5', '01,234.5'),
777 # no thousands separators in fraction part
778 (',', '1.23456789', '1.23456789'),
779 (',%', '123.456789', '12,345.6789%'),
780 (',e', '123456', '1.23456e+5'),
781 (',E', '123456', '1.23456E+5'),
Mark Dickinsond496d302009-09-07 16:23:26 +0000782
783 # issue 6850
784 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000785 ]
786 for fmt, d, result in test_values:
787 self.assertEqual(format(Decimal(d), fmt), result)
788
Mark Dickinson79f52032009-03-17 23:12:51 +0000789 def test_n_format(self):
790 try:
791 from locale import CHAR_MAX
792 except ImportError:
793 return
794
795 # Set up some localeconv-like dictionaries
796 en_US = {
797 'decimal_point' : '.',
798 'grouping' : [3, 3, 0],
799 'thousands_sep': ','
800 }
801
802 fr_FR = {
803 'decimal_point' : ',',
804 'grouping' : [CHAR_MAX],
805 'thousands_sep' : ''
806 }
807
808 ru_RU = {
809 'decimal_point' : ',',
810 'grouping' : [3, 3, 0],
811 'thousands_sep' : ' '
812 }
813
814 crazy = {
815 'decimal_point' : '&',
816 'grouping' : [1, 4, 2, CHAR_MAX],
817 'thousands_sep' : '-'
818 }
819
820
821 def get_fmt(x, locale, fmt='n'):
822 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
823
824 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
825 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
826 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
827 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
828
829 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
830 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
831 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
832 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
833
834 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
835 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
836 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
837 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
838
Mark Dickinson7303b592009-03-18 08:25:36 +0000839 # zero padding
840 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
841 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
842 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
843 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
844
845 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
846 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
847 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
848 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
849 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
850 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
851
852 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
853 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
854 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
855 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
856 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
857 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
858 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
859 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
860
Mark Dickinson79f52032009-03-17 23:12:51 +0000861
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000862class DecimalArithmeticOperatorsTest(unittest.TestCase):
863 '''Unit tests for all arithmetic operators, binary and unary.'''
864
865 def test_addition(self):
866
867 d1 = Decimal('-11.1')
868 d2 = Decimal('22.2')
869
870 #two Decimals
871 self.assertEqual(d1+d2, Decimal('11.1'))
872 self.assertEqual(d2+d1, Decimal('11.1'))
873
874 #with other type, left
875 c = d1 + 5
876 self.assertEqual(c, Decimal('-6.1'))
877 self.assertEqual(type(c), type(d1))
878
879 #with other type, right
880 c = 5 + d1
881 self.assertEqual(c, Decimal('-6.1'))
882 self.assertEqual(type(c), type(d1))
883
884 #inline with decimal
885 d1 += d2
886 self.assertEqual(d1, Decimal('11.1'))
887
888 #inline with other type
889 d1 += 5
890 self.assertEqual(d1, Decimal('16.1'))
891
892 def test_subtraction(self):
893
894 d1 = Decimal('-11.1')
895 d2 = Decimal('22.2')
896
897 #two Decimals
898 self.assertEqual(d1-d2, Decimal('-33.3'))
899 self.assertEqual(d2-d1, Decimal('33.3'))
900
901 #with other type, left
902 c = d1 - 5
903 self.assertEqual(c, Decimal('-16.1'))
904 self.assertEqual(type(c), type(d1))
905
906 #with other type, right
907 c = 5 - d1
908 self.assertEqual(c, Decimal('16.1'))
909 self.assertEqual(type(c), type(d1))
910
911 #inline with decimal
912 d1 -= d2
913 self.assertEqual(d1, Decimal('-33.3'))
914
915 #inline with other type
916 d1 -= 5
917 self.assertEqual(d1, Decimal('-38.3'))
918
919 def test_multiplication(self):
920
921 d1 = Decimal('-5')
922 d2 = Decimal('3')
923
924 #two Decimals
925 self.assertEqual(d1*d2, Decimal('-15'))
926 self.assertEqual(d2*d1, Decimal('-15'))
927
928 #with other type, left
929 c = d1 * 5
930 self.assertEqual(c, Decimal('-25'))
931 self.assertEqual(type(c), type(d1))
932
933 #with other type, right
934 c = 5 * d1
935 self.assertEqual(c, Decimal('-25'))
936 self.assertEqual(type(c), type(d1))
937
938 #inline with decimal
939 d1 *= d2
940 self.assertEqual(d1, Decimal('-15'))
941
942 #inline with other type
943 d1 *= 5
944 self.assertEqual(d1, Decimal('-75'))
945
946 def test_division(self):
947
948 d1 = Decimal('-5')
949 d2 = Decimal('2')
950
951 #two Decimals
952 self.assertEqual(d1/d2, Decimal('-2.5'))
953 self.assertEqual(d2/d1, Decimal('-0.4'))
954
955 #with other type, left
956 c = d1 / 4
957 self.assertEqual(c, Decimal('-1.25'))
958 self.assertEqual(type(c), type(d1))
959
960 #with other type, right
961 c = 4 / d1
962 self.assertEqual(c, Decimal('-0.8'))
963 self.assertEqual(type(c), type(d1))
964
965 #inline with decimal
966 d1 /= d2
967 self.assertEqual(d1, Decimal('-2.5'))
968
969 #inline with other type
970 d1 /= 4
971 self.assertEqual(d1, Decimal('-0.625'))
972
973 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000974
975 d1 = Decimal('5')
976 d2 = Decimal('2')
977
978 #two Decimals
979 self.assertEqual(d1//d2, Decimal('2'))
980 self.assertEqual(d2//d1, Decimal('0'))
981
982 #with other type, left
983 c = d1 // 4
984 self.assertEqual(c, Decimal('1'))
985 self.assertEqual(type(c), type(d1))
986
987 #with other type, right
988 c = 7 // d1
989 self.assertEqual(c, Decimal('1'))
990 self.assertEqual(type(c), type(d1))
991
992 #inline with decimal
993 d1 //= d2
994 self.assertEqual(d1, Decimal('2'))
995
996 #inline with other type
997 d1 //= 2
998 self.assertEqual(d1, Decimal('1'))
999
1000 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001001
1002 d1 = Decimal('5')
1003 d2 = Decimal('2')
1004
1005 #two Decimals
1006 self.assertEqual(d1**d2, Decimal('25'))
1007 self.assertEqual(d2**d1, Decimal('32'))
1008
1009 #with other type, left
1010 c = d1 ** 4
1011 self.assertEqual(c, Decimal('625'))
1012 self.assertEqual(type(c), type(d1))
1013
1014 #with other type, right
1015 c = 7 ** d1
1016 self.assertEqual(c, Decimal('16807'))
1017 self.assertEqual(type(c), type(d1))
1018
1019 #inline with decimal
1020 d1 **= d2
1021 self.assertEqual(d1, Decimal('25'))
1022
1023 #inline with other type
1024 d1 **= 4
1025 self.assertEqual(d1, Decimal('390625'))
1026
1027 def test_module(self):
1028
1029 d1 = Decimal('5')
1030 d2 = Decimal('2')
1031
1032 #two Decimals
1033 self.assertEqual(d1%d2, Decimal('1'))
1034 self.assertEqual(d2%d1, Decimal('2'))
1035
1036 #with other type, left
1037 c = d1 % 4
1038 self.assertEqual(c, Decimal('1'))
1039 self.assertEqual(type(c), type(d1))
1040
1041 #with other type, right
1042 c = 7 % d1
1043 self.assertEqual(c, Decimal('2'))
1044 self.assertEqual(type(c), type(d1))
1045
1046 #inline with decimal
1047 d1 %= d2
1048 self.assertEqual(d1, Decimal('1'))
1049
1050 #inline with other type
1051 d1 %= 4
1052 self.assertEqual(d1, Decimal('1'))
1053
1054 def test_floor_div_module(self):
1055
1056 d1 = Decimal('5')
1057 d2 = Decimal('2')
1058
1059 #two Decimals
1060 (p, q) = divmod(d1, d2)
1061 self.assertEqual(p, Decimal('2'))
1062 self.assertEqual(q, Decimal('1'))
1063 self.assertEqual(type(p), type(d1))
1064 self.assertEqual(type(q), type(d1))
1065
1066 #with other type, left
1067 (p, q) = divmod(d1, 4)
1068 self.assertEqual(p, Decimal('1'))
1069 self.assertEqual(q, Decimal('1'))
1070 self.assertEqual(type(p), type(d1))
1071 self.assertEqual(type(q), type(d1))
1072
1073 #with other type, right
1074 (p, q) = divmod(7, d1)
1075 self.assertEqual(p, Decimal('1'))
1076 self.assertEqual(q, Decimal('2'))
1077 self.assertEqual(type(p), type(d1))
1078 self.assertEqual(type(q), type(d1))
1079
1080 def test_unary_operators(self):
1081 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1082 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1083 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1084
Christian Heimes77c02eb2008-02-09 02:18:51 +00001085 def test_nan_comparisons(self):
1086 n = Decimal('NaN')
1087 s = Decimal('sNaN')
1088 i = Decimal('Inf')
1089 f = Decimal('2')
1090 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1091 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Georg Brandlab91fde2009-08-13 08:51:18 +00001092 self.assertTrue(x != y)
1093 self.assertTrue(not (x == y))
1094 self.assertTrue(not (x < y))
1095 self.assertTrue(not (x <= y))
1096 self.assertTrue(not (x > y))
1097 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001098
1099# The following are two functions used to test threading in the next class
1100
1101def thfunc1(cls):
1102 d1 = Decimal(1)
1103 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001104 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001105 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001106 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001107 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001108
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001109 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1110 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001111 return
1112
1113def thfunc2(cls):
1114 d1 = Decimal(1)
1115 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001116 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001117 thiscontext = getcontext()
1118 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001119 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001120 cls.synchro.set()
1121 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001122
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001123 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001124 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001125 return
1126
1127
1128class DecimalUseOfContextTest(unittest.TestCase):
1129 '''Unit tests for Use of Context cases in Decimal.'''
1130
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001131 try:
1132 import threading
1133 except ImportError:
1134 threading = None
1135
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001136 # Take care executing this test from IDLE, there's an issue in threading
1137 # that hangs IDLE and I couldn't find it
1138
1139 def test_threading(self):
1140 #Test the "threading isolation" of a Context.
1141
1142 self.synchro = threading.Event()
1143 self.finish1 = threading.Event()
1144 self.finish2 = threading.Event()
1145
1146 th1 = threading.Thread(target=thfunc1, args=(self,))
1147 th2 = threading.Thread(target=thfunc2, args=(self,))
1148
1149 th1.start()
1150 th2.start()
1151
1152 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001153 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001154 return
1155
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001156 if threading is None:
1157 del test_threading
1158
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001159
1160class DecimalUsabilityTest(unittest.TestCase):
1161 '''Unit tests for Usability cases of Decimal.'''
1162
1163 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001164
1165 da = Decimal('23.42')
1166 db = Decimal('23.42')
1167 dc = Decimal('45')
1168
1169 #two Decimals
Georg Brandlab91fde2009-08-13 08:51:18 +00001170 self.assertTrue(dc > da)
1171 self.assertTrue(dc >= da)
1172 self.assertTrue(da < dc)
1173 self.assertTrue(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001174 self.assertEqual(da, db)
Georg Brandlab91fde2009-08-13 08:51:18 +00001175 self.assertTrue(da != dc)
1176 self.assertTrue(da <= db)
1177 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178
1179 #a Decimal and an int
Georg Brandlab91fde2009-08-13 08:51:18 +00001180 self.assertTrue(dc > 23)
1181 self.assertTrue(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001182 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183
1184 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001185 self.assertNotEqual(da, 'ugly')
1186 self.assertNotEqual(da, 32.7)
1187 self.assertNotEqual(da, object())
1188 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001190 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001191 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001192 b = a[:]
1193 random.shuffle(a)
1194 a.sort()
1195 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196
1197 def test_copy_and_deepcopy_methods(self):
1198 d = Decimal('43.24')
1199 c = copy.copy(d)
1200 self.assertEqual(id(c), id(d))
1201 dc = copy.deepcopy(d)
1202 self.assertEqual(id(dc), id(d))
1203
1204 def test_hash_method(self):
1205 #just that it's hashable
1206 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001207
1208 test_values = [Decimal(sign*(2**m + n))
1209 for m in [0, 14, 15, 16, 17, 30, 31,
1210 32, 33, 62, 63, 64, 65, 66]
1211 for n in range(-10, 10)
1212 for sign in [-1, 1]]
1213 test_values.extend([
1214 Decimal("-0"), # zeros
1215 Decimal("0.00"),
1216 Decimal("-0.000"),
1217 Decimal("0E10"),
1218 Decimal("-0E12"),
1219 Decimal("10.0"), # negative exponent
1220 Decimal("-23.00000"),
1221 Decimal("1230E100"), # positive exponent
1222 Decimal("-4.5678E50"),
1223 # a value for which hash(n) != hash(n % (2**64-1))
1224 # in Python pre-2.6
1225 Decimal(2**64 + 2**32 - 1),
1226 # selection of values which fail with the old (before
1227 # version 2.6) long.__hash__
1228 Decimal("1.634E100"),
1229 Decimal("90.697E100"),
1230 Decimal("188.83E100"),
1231 Decimal("1652.9E100"),
1232 Decimal("56531E100"),
1233 ])
1234
1235 # check that hash(d) == hash(int(d)) for integral values
1236 for value in test_values:
1237 self.assertEqual(hash(value), hash(int(value)))
1238
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239 #the same hash that to an int
1240 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001241 self.assertRaises(TypeError, hash, Decimal('NaN'))
Georg Brandlab91fde2009-08-13 08:51:18 +00001242 self.assertTrue(hash(Decimal('Inf')))
1243 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244
Christian Heimes2380ac72008-01-09 00:17:24 +00001245 # check that the value of the hash doesn't depend on the
1246 # current context (issue #1757)
1247 c = getcontext()
1248 old_precision = c.prec
1249 x = Decimal("123456789.1")
1250
1251 c.prec = 6
1252 h1 = hash(x)
1253 c.prec = 10
1254 h2 = hash(x)
1255 c.prec = 16
1256 h3 = hash(x)
1257
1258 self.assertEqual(h1, h2)
1259 self.assertEqual(h1, h3)
1260 c.prec = old_precision
1261
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001262 def test_min_and_max_methods(self):
1263
1264 d1 = Decimal('15.32')
1265 d2 = Decimal('28.5')
1266 l1 = 15
1267 l2 = 28
1268
1269 #between Decimals
Georg Brandlab91fde2009-08-13 08:51:18 +00001270 self.assertTrue(min(d1,d2) is d1)
1271 self.assertTrue(min(d2,d1) is d1)
1272 self.assertTrue(max(d1,d2) is d2)
1273 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001274
1275 #between Decimal and long
Georg Brandlab91fde2009-08-13 08:51:18 +00001276 self.assertTrue(min(d1,l2) is d1)
1277 self.assertTrue(min(l2,d1) is d1)
1278 self.assertTrue(max(l1,d2) is d2)
1279 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001280
1281 def test_as_nonzero(self):
1282 #as false
Georg Brandlab91fde2009-08-13 08:51:18 +00001283 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001284 #as true
Georg Brandlab91fde2009-08-13 08:51:18 +00001285 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001286
1287 def test_tostring_methods(self):
1288 #Test str and repr methods.
1289
1290 d = Decimal('15.32')
1291 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001292 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001293
1294 def test_tonum_methods(self):
1295 #Test float, int and long methods.
1296
1297 d1 = Decimal('66')
1298 d2 = Decimal('15.32')
1299
1300 #int
1301 self.assertEqual(int(d1), 66)
1302 self.assertEqual(int(d2), 15)
1303
1304 #long
Guido van Rossume2a383d2007-01-15 16:59:06 +00001305 self.assertEqual(int(d1), 66)
1306 self.assertEqual(int(d2), 15)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001307
1308 #float
1309 self.assertEqual(float(d1), 66)
1310 self.assertEqual(float(d2), 15.32)
1311
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001312 #floor
1313 test_pairs = [
1314 ('123.00', 123),
1315 ('3.2', 3),
1316 ('3.54', 3),
1317 ('3.899', 3),
1318 ('-2.3', -3),
1319 ('-11.0', -11),
1320 ('0.0', 0),
1321 ('-0E3', 0),
1322 ]
1323 for d, i in test_pairs:
1324 self.assertEqual(math.floor(Decimal(d)), i)
1325 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1326 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1327 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1328 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1329 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1330
1331 #ceiling
1332 test_pairs = [
1333 ('123.00', 123),
1334 ('3.2', 4),
1335 ('3.54', 4),
1336 ('3.899', 4),
1337 ('-2.3', -2),
1338 ('-11.0', -11),
1339 ('0.0', 0),
1340 ('-0E3', 0),
1341 ]
1342 for d, i in test_pairs:
1343 self.assertEqual(math.ceil(Decimal(d)), i)
1344 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1345 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1346 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1347 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1348 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1349
1350 #round, single argument
1351 test_pairs = [
1352 ('123.00', 123),
1353 ('3.2', 3),
1354 ('3.54', 4),
1355 ('3.899', 4),
1356 ('-2.3', -2),
1357 ('-11.0', -11),
1358 ('0.0', 0),
1359 ('-0E3', 0),
1360 ('-3.5', -4),
1361 ('-2.5', -2),
1362 ('-1.5', -2),
1363 ('-0.5', 0),
1364 ('0.5', 0),
1365 ('1.5', 2),
1366 ('2.5', 2),
1367 ('3.5', 4),
1368 ]
1369 for d, i in test_pairs:
1370 self.assertEqual(round(Decimal(d)), i)
1371 self.assertRaises(ValueError, round, Decimal('-NaN'))
1372 self.assertRaises(ValueError, round, Decimal('sNaN'))
1373 self.assertRaises(ValueError, round, Decimal('NaN123'))
1374 self.assertRaises(OverflowError, round, Decimal('Inf'))
1375 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1376
1377 #round, two arguments; this is essentially equivalent
1378 #to quantize, which is already extensively tested
1379 test_triples = [
1380 ('123.456', -4, '0E+4'),
1381 ('123.456', -3, '0E+3'),
1382 ('123.456', -2, '1E+2'),
1383 ('123.456', -1, '1.2E+2'),
1384 ('123.456', 0, '123'),
1385 ('123.456', 1, '123.5'),
1386 ('123.456', 2, '123.46'),
1387 ('123.456', 3, '123.456'),
1388 ('123.456', 4, '123.4560'),
1389 ('123.455', 2, '123.46'),
1390 ('123.445', 2, '123.44'),
1391 ('Inf', 4, 'NaN'),
1392 ('-Inf', -23, 'NaN'),
1393 ('sNaN314', 3, 'NaN314'),
1394 ]
1395 for d, n, r in test_triples:
1396 self.assertEqual(str(round(Decimal(d), n)), r)
1397
1398
1399
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001400 def test_eval_round_trip(self):
1401
1402 #with zero
1403 d = Decimal( (0, (0,), 0) )
1404 self.assertEqual(d, eval(repr(d)))
1405
1406 #int
1407 d = Decimal( (1, (4, 5), 0) )
1408 self.assertEqual(d, eval(repr(d)))
1409
1410 #float
1411 d = Decimal( (0, (4, 5, 3, 4), -2) )
1412 self.assertEqual(d, eval(repr(d)))
1413
1414 #weird
1415 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1416 self.assertEqual(d, eval(repr(d)))
1417
1418 def test_as_tuple(self):
1419
1420 #with zero
1421 d = Decimal(0)
1422 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1423
1424 #int
1425 d = Decimal(-45)
1426 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1427
1428 #complicated string
1429 d = Decimal("-4.34913534E-17")
1430 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1431
1432 #inf
1433 d = Decimal("Infinity")
1434 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1435
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001436 #leading zeros in coefficient should be stripped
1437 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1438 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1439 d = Decimal( (1, (0, 0, 0), 37) )
1440 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1441 d = Decimal( (1, (), 37) )
1442 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1443
1444 #leading zeros in NaN diagnostic info should be stripped
1445 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1446 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1447 d = Decimal( (1, (0, 0, 0), 'N') )
1448 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1449 d = Decimal( (1, (), 'n') )
1450 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1451
1452 #coefficient in infinity should be ignored
1453 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1454 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1455 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1456 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1457
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001458 def test_immutability_operations(self):
1459 # Do operations and check that it didn't change change internal objects.
1460
1461 d1 = Decimal('-25e55')
1462 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001463 d2 = Decimal('33e+33')
1464 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001465
1466 def checkSameDec(operation, useOther=False):
1467 if useOther:
1468 eval("d1." + operation + "(d2)")
1469 self.assertEqual(d1._sign, b1._sign)
1470 self.assertEqual(d1._int, b1._int)
1471 self.assertEqual(d1._exp, b1._exp)
1472 self.assertEqual(d2._sign, b2._sign)
1473 self.assertEqual(d2._int, b2._int)
1474 self.assertEqual(d2._exp, b2._exp)
1475 else:
1476 eval("d1." + operation + "()")
1477 self.assertEqual(d1._sign, b1._sign)
1478 self.assertEqual(d1._int, b1._int)
1479 self.assertEqual(d1._exp, b1._exp)
1480 return
1481
1482 Decimal(d1)
1483 self.assertEqual(d1._sign, b1._sign)
1484 self.assertEqual(d1._int, b1._int)
1485 self.assertEqual(d1._exp, b1._exp)
1486
1487 checkSameDec("__abs__")
1488 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001489 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001490 checkSameDec("__eq__", True)
1491 checkSameDec("__ne__", True)
1492 checkSameDec("__le__", True)
1493 checkSameDec("__lt__", True)
1494 checkSameDec("__ge__", True)
1495 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001496 checkSameDec("__float__")
1497 checkSameDec("__floordiv__", True)
1498 checkSameDec("__hash__")
1499 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001500 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001501 checkSameDec("__mod__", True)
1502 checkSameDec("__mul__", True)
1503 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001504 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001505 checkSameDec("__pos__")
1506 checkSameDec("__pow__", True)
1507 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001508 checkSameDec("__rdivmod__", True)
1509 checkSameDec("__repr__")
1510 checkSameDec("__rfloordiv__", True)
1511 checkSameDec("__rmod__", True)
1512 checkSameDec("__rmul__", True)
1513 checkSameDec("__rpow__", True)
1514 checkSameDec("__rsub__", True)
1515 checkSameDec("__str__")
1516 checkSameDec("__sub__", True)
1517 checkSameDec("__truediv__", True)
1518 checkSameDec("adjusted")
1519 checkSameDec("as_tuple")
1520 checkSameDec("compare", True)
1521 checkSameDec("max", True)
1522 checkSameDec("min", True)
1523 checkSameDec("normalize")
1524 checkSameDec("quantize", True)
1525 checkSameDec("remainder_near", True)
1526 checkSameDec("same_quantum", True)
1527 checkSameDec("sqrt")
1528 checkSameDec("to_eng_string")
1529 checkSameDec("to_integral")
1530
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001531 def test_subclassing(self):
1532 # Different behaviours when subclassing Decimal
1533
1534 class MyDecimal(Decimal):
1535 pass
1536
1537 d1 = MyDecimal(1)
1538 d2 = MyDecimal(2)
1539 d = d1 + d2
1540 self.assertTrue(type(d) is Decimal)
1541
1542 d = d1.max(d2)
1543 self.assertTrue(type(d) is Decimal)
1544
Christian Heimes0348fb62008-03-26 12:55:56 +00001545 def test_implicit_context(self):
1546 # Check results when context given implicitly. (Issue 2478)
1547 c = getcontext()
1548 self.assertEqual(str(Decimal(0).sqrt()),
1549 str(c.sqrt(Decimal(0))))
1550
Mark Dickinson9050bb22009-10-29 12:25:07 +00001551 def test_conversions_from_int(self):
1552 # Check that methods taking a second Decimal argument will
1553 # always accept an integer in place of a Decimal.
1554 self.assertEqual(Decimal(4).compare(3),
1555 Decimal(4).compare(Decimal(3)))
1556 self.assertEqual(Decimal(4).compare_signal(3),
1557 Decimal(4).compare_signal(Decimal(3)))
1558 self.assertEqual(Decimal(4).compare_total(3),
1559 Decimal(4).compare_total(Decimal(3)))
1560 self.assertEqual(Decimal(4).compare_total_mag(3),
1561 Decimal(4).compare_total_mag(Decimal(3)))
1562 self.assertEqual(Decimal(10101).logical_and(1001),
1563 Decimal(10101).logical_and(Decimal(1001)))
1564 self.assertEqual(Decimal(10101).logical_or(1001),
1565 Decimal(10101).logical_or(Decimal(1001)))
1566 self.assertEqual(Decimal(10101).logical_xor(1001),
1567 Decimal(10101).logical_xor(Decimal(1001)))
1568 self.assertEqual(Decimal(567).max(123),
1569 Decimal(567).max(Decimal(123)))
1570 self.assertEqual(Decimal(567).max_mag(123),
1571 Decimal(567).max_mag(Decimal(123)))
1572 self.assertEqual(Decimal(567).min(123),
1573 Decimal(567).min(Decimal(123)))
1574 self.assertEqual(Decimal(567).min_mag(123),
1575 Decimal(567).min_mag(Decimal(123)))
1576 self.assertEqual(Decimal(567).next_toward(123),
1577 Decimal(567).next_toward(Decimal(123)))
1578 self.assertEqual(Decimal(1234).quantize(100),
1579 Decimal(1234).quantize(Decimal(100)))
1580 self.assertEqual(Decimal(768).remainder_near(1234),
1581 Decimal(768).remainder_near(Decimal(1234)))
1582 self.assertEqual(Decimal(123).rotate(1),
1583 Decimal(123).rotate(Decimal(1)))
1584 self.assertEqual(Decimal(1234).same_quantum(1000),
1585 Decimal(1234).same_quantum(Decimal(1000)))
1586 self.assertEqual(Decimal('9.123').scaleb(-100),
1587 Decimal('9.123').scaleb(Decimal(-100)))
1588 self.assertEqual(Decimal(456).shift(-1),
1589 Decimal(456).shift(Decimal(-1)))
1590
1591 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1592 Decimal(-12).fma(Decimal(45), Decimal(67)))
1593 self.assertEqual(Decimal(-12).fma(45, 67),
1594 Decimal(-12).fma(Decimal(45), Decimal(67)))
1595 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1596 Decimal(-12).fma(Decimal(45), Decimal(67)))
1597
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001598
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001599class DecimalPythonAPItests(unittest.TestCase):
1600
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001601 def test_abc(self):
Georg Brandlab91fde2009-08-13 08:51:18 +00001602 self.assertTrue(issubclass(Decimal, numbers.Number))
1603 self.assertTrue(not issubclass(Decimal, numbers.Real))
1604 self.assertTrue(isinstance(Decimal(0), numbers.Number))
1605 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001606
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001607 def test_pickle(self):
1608 d = Decimal('-3.141590000')
1609 p = pickle.dumps(d)
1610 e = pickle.loads(p)
1611 self.assertEqual(d, e)
1612
Raymond Hettinger5548be22004-07-05 18:49:38 +00001613 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001614 for x in range(-250, 250):
1615 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001616 # should work the same as for floats
1617 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001618 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001619 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001620 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001621 self.assertEqual(Decimal(int(d)), r)
1622
Mark Dickinson8fde3da2009-09-08 19:23:44 +00001623 self.assertRaises(ValueError, int, Decimal('-nan'))
1624 self.assertRaises(ValueError, int, Decimal('snan'))
1625 self.assertRaises(OverflowError, int, Decimal('inf'))
1626 self.assertRaises(OverflowError, int, Decimal('-inf'))
1627
Christian Heimes969fe572008-01-25 11:23:10 +00001628 def test_trunc(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)
Christian Heimes400adb02008-02-01 08:12:03 +00001636 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001637
Raymond Hettinger771ed762009-01-03 19:20:32 +00001638 def test_from_float(self):
1639
1640 class MyDecimal(Decimal):
1641 pass
1642
1643 r = MyDecimal.from_float(0.1)
1644 self.assertEqual(type(r), MyDecimal)
1645 self.assertEqual(str(r),
1646 '0.1000000000000000055511151231257827021181583404541015625')
1647 bigint = 12345678901234567890123456789
1648 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Georg Brandlab91fde2009-08-13 08:51:18 +00001649 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1650 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1651 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001652 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1653 str(Decimal('NaN')))
1654 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1655 str(Decimal('Infinity')))
1656 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1657 str(Decimal('-Infinity')))
1658 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1659 for i in range(200):
1660 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1661 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1662
1663 def test_create_decimal_from_float(self):
1664 context = Context(prec=5, rounding=ROUND_DOWN)
1665 self.assertEqual(
1666 context.create_decimal_from_float(math.pi),
1667 Decimal('3.1415')
1668 )
1669 context = Context(prec=5, rounding=ROUND_UP)
1670 self.assertEqual(
1671 context.create_decimal_from_float(math.pi),
1672 Decimal('3.1416')
1673 )
1674 context = Context(prec=5, traps=[Inexact])
1675 self.assertRaises(
1676 Inexact,
1677 context.create_decimal_from_float,
1678 math.pi
1679 )
1680 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1681 "Decimal('-0')")
1682 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1683 "Decimal('1')")
1684 self.assertEqual(repr(context.create_decimal_from_float(10)),
1685 "Decimal('10')")
1686
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001687class ContextAPItests(unittest.TestCase):
1688
1689 def test_pickle(self):
1690 c = Context()
1691 e = pickle.loads(pickle.dumps(c))
1692 for k in vars(c):
1693 v1 = vars(c)[k]
1694 v2 = vars(e)[k]
1695 self.assertEqual(v1, v2)
1696
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001697 def test_equality_with_other_types(self):
Georg Brandlab91fde2009-08-13 08:51:18 +00001698 self.assertTrue(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1699 self.assertTrue(Decimal(10) not in ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001700
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001701 def test_copy(self):
1702 # All copies should be deep
1703 c = Context()
1704 d = c.copy()
1705 self.assertNotEqual(id(c), id(d))
1706 self.assertNotEqual(id(c.flags), id(d.flags))
1707 self.assertNotEqual(id(c.traps), id(d.traps))
1708
Thomas Wouters89f507f2006-12-13 04:49:30 +00001709class WithStatementTest(unittest.TestCase):
1710 # Can't do these as docstrings until Python 2.6
1711 # as doctest can't handle __future__ statements
1712
1713 def test_localcontext(self):
1714 # Use a copy of the current context in the block
1715 orig_ctx = getcontext()
1716 with localcontext() as enter_ctx:
1717 set_ctx = getcontext()
1718 final_ctx = getcontext()
Georg Brandlab91fde2009-08-13 08:51:18 +00001719 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
1720 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
1721 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00001722
1723 def test_localcontextarg(self):
1724 # Use a copy of the supplied context in the block
1725 orig_ctx = getcontext()
1726 new_ctx = Context(prec=42)
1727 with localcontext(new_ctx) as enter_ctx:
1728 set_ctx = getcontext()
1729 final_ctx = getcontext()
Georg Brandlab91fde2009-08-13 08:51:18 +00001730 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
1731 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1732 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
1733 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00001734
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001735class ContextFlags(unittest.TestCase):
1736 def test_flags_irrelevant(self):
1737 # check that the result (numeric result + flags raised) of an
1738 # arithmetic operation doesn't depend on the current flags
1739
1740 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1741 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1742
1743 # operations that raise various flags, in the form (function, arglist)
1744 operations = [
1745 (context._apply, [Decimal("100E-1000000009")]),
1746 (context.sqrt, [Decimal(2)]),
1747 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1748 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1749 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1750 ]
1751
1752 # try various flags individually, then a whole lot at once
1753 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1754 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1755
1756 for fn, args in operations:
1757 # find answer and flags raised using a clean context
1758 context.clear_flags()
1759 ans = fn(*args)
1760 flags = [k for k, v in context.flags.items() if v]
1761
1762 for extra_flags in flagsets:
1763 # set flags, before calling operation
1764 context.clear_flags()
1765 for flag in extra_flags:
1766 context._raise_error(flag)
1767 new_ans = fn(*args)
1768
1769 # flags that we expect to be set after the operation
1770 expected_flags = list(flags)
1771 for flag in extra_flags:
1772 if flag not in expected_flags:
1773 expected_flags.append(flag)
1774 expected_flags.sort(key=id)
1775
1776 # flags we actually got
1777 new_flags = [k for k,v in context.flags.items() if v]
1778 new_flags.sort(key=id)
1779
1780 self.assertEqual(ans, new_ans,
1781 "operation produces different answers depending on flags set: " +
1782 "expected %s, got %s." % (ans, new_ans))
1783 self.assertEqual(new_flags, expected_flags,
1784 "operation raises different flags depending on flags set: " +
1785 "expected %s, got %s" % (expected_flags, new_flags))
1786
1787def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001788 """ Execute the tests.
1789
Raymond Hettingered20ad82004-09-04 20:09:13 +00001790 Runs all arithmetic tests if arith is True or if the "decimal" resource
1791 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001792 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001793
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001794 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001795 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001796 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001797 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001798
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001799 if todo_tests is None:
1800 test_classes = [
1801 DecimalExplicitConstructionTest,
1802 DecimalImplicitConstructionTest,
1803 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00001804 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001805 DecimalUseOfContextTest,
1806 DecimalUsabilityTest,
1807 DecimalPythonAPItests,
1808 ContextAPItests,
1809 DecimalTest,
1810 WithStatementTest,
1811 ContextFlags
1812 ]
1813 else:
1814 test_classes = [DecimalTest]
1815
1816 # Dynamically build custom test definition for each file in the test
1817 # directory and add the definitions to the DecimalTest class. This
1818 # procedure insures that new files do not get skipped.
1819 for filename in os.listdir(directory):
1820 if '.decTest' not in filename or filename.startswith("."):
1821 continue
1822 head, tail = filename.split('.')
1823 if todo_tests is not None and head not in todo_tests:
1824 continue
1825 tester = lambda self, f=filename: self.eval_file(directory + f)
1826 setattr(DecimalTest, 'test_' + head, tester)
1827 del filename, head, tail, tester
1828
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001829
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001830 try:
1831 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001832 if todo_tests is None:
1833 import decimal as DecimalModule
1834 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001835 finally:
1836 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001837
1838if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001839 import optparse
1840 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1841 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1842 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1843 (opt, args) = p.parse_args()
1844
1845 if opt.skip:
1846 test_main(arith=False, verbose=True)
1847 elif args:
1848 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001850 test_main(arith=True, verbose=True)