blob: ec381e4139532d69bad81aaad7cf285b40df31db [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
Antoine Pitrouea5d8272010-10-14 22:14:36 +0000221 with open(file) as f:
222 for line in f:
223 line = line.replace('\r\n', '').replace('\n', '')
224 #print line
225 try:
226 t = self.eval_line(line)
227 except DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200228 #Exception raised where there shouldn't have been one.
Antoine Pitrouea5d8272010-10-14 22:14:36 +0000229 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000230
231 return
232
233 def eval_line(self, s):
234 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
235 s = (s.split('->')[0] + '->' +
236 s.split('->')[1].split('--')[0]).strip()
237 else:
238 s = s.split('--')[0].strip()
239
240 for ignore in self.ignore_list:
241 if s.find(ignore) >= 0:
242 #print s.split()[0], 'NotImplemented--', ignore
243 return
244 if not s:
245 return
246 elif ':' in s:
247 return self.eval_directive(s)
248 else:
249 return self.eval_equation(s)
250
251 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000252 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000253 if funct == 'rounding':
254 value = RoundingDict[value]
255 else:
256 try:
257 value = int(value)
258 except ValueError:
259 pass
260
261 funct = self.ChangeDict.get(funct, Nonfunction)
262 funct(value)
263
264 def eval_equation(self, s):
265 #global DEFAULT_PRECISION
266 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000267
268 if not TEST_ALL and random.random() < 0.90:
269 return
270
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000271 try:
272 Sides = s.split('->')
273 L = Sides[0].strip().split()
274 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000275 if DEBUG:
276 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 funct = L[1].lower()
278 valstemp = L[2:]
279 L = Sides[1].strip().split()
280 ans = L[0]
281 exceptions = L[1:]
282 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000283 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000284 def FixQuotes(val):
285 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
286 val = val.replace("'", '').replace('"', '')
287 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
288 return val
Mark Dickinsond08fb832009-10-08 16:33:06 +0000289
290 if id in skipped_test_ids:
291 return
292
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 fname = nameAdapter.get(funct, funct)
294 if fname == 'rescale':
295 return
296 funct = getattr(self.context, fname)
297 vals = []
298 conglomerate = ''
299 quote = 0
300 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
301
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000302 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000303 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000305 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000306 for i, val in enumerate(valstemp):
307 if val.count("'") % 2 == 1:
308 quote = 1 - quote
309 if quote:
310 conglomerate = conglomerate + ' ' + val
311 continue
312 else:
313 val = conglomerate + val
314 conglomerate = ''
315 v = FixQuotes(val)
316 if fname in ('to_sci_string', 'to_eng_string'):
317 if EXTENDEDERRORTEST:
318 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000319 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 try:
321 funct(self.context.create_decimal(v))
322 except error:
323 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000324 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 self.fail("Raised %s in %s when %s disabled" % \
326 (e, s, error))
327 else:
328 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000329 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 v = self.context.create_decimal(v)
331 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000332 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000333 vals.append(v)
334
335 ans = FixQuotes(ans)
336
337 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
338 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000339 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 try:
341 funct(*vals)
342 except error:
343 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000344 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 self.fail("Raised %s in %s when %s disabled" % \
346 (e, s, error))
347 else:
348 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000349 self.context.traps[error] = 0
Mark Dickinsonece06972010-05-04 14:37:14 +0000350
351 # as above, but add traps cumulatively, to check precedence
352 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
353 for error in ordered_errors:
354 self.context.traps[error] = 1
355 try:
356 funct(*vals)
357 except error:
358 pass
359 except Signals as e:
360 self.fail("Raised %s in %s; expected %s" %
361 (type(e), s, error))
362 else:
363 self.fail("Did not raise %s in %s" % (error, s))
364 # reset traps
365 for error in ordered_errors:
366 self.context.traps[error] = 0
367
368
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000369 if DEBUG:
370 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371 try:
372 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000373 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000375 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 self.fail("Raised %s in %s" % (error, s))
377 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000378 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 raise
380
381 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000382 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000383
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000384 myexceptions.sort(key=repr)
385 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386
387 self.assertEqual(result, ans,
388 'Incorrect answer for ' + s + ' -- got ' + result)
389 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000390 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 return
392
393 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000394 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 def change_precision(self, prec):
397 self.context.prec = prec
398 def change_rounding_method(self, rounding):
399 self.context.rounding = rounding
400 def change_min_exponent(self, exp):
401 self.context.Emin = exp
402 def change_max_exponent(self, exp):
403 self.context.Emax = exp
404 def change_clamp(self, clamp):
405 self.context._clamp = clamp
406
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407
408
409# The following classes test the behaviour of Decimal according to PEP 327
410
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411class DecimalExplicitConstructionTest(unittest.TestCase):
412 '''Unit tests for Explicit Construction cases of Decimal.'''
413
414 def test_explicit_empty(self):
415 self.assertEqual(Decimal(), Decimal("0"))
416
417 def test_explicit_from_None(self):
418 self.assertRaises(TypeError, Decimal, None)
419
420 def test_explicit_from_int(self):
421
422 #positive
423 d = Decimal(45)
424 self.assertEqual(str(d), '45')
425
426 #very large positive
427 d = Decimal(500000123)
428 self.assertEqual(str(d), '500000123')
429
430 #negative
431 d = Decimal(-45)
432 self.assertEqual(str(d), '-45')
433
434 #zero
435 d = Decimal(0)
436 self.assertEqual(str(d), '0')
437
438 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000439
440 #empty
441 self.assertEqual(str(Decimal('')), 'NaN')
442
443 #int
444 self.assertEqual(str(Decimal('45')), '45')
445
446 #float
447 self.assertEqual(str(Decimal('45.34')), '45.34')
448
449 #engineer notation
450 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
451
452 #just not a number
453 self.assertEqual(str(Decimal('ugly')), 'NaN')
454
Christian Heimesa62da1d2008-01-12 19:39:10 +0000455 #leading and trailing whitespace permitted
456 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
457 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
458
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000459 def test_explicit_from_tuples(self):
460
461 #zero
462 d = Decimal( (0, (0,), 0) )
463 self.assertEqual(str(d), '0')
464
465 #int
466 d = Decimal( (1, (4, 5), 0) )
467 self.assertEqual(str(d), '-45')
468
469 #float
470 d = Decimal( (0, (4, 5, 3, 4), -2) )
471 self.assertEqual(str(d), '45.34')
472
473 #weird
474 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
475 self.assertEqual(str(d), '-4.34913534E-17')
476
477 #wrong number of items
478 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
479
480 #bad sign
481 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000482 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
483 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000484
485 #bad exp
486 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000487 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
488 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000489
490 #bad coefficients
491 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
492 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495
496 def test_explicit_from_Decimal(self):
497
498 #positive
499 d = Decimal(45)
500 e = Decimal(d)
501 self.assertEqual(str(e), '45')
502 self.assertNotEqual(id(d), id(e))
503
504 #very large positive
505 d = Decimal(500000123)
506 e = Decimal(d)
507 self.assertEqual(str(e), '500000123')
508 self.assertNotEqual(id(d), id(e))
509
510 #negative
511 d = Decimal(-45)
512 e = Decimal(d)
513 self.assertEqual(str(e), '-45')
514 self.assertNotEqual(id(d), id(e))
515
516 #zero
517 d = Decimal(0)
518 e = Decimal(d)
519 self.assertEqual(str(e), '0')
520 self.assertNotEqual(id(d), id(e))
521
522 def test_explicit_context_create_decimal(self):
523
524 nc = copy.copy(getcontext())
525 nc.prec = 3
526
527 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000528 d = Decimal()
529 self.assertEqual(str(d), '0')
530 d = nc.create_decimal()
531 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000532
533 # from None
534 self.assertRaises(TypeError, nc.create_decimal, None)
535
536 # from int
537 d = nc.create_decimal(456)
Georg Brandlab91fde2009-08-13 08:51:18 +0000538 self.assertTrue(isinstance(d, Decimal))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000539 self.assertEqual(nc.create_decimal(45678),
540 nc.create_decimal('457E+2'))
541
542 # from string
543 d = Decimal('456789')
544 self.assertEqual(str(d), '456789')
545 d = nc.create_decimal('456789')
546 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000547 # leading and trailing whitespace should result in a NaN;
548 # spaces are already checked in Cowlishaw's test-suite, so
549 # here we just check that a trailing newline results in a NaN
550 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000551
552 # from tuples
553 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
554 self.assertEqual(str(d), '-4.34913534E-17')
555 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
556 self.assertEqual(str(d), '-4.35E-17')
557
558 # from Decimal
559 prevdec = Decimal(500000123)
560 d = Decimal(prevdec)
561 self.assertEqual(str(d), '500000123')
562 d = nc.create_decimal(prevdec)
563 self.assertEqual(str(d), '5.00E+8')
564
Mark Dickinson8d238292009-08-02 10:16:33 +0000565 def test_unicode_digits(self):
566 test_values = {
567 '\uff11': '1',
568 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
569 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
570 }
571 for input, expected in test_values.items():
572 self.assertEqual(str(Decimal(input)), expected)
573
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000574
575class DecimalImplicitConstructionTest(unittest.TestCase):
576 '''Unit tests for Implicit Construction cases of Decimal.'''
577
578 def test_implicit_from_None(self):
579 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
580
581 def test_implicit_from_int(self):
582 #normal
583 self.assertEqual(str(Decimal(5) + 45), '50')
584 #exceeding precision
585 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
586
587 def test_implicit_from_string(self):
588 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
589
590 def test_implicit_from_float(self):
591 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
592
593 def test_implicit_from_Decimal(self):
594 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
595
Raymond Hettinger267b8682005-03-27 10:47:39 +0000596 def test_rop(self):
597 # Allow other classes to be trained to interact with Decimals
598 class E:
599 def __divmod__(self, other):
600 return 'divmod ' + str(other)
601 def __rdivmod__(self, other):
602 return str(other) + ' rdivmod'
603 def __lt__(self, other):
604 return 'lt ' + str(other)
605 def __gt__(self, other):
606 return 'gt ' + str(other)
607 def __le__(self, other):
608 return 'le ' + str(other)
609 def __ge__(self, other):
610 return 'ge ' + str(other)
611 def __eq__(self, other):
612 return 'eq ' + str(other)
613 def __ne__(self, other):
614 return 'ne ' + str(other)
615
616 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
617 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
618 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
619 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
620 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
621 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
622 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
623 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
624
625 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000626 oplist = [
627 ('+', '__add__', '__radd__'),
628 ('-', '__sub__', '__rsub__'),
629 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000630 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000631 ('%', '__mod__', '__rmod__'),
632 ('//', '__floordiv__', '__rfloordiv__'),
633 ('**', '__pow__', '__rpow__')
634 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000635
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000636 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000637 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
638 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
639 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
640 'str' + lop + '10')
641 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
642 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000643
Mark Dickinson79f52032009-03-17 23:12:51 +0000644
Christian Heimesf16baeb2008-02-29 14:57:44 +0000645class DecimalFormatTest(unittest.TestCase):
646 '''Unit tests for the format function.'''
647 def test_formatting(self):
648 # triples giving a format, a Decimal, and the expected result
649 test_values = [
650 ('e', '0E-15', '0e-15'),
651 ('e', '2.3E-15', '2.3e-15'),
652 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
653 ('e', '2.30000E-15', '2.30000e-15'),
654 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
655 ('e', '1.5', '1.5e+0'),
656 ('e', '0.15', '1.5e-1'),
657 ('e', '0.015', '1.5e-2'),
658 ('e', '0.0000000000015', '1.5e-12'),
659 ('e', '15.0', '1.50e+1'),
660 ('e', '-15', '-1.5e+1'),
661 ('e', '0', '0e+0'),
662 ('e', '0E1', '0e+1'),
663 ('e', '0.0', '0e-1'),
664 ('e', '0.00', '0e-2'),
665 ('.6e', '0E-15', '0.000000e-9'),
666 ('.6e', '0', '0.000000e+6'),
667 ('.6e', '9.999999', '9.999999e+0'),
668 ('.6e', '9.9999999', '1.000000e+1'),
669 ('.6e', '-1.23e5', '-1.230000e+5'),
670 ('.6e', '1.23456789e-3', '1.234568e-3'),
671 ('f', '0', '0'),
672 ('f', '0.0', '0.0'),
673 ('f', '0E-2', '0.00'),
674 ('f', '0.00E-8', '0.0000000000'),
675 ('f', '0E1', '0'), # loses exponent information
676 ('f', '3.2E1', '32'),
677 ('f', '3.2E2', '320'),
678 ('f', '3.20E2', '320'),
679 ('f', '3.200E2', '320.0'),
680 ('f', '3.2E-6', '0.0000032'),
681 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
682 ('.6f', '0E1', '0.000000'),
683 ('.6f', '0', '0.000000'),
684 ('.0f', '0', '0'), # no decimal point
685 ('.0f', '0e-2', '0'),
686 ('.0f', '3.14159265', '3'),
687 ('.1f', '3.14159265', '3.1'),
688 ('.4f', '3.14159265', '3.1416'),
689 ('.6f', '3.14159265', '3.141593'),
690 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
691 ('.8f', '3.14159265', '3.14159265'),
692 ('.9f', '3.14159265', '3.141592650'),
693
694 ('g', '0', '0'),
695 ('g', '0.0', '0.0'),
696 ('g', '0E1', '0e+1'),
697 ('G', '0E1', '0E+1'),
698 ('g', '0E-5', '0.00000'),
699 ('g', '0E-6', '0.000000'),
700 ('g', '0E-7', '0e-7'),
701 ('g', '-0E2', '-0e+2'),
702 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
703 ('.1g', '3.14159265', '3'),
704 ('.2g', '3.14159265', '3.1'),
705 ('.5g', '3.14159265', '3.1416'),
706 ('.7g', '3.14159265', '3.141593'),
707 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
708 ('.9g', '3.14159265', '3.14159265'),
709 ('.10g', '3.14159265', '3.14159265'), # don't pad
710
711 ('%', '0E1', '0%'),
712 ('%', '0E0', '0%'),
713 ('%', '0E-1', '0%'),
714 ('%', '0E-2', '0%'),
715 ('%', '0E-3', '0.0%'),
716 ('%', '0E-4', '0.00%'),
717
718 ('.3%', '0', '0.000%'), # all zeros treated equally
719 ('.3%', '0E10', '0.000%'),
720 ('.3%', '0E-10', '0.000%'),
721 ('.3%', '2.34', '234.000%'),
722 ('.3%', '1.234567', '123.457%'),
723 ('.0%', '1.23', '123%'),
724
725 ('e', 'NaN', 'NaN'),
726 ('f', '-NaN123', '-NaN123'),
727 ('+g', 'NaN456', '+NaN456'),
728 ('.3e', 'Inf', 'Infinity'),
729 ('.16f', '-Inf', '-Infinity'),
730 ('.0g', '-sNaN', '-sNaN'),
731
732 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000733
Mark Dickinson79f52032009-03-17 23:12:51 +0000734 # test alignment and padding
Mark Dickinsonad416342009-03-17 18:10:15 +0000735 ('<6', '123', '123 '),
736 ('>6', '123', ' 123'),
737 ('^6', '123', ' 123 '),
738 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000739 ('#<10', 'NaN', 'NaN#######'),
740 ('#<10', '-4.3', '-4.3######'),
741 ('#<+10', '0.0130', '+0.0130###'),
742 ('#< 10', '0.0130', ' 0.0130###'),
743 ('@>10', '-Inf', '@-Infinity'),
744 ('#>5', '-Inf', '-Infinity'),
745 ('?^5', '123', '?123?'),
746 ('%^6', '123', '%123%%'),
747 (' ^6', '-45.6', '-45.6 '),
748 ('/=10', '-45.6', '-/////45.6'),
749 ('/=+10', '45.6', '+/////45.6'),
750 ('/= 10', '45.6', ' /////45.6'),
751
752 # thousands separator
753 (',', '1234567', '1,234,567'),
754 (',', '123456', '123,456'),
755 (',', '12345', '12,345'),
756 (',', '1234', '1,234'),
757 (',', '123', '123'),
758 (',', '12', '12'),
759 (',', '1', '1'),
760 (',', '0', '0'),
761 (',', '-1234567', '-1,234,567'),
762 (',', '-123456', '-123,456'),
763 ('7,', '123456', '123,456'),
764 ('8,', '123456', '123,456 '),
765 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
766 ('+08,', '123456', '+123,456'), # but not if there's a sign
767 (' 08,', '123456', ' 123,456'),
768 ('08,', '-123456', '-123,456'),
769 ('+09,', '123456', '+0,123,456'),
770 # ... with fractional part...
771 ('07,', '1234.56', '1,234.56'),
772 ('08,', '1234.56', '1,234.56'),
773 ('09,', '1234.56', '01,234.56'),
774 ('010,', '1234.56', '001,234.56'),
775 ('011,', '1234.56', '0,001,234.56'),
776 ('012,', '1234.56', '0,001,234.56'),
777 ('08,.1f', '1234.5', '01,234.5'),
778 # no thousands separators in fraction part
779 (',', '1.23456789', '1.23456789'),
780 (',%', '123.456789', '12,345.6789%'),
781 (',e', '123456', '1.23456e+5'),
782 (',E', '123456', '1.23456E+5'),
Mark Dickinsond496d302009-09-07 16:23:26 +0000783
784 # issue 6850
785 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000786 ]
787 for fmt, d, result in test_values:
788 self.assertEqual(format(Decimal(d), fmt), result)
789
Mark Dickinson79f52032009-03-17 23:12:51 +0000790 def test_n_format(self):
791 try:
792 from locale import CHAR_MAX
793 except ImportError:
794 return
795
796 # Set up some localeconv-like dictionaries
797 en_US = {
798 'decimal_point' : '.',
799 'grouping' : [3, 3, 0],
800 'thousands_sep': ','
801 }
802
803 fr_FR = {
804 'decimal_point' : ',',
805 'grouping' : [CHAR_MAX],
806 'thousands_sep' : ''
807 }
808
809 ru_RU = {
810 'decimal_point' : ',',
811 'grouping' : [3, 3, 0],
812 'thousands_sep' : ' '
813 }
814
815 crazy = {
816 'decimal_point' : '&',
817 'grouping' : [1, 4, 2, CHAR_MAX],
818 'thousands_sep' : '-'
819 }
820
821
822 def get_fmt(x, locale, fmt='n'):
823 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
824
825 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
826 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
827 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
828 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
829
830 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
831 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
832 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
833 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
834
835 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
836 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
837 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
838 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
839
Mark Dickinson7303b592009-03-18 08:25:36 +0000840 # zero padding
841 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
842 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
843 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
844 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
845
846 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
847 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
848 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
849 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
850 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
851 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
852
853 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
854 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
855 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
856 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
857 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
858 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
859 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
860 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
861
Mark Dickinson79f52032009-03-17 23:12:51 +0000862
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000863class DecimalArithmeticOperatorsTest(unittest.TestCase):
864 '''Unit tests for all arithmetic operators, binary and unary.'''
865
866 def test_addition(self):
867
868 d1 = Decimal('-11.1')
869 d2 = Decimal('22.2')
870
871 #two Decimals
872 self.assertEqual(d1+d2, Decimal('11.1'))
873 self.assertEqual(d2+d1, Decimal('11.1'))
874
875 #with other type, left
876 c = d1 + 5
877 self.assertEqual(c, Decimal('-6.1'))
878 self.assertEqual(type(c), type(d1))
879
880 #with other type, right
881 c = 5 + d1
882 self.assertEqual(c, Decimal('-6.1'))
883 self.assertEqual(type(c), type(d1))
884
885 #inline with decimal
886 d1 += d2
887 self.assertEqual(d1, Decimal('11.1'))
888
889 #inline with other type
890 d1 += 5
891 self.assertEqual(d1, Decimal('16.1'))
892
893 def test_subtraction(self):
894
895 d1 = Decimal('-11.1')
896 d2 = Decimal('22.2')
897
898 #two Decimals
899 self.assertEqual(d1-d2, Decimal('-33.3'))
900 self.assertEqual(d2-d1, Decimal('33.3'))
901
902 #with other type, left
903 c = d1 - 5
904 self.assertEqual(c, Decimal('-16.1'))
905 self.assertEqual(type(c), type(d1))
906
907 #with other type, right
908 c = 5 - d1
909 self.assertEqual(c, Decimal('16.1'))
910 self.assertEqual(type(c), type(d1))
911
912 #inline with decimal
913 d1 -= d2
914 self.assertEqual(d1, Decimal('-33.3'))
915
916 #inline with other type
917 d1 -= 5
918 self.assertEqual(d1, Decimal('-38.3'))
919
920 def test_multiplication(self):
921
922 d1 = Decimal('-5')
923 d2 = Decimal('3')
924
925 #two Decimals
926 self.assertEqual(d1*d2, Decimal('-15'))
927 self.assertEqual(d2*d1, Decimal('-15'))
928
929 #with other type, left
930 c = d1 * 5
931 self.assertEqual(c, Decimal('-25'))
932 self.assertEqual(type(c), type(d1))
933
934 #with other type, right
935 c = 5 * d1
936 self.assertEqual(c, Decimal('-25'))
937 self.assertEqual(type(c), type(d1))
938
939 #inline with decimal
940 d1 *= d2
941 self.assertEqual(d1, Decimal('-15'))
942
943 #inline with other type
944 d1 *= 5
945 self.assertEqual(d1, Decimal('-75'))
946
947 def test_division(self):
948
949 d1 = Decimal('-5')
950 d2 = Decimal('2')
951
952 #two Decimals
953 self.assertEqual(d1/d2, Decimal('-2.5'))
954 self.assertEqual(d2/d1, Decimal('-0.4'))
955
956 #with other type, left
957 c = d1 / 4
958 self.assertEqual(c, Decimal('-1.25'))
959 self.assertEqual(type(c), type(d1))
960
961 #with other type, right
962 c = 4 / d1
963 self.assertEqual(c, Decimal('-0.8'))
964 self.assertEqual(type(c), type(d1))
965
966 #inline with decimal
967 d1 /= d2
968 self.assertEqual(d1, Decimal('-2.5'))
969
970 #inline with other type
971 d1 /= 4
972 self.assertEqual(d1, Decimal('-0.625'))
973
974 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000975
976 d1 = Decimal('5')
977 d2 = Decimal('2')
978
979 #two Decimals
980 self.assertEqual(d1//d2, Decimal('2'))
981 self.assertEqual(d2//d1, Decimal('0'))
982
983 #with other type, left
984 c = d1 // 4
985 self.assertEqual(c, Decimal('1'))
986 self.assertEqual(type(c), type(d1))
987
988 #with other type, right
989 c = 7 // d1
990 self.assertEqual(c, Decimal('1'))
991 self.assertEqual(type(c), type(d1))
992
993 #inline with decimal
994 d1 //= d2
995 self.assertEqual(d1, Decimal('2'))
996
997 #inline with other type
998 d1 //= 2
999 self.assertEqual(d1, Decimal('1'))
1000
1001 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001002
1003 d1 = Decimal('5')
1004 d2 = Decimal('2')
1005
1006 #two Decimals
1007 self.assertEqual(d1**d2, Decimal('25'))
1008 self.assertEqual(d2**d1, Decimal('32'))
1009
1010 #with other type, left
1011 c = d1 ** 4
1012 self.assertEqual(c, Decimal('625'))
1013 self.assertEqual(type(c), type(d1))
1014
1015 #with other type, right
1016 c = 7 ** d1
1017 self.assertEqual(c, Decimal('16807'))
1018 self.assertEqual(type(c), type(d1))
1019
1020 #inline with decimal
1021 d1 **= d2
1022 self.assertEqual(d1, Decimal('25'))
1023
1024 #inline with other type
1025 d1 **= 4
1026 self.assertEqual(d1, Decimal('390625'))
1027
1028 def test_module(self):
1029
1030 d1 = Decimal('5')
1031 d2 = Decimal('2')
1032
1033 #two Decimals
1034 self.assertEqual(d1%d2, Decimal('1'))
1035 self.assertEqual(d2%d1, Decimal('2'))
1036
1037 #with other type, left
1038 c = d1 % 4
1039 self.assertEqual(c, Decimal('1'))
1040 self.assertEqual(type(c), type(d1))
1041
1042 #with other type, right
1043 c = 7 % d1
1044 self.assertEqual(c, Decimal('2'))
1045 self.assertEqual(type(c), type(d1))
1046
1047 #inline with decimal
1048 d1 %= d2
1049 self.assertEqual(d1, Decimal('1'))
1050
1051 #inline with other type
1052 d1 %= 4
1053 self.assertEqual(d1, Decimal('1'))
1054
1055 def test_floor_div_module(self):
1056
1057 d1 = Decimal('5')
1058 d2 = Decimal('2')
1059
1060 #two Decimals
1061 (p, q) = divmod(d1, d2)
1062 self.assertEqual(p, Decimal('2'))
1063 self.assertEqual(q, Decimal('1'))
1064 self.assertEqual(type(p), type(d1))
1065 self.assertEqual(type(q), type(d1))
1066
1067 #with other type, left
1068 (p, q) = divmod(d1, 4)
1069 self.assertEqual(p, Decimal('1'))
1070 self.assertEqual(q, Decimal('1'))
1071 self.assertEqual(type(p), type(d1))
1072 self.assertEqual(type(q), type(d1))
1073
1074 #with other type, right
1075 (p, q) = divmod(7, d1)
1076 self.assertEqual(p, Decimal('1'))
1077 self.assertEqual(q, Decimal('2'))
1078 self.assertEqual(type(p), type(d1))
1079 self.assertEqual(type(q), type(d1))
1080
1081 def test_unary_operators(self):
1082 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1083 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1084 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1085
Christian Heimes77c02eb2008-02-09 02:18:51 +00001086 def test_nan_comparisons(self):
1087 n = Decimal('NaN')
1088 s = Decimal('sNaN')
1089 i = Decimal('Inf')
1090 f = Decimal('2')
1091 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1092 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Georg Brandlab91fde2009-08-13 08:51:18 +00001093 self.assertTrue(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))
1098 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001099
1100# The following are two functions used to test threading in the next class
1101
1102def thfunc1(cls):
1103 d1 = Decimal(1)
1104 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001105 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001106 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001107 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001108 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001109
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001110 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1111 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001112 return
1113
1114def thfunc2(cls):
1115 d1 = Decimal(1)
1116 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001117 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001118 thiscontext = getcontext()
1119 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001120 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001121 cls.synchro.set()
1122 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001123
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001124 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001125 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001126 return
1127
1128
1129class DecimalUseOfContextTest(unittest.TestCase):
1130 '''Unit tests for Use of Context cases in Decimal.'''
1131
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001132 try:
1133 import threading
1134 except ImportError:
1135 threading = None
1136
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001137 # Take care executing this test from IDLE, there's an issue in threading
1138 # that hangs IDLE and I couldn't find it
1139
1140 def test_threading(self):
1141 #Test the "threading isolation" of a Context.
1142
1143 self.synchro = threading.Event()
1144 self.finish1 = threading.Event()
1145 self.finish2 = threading.Event()
1146
1147 th1 = threading.Thread(target=thfunc1, args=(self,))
1148 th2 = threading.Thread(target=thfunc2, args=(self,))
1149
1150 th1.start()
1151 th2.start()
1152
1153 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001154 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001155 return
1156
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001157 if threading is None:
1158 del test_threading
1159
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001160
1161class DecimalUsabilityTest(unittest.TestCase):
1162 '''Unit tests for Usability cases of Decimal.'''
1163
1164 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001165
1166 da = Decimal('23.42')
1167 db = Decimal('23.42')
1168 dc = Decimal('45')
1169
1170 #two Decimals
Georg Brandlab91fde2009-08-13 08:51:18 +00001171 self.assertTrue(dc > da)
1172 self.assertTrue(dc >= da)
1173 self.assertTrue(da < dc)
1174 self.assertTrue(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001175 self.assertEqual(da, db)
Georg Brandlab91fde2009-08-13 08:51:18 +00001176 self.assertTrue(da != dc)
1177 self.assertTrue(da <= db)
1178 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179
1180 #a Decimal and an int
Georg Brandlab91fde2009-08-13 08:51:18 +00001181 self.assertTrue(dc > 23)
1182 self.assertTrue(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001183 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184
1185 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001186 self.assertNotEqual(da, 'ugly')
1187 self.assertNotEqual(da, 32.7)
1188 self.assertNotEqual(da, object())
1189 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001191 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001192 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001193 b = a[:]
1194 random.shuffle(a)
1195 a.sort()
1196 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001197
1198 def test_copy_and_deepcopy_methods(self):
1199 d = Decimal('43.24')
1200 c = copy.copy(d)
1201 self.assertEqual(id(c), id(d))
1202 dc = copy.deepcopy(d)
1203 self.assertEqual(id(dc), id(d))
1204
1205 def test_hash_method(self):
1206 #just that it's hashable
1207 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001208
1209 test_values = [Decimal(sign*(2**m + n))
1210 for m in [0, 14, 15, 16, 17, 30, 31,
1211 32, 33, 62, 63, 64, 65, 66]
1212 for n in range(-10, 10)
1213 for sign in [-1, 1]]
1214 test_values.extend([
1215 Decimal("-0"), # zeros
1216 Decimal("0.00"),
1217 Decimal("-0.000"),
1218 Decimal("0E10"),
1219 Decimal("-0E12"),
1220 Decimal("10.0"), # negative exponent
1221 Decimal("-23.00000"),
1222 Decimal("1230E100"), # positive exponent
1223 Decimal("-4.5678E50"),
1224 # a value for which hash(n) != hash(n % (2**64-1))
1225 # in Python pre-2.6
1226 Decimal(2**64 + 2**32 - 1),
1227 # selection of values which fail with the old (before
1228 # version 2.6) long.__hash__
1229 Decimal("1.634E100"),
1230 Decimal("90.697E100"),
1231 Decimal("188.83E100"),
1232 Decimal("1652.9E100"),
1233 Decimal("56531E100"),
1234 ])
1235
1236 # check that hash(d) == hash(int(d)) for integral values
1237 for value in test_values:
1238 self.assertEqual(hash(value), hash(int(value)))
1239
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001240 #the same hash that to an int
1241 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001242 self.assertRaises(TypeError, hash, Decimal('NaN'))
Georg Brandlab91fde2009-08-13 08:51:18 +00001243 self.assertTrue(hash(Decimal('Inf')))
1244 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001245
Christian Heimes2380ac72008-01-09 00:17:24 +00001246 # check that the value of the hash doesn't depend on the
1247 # current context (issue #1757)
1248 c = getcontext()
1249 old_precision = c.prec
1250 x = Decimal("123456789.1")
1251
1252 c.prec = 6
1253 h1 = hash(x)
1254 c.prec = 10
1255 h2 = hash(x)
1256 c.prec = 16
1257 h3 = hash(x)
1258
1259 self.assertEqual(h1, h2)
1260 self.assertEqual(h1, h3)
1261 c.prec = old_precision
1262
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263 def test_min_and_max_methods(self):
1264
1265 d1 = Decimal('15.32')
1266 d2 = Decimal('28.5')
1267 l1 = 15
1268 l2 = 28
1269
1270 #between Decimals
Georg Brandlab91fde2009-08-13 08:51:18 +00001271 self.assertTrue(min(d1,d2) is d1)
1272 self.assertTrue(min(d2,d1) is d1)
1273 self.assertTrue(max(d1,d2) is d2)
1274 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001275
1276 #between Decimal and long
Georg Brandlab91fde2009-08-13 08:51:18 +00001277 self.assertTrue(min(d1,l2) is d1)
1278 self.assertTrue(min(l2,d1) is d1)
1279 self.assertTrue(max(l1,d2) is d2)
1280 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001281
1282 def test_as_nonzero(self):
1283 #as false
Georg Brandlab91fde2009-08-13 08:51:18 +00001284 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001285 #as true
Georg Brandlab91fde2009-08-13 08:51:18 +00001286 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001287
1288 def test_tostring_methods(self):
1289 #Test str and repr methods.
1290
1291 d = Decimal('15.32')
1292 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001293 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
1295 def test_tonum_methods(self):
1296 #Test float, int and long methods.
1297
1298 d1 = Decimal('66')
1299 d2 = Decimal('15.32')
1300
1301 #int
1302 self.assertEqual(int(d1), 66)
1303 self.assertEqual(int(d2), 15)
1304
1305 #long
Guido van Rossume2a383d2007-01-15 16:59:06 +00001306 self.assertEqual(int(d1), 66)
1307 self.assertEqual(int(d2), 15)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001308
1309 #float
1310 self.assertEqual(float(d1), 66)
1311 self.assertEqual(float(d2), 15.32)
1312
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001313 #floor
1314 test_pairs = [
1315 ('123.00', 123),
1316 ('3.2', 3),
1317 ('3.54', 3),
1318 ('3.899', 3),
1319 ('-2.3', -3),
1320 ('-11.0', -11),
1321 ('0.0', 0),
1322 ('-0E3', 0),
1323 ]
1324 for d, i in test_pairs:
1325 self.assertEqual(math.floor(Decimal(d)), i)
1326 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1327 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1328 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1329 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1330 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1331
1332 #ceiling
1333 test_pairs = [
1334 ('123.00', 123),
1335 ('3.2', 4),
1336 ('3.54', 4),
1337 ('3.899', 4),
1338 ('-2.3', -2),
1339 ('-11.0', -11),
1340 ('0.0', 0),
1341 ('-0E3', 0),
1342 ]
1343 for d, i in test_pairs:
1344 self.assertEqual(math.ceil(Decimal(d)), i)
1345 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1346 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1347 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1348 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1349 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1350
1351 #round, single argument
1352 test_pairs = [
1353 ('123.00', 123),
1354 ('3.2', 3),
1355 ('3.54', 4),
1356 ('3.899', 4),
1357 ('-2.3', -2),
1358 ('-11.0', -11),
1359 ('0.0', 0),
1360 ('-0E3', 0),
1361 ('-3.5', -4),
1362 ('-2.5', -2),
1363 ('-1.5', -2),
1364 ('-0.5', 0),
1365 ('0.5', 0),
1366 ('1.5', 2),
1367 ('2.5', 2),
1368 ('3.5', 4),
1369 ]
1370 for d, i in test_pairs:
1371 self.assertEqual(round(Decimal(d)), i)
1372 self.assertRaises(ValueError, round, Decimal('-NaN'))
1373 self.assertRaises(ValueError, round, Decimal('sNaN'))
1374 self.assertRaises(ValueError, round, Decimal('NaN123'))
1375 self.assertRaises(OverflowError, round, Decimal('Inf'))
1376 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1377
1378 #round, two arguments; this is essentially equivalent
1379 #to quantize, which is already extensively tested
1380 test_triples = [
1381 ('123.456', -4, '0E+4'),
1382 ('123.456', -3, '0E+3'),
1383 ('123.456', -2, '1E+2'),
1384 ('123.456', -1, '1.2E+2'),
1385 ('123.456', 0, '123'),
1386 ('123.456', 1, '123.5'),
1387 ('123.456', 2, '123.46'),
1388 ('123.456', 3, '123.456'),
1389 ('123.456', 4, '123.4560'),
1390 ('123.455', 2, '123.46'),
1391 ('123.445', 2, '123.44'),
1392 ('Inf', 4, 'NaN'),
1393 ('-Inf', -23, 'NaN'),
1394 ('sNaN314', 3, 'NaN314'),
1395 ]
1396 for d, n, r in test_triples:
1397 self.assertEqual(str(round(Decimal(d), n)), r)
1398
1399
1400
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401 def test_eval_round_trip(self):
1402
1403 #with zero
1404 d = Decimal( (0, (0,), 0) )
1405 self.assertEqual(d, eval(repr(d)))
1406
1407 #int
1408 d = Decimal( (1, (4, 5), 0) )
1409 self.assertEqual(d, eval(repr(d)))
1410
1411 #float
1412 d = Decimal( (0, (4, 5, 3, 4), -2) )
1413 self.assertEqual(d, eval(repr(d)))
1414
1415 #weird
1416 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1417 self.assertEqual(d, eval(repr(d)))
1418
1419 def test_as_tuple(self):
1420
1421 #with zero
1422 d = Decimal(0)
1423 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1424
1425 #int
1426 d = Decimal(-45)
1427 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1428
1429 #complicated string
1430 d = Decimal("-4.34913534E-17")
1431 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1432
1433 #inf
1434 d = Decimal("Infinity")
1435 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1436
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001437 #leading zeros in coefficient should be stripped
1438 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1439 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1440 d = Decimal( (1, (0, 0, 0), 37) )
1441 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1442 d = Decimal( (1, (), 37) )
1443 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1444
1445 #leading zeros in NaN diagnostic info should be stripped
1446 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1447 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1448 d = Decimal( (1, (0, 0, 0), 'N') )
1449 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1450 d = Decimal( (1, (), 'n') )
1451 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1452
1453 #coefficient in infinity should be ignored
1454 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1455 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1456 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1457 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1458
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001459 def test_immutability_operations(self):
1460 # Do operations and check that it didn't change change internal objects.
1461
1462 d1 = Decimal('-25e55')
1463 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001464 d2 = Decimal('33e+33')
1465 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001466
1467 def checkSameDec(operation, useOther=False):
1468 if useOther:
1469 eval("d1." + operation + "(d2)")
1470 self.assertEqual(d1._sign, b1._sign)
1471 self.assertEqual(d1._int, b1._int)
1472 self.assertEqual(d1._exp, b1._exp)
1473 self.assertEqual(d2._sign, b2._sign)
1474 self.assertEqual(d2._int, b2._int)
1475 self.assertEqual(d2._exp, b2._exp)
1476 else:
1477 eval("d1." + operation + "()")
1478 self.assertEqual(d1._sign, b1._sign)
1479 self.assertEqual(d1._int, b1._int)
1480 self.assertEqual(d1._exp, b1._exp)
1481 return
1482
1483 Decimal(d1)
1484 self.assertEqual(d1._sign, b1._sign)
1485 self.assertEqual(d1._int, b1._int)
1486 self.assertEqual(d1._exp, b1._exp)
1487
1488 checkSameDec("__abs__")
1489 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001490 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001491 checkSameDec("__eq__", True)
1492 checkSameDec("__ne__", True)
1493 checkSameDec("__le__", True)
1494 checkSameDec("__lt__", True)
1495 checkSameDec("__ge__", True)
1496 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001497 checkSameDec("__float__")
1498 checkSameDec("__floordiv__", True)
1499 checkSameDec("__hash__")
1500 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001501 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001502 checkSameDec("__mod__", True)
1503 checkSameDec("__mul__", True)
1504 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001505 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001506 checkSameDec("__pos__")
1507 checkSameDec("__pow__", True)
1508 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 checkSameDec("__rdivmod__", True)
1510 checkSameDec("__repr__")
1511 checkSameDec("__rfloordiv__", True)
1512 checkSameDec("__rmod__", True)
1513 checkSameDec("__rmul__", True)
1514 checkSameDec("__rpow__", True)
1515 checkSameDec("__rsub__", True)
1516 checkSameDec("__str__")
1517 checkSameDec("__sub__", True)
1518 checkSameDec("__truediv__", True)
1519 checkSameDec("adjusted")
1520 checkSameDec("as_tuple")
1521 checkSameDec("compare", True)
1522 checkSameDec("max", True)
1523 checkSameDec("min", True)
1524 checkSameDec("normalize")
1525 checkSameDec("quantize", True)
1526 checkSameDec("remainder_near", True)
1527 checkSameDec("same_quantum", True)
1528 checkSameDec("sqrt")
1529 checkSameDec("to_eng_string")
1530 checkSameDec("to_integral")
1531
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001532 def test_subclassing(self):
1533 # Different behaviours when subclassing Decimal
1534
1535 class MyDecimal(Decimal):
1536 pass
1537
1538 d1 = MyDecimal(1)
1539 d2 = MyDecimal(2)
1540 d = d1 + d2
1541 self.assertTrue(type(d) is Decimal)
1542
1543 d = d1.max(d2)
1544 self.assertTrue(type(d) is Decimal)
1545
Christian Heimes0348fb62008-03-26 12:55:56 +00001546 def test_implicit_context(self):
1547 # Check results when context given implicitly. (Issue 2478)
1548 c = getcontext()
1549 self.assertEqual(str(Decimal(0).sqrt()),
1550 str(c.sqrt(Decimal(0))))
1551
Mark Dickinson9050bb22009-10-29 12:25:07 +00001552 def test_conversions_from_int(self):
1553 # Check that methods taking a second Decimal argument will
1554 # always accept an integer in place of a Decimal.
1555 self.assertEqual(Decimal(4).compare(3),
1556 Decimal(4).compare(Decimal(3)))
1557 self.assertEqual(Decimal(4).compare_signal(3),
1558 Decimal(4).compare_signal(Decimal(3)))
1559 self.assertEqual(Decimal(4).compare_total(3),
1560 Decimal(4).compare_total(Decimal(3)))
1561 self.assertEqual(Decimal(4).compare_total_mag(3),
1562 Decimal(4).compare_total_mag(Decimal(3)))
1563 self.assertEqual(Decimal(10101).logical_and(1001),
1564 Decimal(10101).logical_and(Decimal(1001)))
1565 self.assertEqual(Decimal(10101).logical_or(1001),
1566 Decimal(10101).logical_or(Decimal(1001)))
1567 self.assertEqual(Decimal(10101).logical_xor(1001),
1568 Decimal(10101).logical_xor(Decimal(1001)))
1569 self.assertEqual(Decimal(567).max(123),
1570 Decimal(567).max(Decimal(123)))
1571 self.assertEqual(Decimal(567).max_mag(123),
1572 Decimal(567).max_mag(Decimal(123)))
1573 self.assertEqual(Decimal(567).min(123),
1574 Decimal(567).min(Decimal(123)))
1575 self.assertEqual(Decimal(567).min_mag(123),
1576 Decimal(567).min_mag(Decimal(123)))
1577 self.assertEqual(Decimal(567).next_toward(123),
1578 Decimal(567).next_toward(Decimal(123)))
1579 self.assertEqual(Decimal(1234).quantize(100),
1580 Decimal(1234).quantize(Decimal(100)))
1581 self.assertEqual(Decimal(768).remainder_near(1234),
1582 Decimal(768).remainder_near(Decimal(1234)))
1583 self.assertEqual(Decimal(123).rotate(1),
1584 Decimal(123).rotate(Decimal(1)))
1585 self.assertEqual(Decimal(1234).same_quantum(1000),
1586 Decimal(1234).same_quantum(Decimal(1000)))
1587 self.assertEqual(Decimal('9.123').scaleb(-100),
1588 Decimal('9.123').scaleb(Decimal(-100)))
1589 self.assertEqual(Decimal(456).shift(-1),
1590 Decimal(456).shift(Decimal(-1)))
1591
1592 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1593 Decimal(-12).fma(Decimal(45), Decimal(67)))
1594 self.assertEqual(Decimal(-12).fma(45, 67),
1595 Decimal(-12).fma(Decimal(45), Decimal(67)))
1596 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1597 Decimal(-12).fma(Decimal(45), Decimal(67)))
1598
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001599
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600class DecimalPythonAPItests(unittest.TestCase):
1601
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001602 def test_abc(self):
Georg Brandlab91fde2009-08-13 08:51:18 +00001603 self.assertTrue(issubclass(Decimal, numbers.Number))
1604 self.assertTrue(not issubclass(Decimal, numbers.Real))
1605 self.assertTrue(isinstance(Decimal(0), numbers.Number))
1606 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001607
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001608 def test_pickle(self):
1609 d = Decimal('-3.141590000')
1610 p = pickle.dumps(d)
1611 e = pickle.loads(p)
1612 self.assertEqual(d, e)
1613
Raymond Hettinger5548be22004-07-05 18:49:38 +00001614 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001615 for x in range(-250, 250):
1616 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001617 # should work the same as for floats
1618 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001619 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001620 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001621 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001622 self.assertEqual(Decimal(int(d)), r)
1623
Mark Dickinson8fde3da2009-09-08 19:23:44 +00001624 self.assertRaises(ValueError, int, Decimal('-nan'))
1625 self.assertRaises(ValueError, int, Decimal('snan'))
1626 self.assertRaises(OverflowError, int, Decimal('inf'))
1627 self.assertRaises(OverflowError, int, Decimal('-inf'))
1628
Christian Heimes969fe572008-01-25 11:23:10 +00001629 def test_trunc(self):
1630 for x in range(-250, 250):
1631 s = '%0.2f' % (x / 100.0)
1632 # should work the same as for floats
1633 self.assertEqual(int(Decimal(s)), int(float(s)))
1634 # should work the same as to_integral in the ROUND_DOWN mode
1635 d = Decimal(s)
1636 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001637 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001638
Raymond Hettinger771ed762009-01-03 19:20:32 +00001639 def test_from_float(self):
1640
1641 class MyDecimal(Decimal):
1642 pass
1643
1644 r = MyDecimal.from_float(0.1)
1645 self.assertEqual(type(r), MyDecimal)
1646 self.assertEqual(str(r),
1647 '0.1000000000000000055511151231257827021181583404541015625')
1648 bigint = 12345678901234567890123456789
1649 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Georg Brandlab91fde2009-08-13 08:51:18 +00001650 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1651 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1652 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001653 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1654 str(Decimal('NaN')))
1655 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1656 str(Decimal('Infinity')))
1657 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1658 str(Decimal('-Infinity')))
1659 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1660 for i in range(200):
1661 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1662 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1663
1664 def test_create_decimal_from_float(self):
1665 context = Context(prec=5, rounding=ROUND_DOWN)
1666 self.assertEqual(
1667 context.create_decimal_from_float(math.pi),
1668 Decimal('3.1415')
1669 )
1670 context = Context(prec=5, rounding=ROUND_UP)
1671 self.assertEqual(
1672 context.create_decimal_from_float(math.pi),
1673 Decimal('3.1416')
1674 )
1675 context = Context(prec=5, traps=[Inexact])
1676 self.assertRaises(
1677 Inexact,
1678 context.create_decimal_from_float,
1679 math.pi
1680 )
1681 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1682 "Decimal('-0')")
1683 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1684 "Decimal('1')")
1685 self.assertEqual(repr(context.create_decimal_from_float(10)),
1686 "Decimal('10')")
1687
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001688class ContextAPItests(unittest.TestCase):
1689
1690 def test_pickle(self):
1691 c = Context()
1692 e = pickle.loads(pickle.dumps(c))
1693 for k in vars(c):
1694 v1 = vars(c)[k]
1695 v2 = vars(e)[k]
1696 self.assertEqual(v1, v2)
1697
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001698 def test_equality_with_other_types(self):
Georg Brandlab91fde2009-08-13 08:51:18 +00001699 self.assertTrue(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1700 self.assertTrue(Decimal(10) not in ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001701
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001702 def test_copy(self):
1703 # All copies should be deep
1704 c = Context()
1705 d = c.copy()
1706 self.assertNotEqual(id(c), id(d))
1707 self.assertNotEqual(id(c.flags), id(d.flags))
1708 self.assertNotEqual(id(c.traps), id(d.traps))
1709
Thomas Wouters89f507f2006-12-13 04:49:30 +00001710class WithStatementTest(unittest.TestCase):
1711 # Can't do these as docstrings until Python 2.6
1712 # as doctest can't handle __future__ statements
1713
1714 def test_localcontext(self):
1715 # Use a copy of the current context in the block
1716 orig_ctx = getcontext()
1717 with localcontext() as enter_ctx:
1718 set_ctx = getcontext()
1719 final_ctx = getcontext()
Georg Brandlab91fde2009-08-13 08:51:18 +00001720 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
1721 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
1722 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00001723
1724 def test_localcontextarg(self):
1725 # Use a copy of the supplied context in the block
1726 orig_ctx = getcontext()
1727 new_ctx = Context(prec=42)
1728 with localcontext(new_ctx) as enter_ctx:
1729 set_ctx = getcontext()
1730 final_ctx = getcontext()
Georg Brandlab91fde2009-08-13 08:51:18 +00001731 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
1732 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1733 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
1734 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00001735
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001736class ContextFlags(unittest.TestCase):
1737 def test_flags_irrelevant(self):
1738 # check that the result (numeric result + flags raised) of an
1739 # arithmetic operation doesn't depend on the current flags
1740
1741 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1742 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1743
1744 # operations that raise various flags, in the form (function, arglist)
1745 operations = [
1746 (context._apply, [Decimal("100E-1000000009")]),
1747 (context.sqrt, [Decimal(2)]),
1748 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1749 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1750 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1751 ]
1752
1753 # try various flags individually, then a whole lot at once
1754 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1755 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1756
1757 for fn, args in operations:
1758 # find answer and flags raised using a clean context
1759 context.clear_flags()
1760 ans = fn(*args)
1761 flags = [k for k, v in context.flags.items() if v]
1762
1763 for extra_flags in flagsets:
1764 # set flags, before calling operation
1765 context.clear_flags()
1766 for flag in extra_flags:
1767 context._raise_error(flag)
1768 new_ans = fn(*args)
1769
1770 # flags that we expect to be set after the operation
1771 expected_flags = list(flags)
1772 for flag in extra_flags:
1773 if flag not in expected_flags:
1774 expected_flags.append(flag)
1775 expected_flags.sort(key=id)
1776
1777 # flags we actually got
1778 new_flags = [k for k,v in context.flags.items() if v]
1779 new_flags.sort(key=id)
1780
1781 self.assertEqual(ans, new_ans,
1782 "operation produces different answers depending on flags set: " +
1783 "expected %s, got %s." % (ans, new_ans))
1784 self.assertEqual(new_flags, expected_flags,
1785 "operation raises different flags depending on flags set: " +
1786 "expected %s, got %s" % (expected_flags, new_flags))
1787
1788def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001789 """ Execute the tests.
1790
Raymond Hettingered20ad82004-09-04 20:09:13 +00001791 Runs all arithmetic tests if arith is True or if the "decimal" resource
1792 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001793 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001794
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001795 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001796 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001797 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001798 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001799
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001800 if todo_tests is None:
1801 test_classes = [
1802 DecimalExplicitConstructionTest,
1803 DecimalImplicitConstructionTest,
1804 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00001805 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001806 DecimalUseOfContextTest,
1807 DecimalUsabilityTest,
1808 DecimalPythonAPItests,
1809 ContextAPItests,
1810 DecimalTest,
1811 WithStatementTest,
1812 ContextFlags
1813 ]
1814 else:
1815 test_classes = [DecimalTest]
1816
1817 # Dynamically build custom test definition for each file in the test
1818 # directory and add the definitions to the DecimalTest class. This
1819 # procedure insures that new files do not get skipped.
1820 for filename in os.listdir(directory):
1821 if '.decTest' not in filename or filename.startswith("."):
1822 continue
1823 head, tail = filename.split('.')
1824 if todo_tests is not None and head not in todo_tests:
1825 continue
1826 tester = lambda self, f=filename: self.eval_file(directory + f)
1827 setattr(DecimalTest, 'test_' + head, tester)
1828 del filename, head, tail, tester
1829
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001830
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001831 try:
1832 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001833 if todo_tests is None:
1834 import decimal as DecimalModule
1835 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001836 finally:
1837 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001838
1839if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001840 import optparse
1841 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1842 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1843 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1844 (opt, args) = p.parse_args()
1845
1846 if opt.skip:
1847 test_main(arith=False, verbose=True)
1848 elif args:
1849 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001851 test_main(arith=True, verbose=True)