blob: 51bdf9ca482c1ddfd4f995588fc6ad2343cc998e [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
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
29import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000030import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000032import numbers
Benjamin Petersone549ead2009-03-28 21:42:05 +000033from test.support import run_unittest, run_doctest, is_resource_enabled
Raymond Hettinger0aeac102004-07-05 22:53:03 +000034import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000035try:
36 import threading
37except ImportError:
38 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000039
Raymond Hettingerfed52962004-07-14 15:41:57 +000040# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000041Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000042
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000043# Tests are built around these assumed context defaults.
44# test_main() restores the original context.
45def init():
46 global ORIGINAL_CONTEXT
47 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000048 DefaultTestContext = Context(
49 prec = 9,
50 rounding = ROUND_HALF_EVEN,
51 traps = dict.fromkeys(Signals, 0)
52 )
53 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000054
Raymond Hettinger96798592010-04-02 16:58:27 +000055# decorator for skipping tests on non-IEEE 754 platforms
56requires_IEEE_754 = unittest.skipUnless(
57 float.__getformat__("double").startswith("IEEE"),
58 "test requires IEEE 754 doubles")
59
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000060TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000061if __name__ == '__main__':
62 file = sys.argv[0]
63else:
64 file = __file__
65testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000066directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000067
Raymond Hettinger267b8682005-03-27 10:47:39 +000068skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000069
Mark Dickinson8a546532009-10-08 16:30:38 +000070# list of individual .decTest test ids that correspond to tests that
71# we're skipping for one reason or another.
72skipped_test_ids = [
73 'scbx164', # skipping apparently implementation-specific scaleb
74 'scbx165', # tests, pending clarification of scaleb rules.
75]
76
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077# Make sure it actually raises errors when not expected and caught in flags
78# Slower, since it runs some things several times.
79EXTENDEDERRORTEST = False
80
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000081#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000082ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000083 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000085 'division_impossible' : InvalidOperation,
86 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000087 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000088 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000089 'invalid_operation' : InvalidOperation,
90 'overflow' : Overflow,
91 'rounded' : Rounded,
92 'subnormal' : Subnormal,
93 'underflow' : Underflow}
94
95
96def Nonfunction(*args):
97 """Doesn't do anything."""
98 return None
99
100RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
101 'down' : ROUND_DOWN,
102 'floor' : ROUND_FLOOR,
103 'half_down' : ROUND_HALF_DOWN,
104 'half_even' : ROUND_HALF_EVEN,
105 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 'up' : ROUND_UP,
107 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000108
109# Name adapter to be able to change the Decimal and Context
110# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000111nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000112 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 'class':'number_class',
114 'comparesig':'compare_signal',
115 'comparetotal':'compare_total',
116 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000117 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000118 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000119 'copynegate':'copy_negate',
120 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000121 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000122 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000123 'iscanonical':'is_canonical',
124 'isfinite':'is_finite',
125 'isinfinite':'is_infinite',
126 'isnan':'is_nan',
127 'isnormal':'is_normal',
128 'isqnan':'is_qnan',
129 'issigned':'is_signed',
130 'issnan':'is_snan',
131 'issubnormal':'is_subnormal',
132 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000133 'maxmag':'max_mag',
134 'minmag':'min_mag',
135 'nextminus':'next_minus',
136 'nextplus':'next_plus',
137 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000138 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000139 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000140 'remaindernear':'remainder_near',
141 'samequantum':'same_quantum',
142 'squareroot':'sqrt',
143 'toeng':'to_eng_string',
144 'tointegral':'to_integral_value',
145 'tointegralx':'to_integral_exact',
146 'tosci':'to_sci_string',
147 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000148 }
149
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000150# The following functions return True/False rather than a Decimal instance
151
152LOGICAL_FUNCTIONS = (
153 'is_canonical',
154 'is_finite',
155 'is_infinite',
156 'is_nan',
157 'is_normal',
158 'is_qnan',
159 'is_signed',
160 'is_snan',
161 'is_subnormal',
162 'is_zero',
163 'same_quantum',
164 )
165
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000166# For some operations (currently exp, ln, log10, power), the decNumber
167# reference implementation imposes additional restrictions on the
168# context and operands. These restrictions are not part of the
169# specification; however, the effect of these restrictions does show
170# up in some of the testcases. We skip testcases that violate these
171# restrictions, since Decimal behaves differently from decNumber for
172# these testcases so these testcases would otherwise fail.
173
174decNumberRestricted = ('power', 'ln', 'log10', 'exp')
175DEC_MAX_MATH = 999999
176def outside_decNumber_bounds(v, context):
177 if (context.prec > DEC_MAX_MATH or
178 context.Emax > DEC_MAX_MATH or
179 -context.Emin > DEC_MAX_MATH):
180 return True
181 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000182 v.adjusted() > DEC_MAX_MATH or
183 v.adjusted() < 1-2*DEC_MAX_MATH):
184 return True
185 return False
186
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000187class DecimalTest(unittest.TestCase):
188 """Class which tests the Decimal class against the test cases.
189
190 Changed for unittest.
191 """
192 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000193 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000194 self.ignore_list = ['#']
195 # Basically, a # means return NaN InvalidOperation.
196 # Different from a sNaN in trim
197
198 self.ChangeDict = {'precision' : self.change_precision,
199 'rounding' : self.change_rounding_method,
200 'maxexponent' : self.change_max_exponent,
201 'minexponent' : self.change_min_exponent,
202 'clamp' : self.change_clamp}
203
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000204 def eval_file(self, file):
205 global skip_expected
206 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000207 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000208 return
Neal Norwitz70967602006-03-17 08:29:44 +0000209 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000210 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000211 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 try:
213 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000214 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000215 #Exception raised where there shoudn't have been one.
216 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
217
218 return
219
220 def eval_line(self, s):
221 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
222 s = (s.split('->')[0] + '->' +
223 s.split('->')[1].split('--')[0]).strip()
224 else:
225 s = s.split('--')[0].strip()
226
227 for ignore in self.ignore_list:
228 if s.find(ignore) >= 0:
229 #print s.split()[0], 'NotImplemented--', ignore
230 return
231 if not s:
232 return
233 elif ':' in s:
234 return self.eval_directive(s)
235 else:
236 return self.eval_equation(s)
237
238 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000239 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000240 if funct == 'rounding':
241 value = RoundingDict[value]
242 else:
243 try:
244 value = int(value)
245 except ValueError:
246 pass
247
248 funct = self.ChangeDict.get(funct, Nonfunction)
249 funct(value)
250
251 def eval_equation(self, s):
252 #global DEFAULT_PRECISION
253 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000254
255 if not TEST_ALL and random.random() < 0.90:
256 return
257
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000258 try:
259 Sides = s.split('->')
260 L = Sides[0].strip().split()
261 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000262 if DEBUG:
263 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000264 funct = L[1].lower()
265 valstemp = L[2:]
266 L = Sides[1].strip().split()
267 ans = L[0]
268 exceptions = L[1:]
269 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000270 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000271 def FixQuotes(val):
272 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
273 val = val.replace("'", '').replace('"', '')
274 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
275 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000276
277 if id in skipped_test_ids:
278 return
279
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000280 fname = nameAdapter.get(funct, funct)
281 if fname == 'rescale':
282 return
283 funct = getattr(self.context, fname)
284 vals = []
285 conglomerate = ''
286 quote = 0
287 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
288
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000289 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000290 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000291 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000292 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 for i, val in enumerate(valstemp):
294 if val.count("'") % 2 == 1:
295 quote = 1 - quote
296 if quote:
297 conglomerate = conglomerate + ' ' + val
298 continue
299 else:
300 val = conglomerate + val
301 conglomerate = ''
302 v = FixQuotes(val)
303 if fname in ('to_sci_string', 'to_eng_string'):
304 if EXTENDEDERRORTEST:
305 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000306 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000307 try:
308 funct(self.context.create_decimal(v))
309 except error:
310 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000311 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000312 self.fail("Raised %s in %s when %s disabled" % \
313 (e, s, error))
314 else:
315 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000316 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000317 v = self.context.create_decimal(v)
318 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000319 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 vals.append(v)
321
322 ans = FixQuotes(ans)
323
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000324 # skip tests that are related to bounds imposed in the decNumber
325 # reference implementation
326 if fname in decNumberRestricted:
327 if fname == 'power':
328 if not (vals[1]._isinteger() and
329 -1999999997 <= vals[1] <= 999999999):
330 if outside_decNumber_bounds(vals[0], self.context) or \
331 outside_decNumber_bounds(vals[1], self.context):
332 #print "Skipping test %s" % s
333 return
334 else:
335 if outside_decNumber_bounds(vals[0], self.context):
336 #print "Skipping test %s" % s
337 return
338
339
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
341 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000342 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 try:
344 funct(*vals)
345 except error:
346 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000347 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000348 self.fail("Raised %s in %s when %s disabled" % \
349 (e, s, error))
350 else:
351 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000352 self.context.traps[error] = 0
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000353 if DEBUG:
354 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 try:
356 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000357 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000358 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000359 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000360 self.fail("Raised %s in %s" % (error, s))
361 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000362 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000363 raise
364
365 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000366 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000367
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000368 myexceptions.sort(key=repr)
369 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370
371 self.assertEqual(result, ans,
372 'Incorrect answer for ' + s + ' -- got ' + result)
373 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000374 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 return
376
377 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000378 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 def change_precision(self, prec):
381 self.context.prec = prec
382 def change_rounding_method(self, rounding):
383 self.context.rounding = rounding
384 def change_min_exponent(self, exp):
385 self.context.Emin = exp
386 def change_max_exponent(self, exp):
387 self.context.Emax = exp
388 def change_clamp(self, clamp):
389 self.context._clamp = clamp
390
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391
392
393# The following classes test the behaviour of Decimal according to PEP 327
394
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395class DecimalExplicitConstructionTest(unittest.TestCase):
396 '''Unit tests for Explicit Construction cases of Decimal.'''
397
398 def test_explicit_empty(self):
399 self.assertEqual(Decimal(), Decimal("0"))
400
401 def test_explicit_from_None(self):
402 self.assertRaises(TypeError, Decimal, None)
403
404 def test_explicit_from_int(self):
405
406 #positive
407 d = Decimal(45)
408 self.assertEqual(str(d), '45')
409
410 #very large positive
411 d = Decimal(500000123)
412 self.assertEqual(str(d), '500000123')
413
414 #negative
415 d = Decimal(-45)
416 self.assertEqual(str(d), '-45')
417
418 #zero
419 d = Decimal(0)
420 self.assertEqual(str(d), '0')
421
422 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000423
424 #empty
425 self.assertEqual(str(Decimal('')), 'NaN')
426
427 #int
428 self.assertEqual(str(Decimal('45')), '45')
429
430 #float
431 self.assertEqual(str(Decimal('45.34')), '45.34')
432
433 #engineer notation
434 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
435
436 #just not a number
437 self.assertEqual(str(Decimal('ugly')), 'NaN')
438
Christian Heimesa62da1d2008-01-12 19:39:10 +0000439 #leading and trailing whitespace permitted
440 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
441 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
442
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000443 def test_explicit_from_tuples(self):
444
445 #zero
446 d = Decimal( (0, (0,), 0) )
447 self.assertEqual(str(d), '0')
448
449 #int
450 d = Decimal( (1, (4, 5), 0) )
451 self.assertEqual(str(d), '-45')
452
453 #float
454 d = Decimal( (0, (4, 5, 3, 4), -2) )
455 self.assertEqual(str(d), '45.34')
456
457 #weird
458 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
459 self.assertEqual(str(d), '-4.34913534E-17')
460
461 #wrong number of items
462 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
463
464 #bad sign
465 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000466 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
467 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
469 #bad exp
470 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000471 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
472 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000473
474 #bad coefficients
475 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
476 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000477 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000478 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479
Antoine Pitrou503ab332010-03-30 18:56:19 +0000480 def test_explicit_from_bool(self):
481 self.assertIs(bool(Decimal(0)), False)
482 self.assertIs(bool(Decimal(1)), True)
483 self.assertEqual(Decimal(False), Decimal(0))
484 self.assertEqual(Decimal(True), Decimal(1))
485
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486 def test_explicit_from_Decimal(self):
487
488 #positive
489 d = Decimal(45)
490 e = Decimal(d)
491 self.assertEqual(str(e), '45')
492 self.assertNotEqual(id(d), id(e))
493
494 #very large positive
495 d = Decimal(500000123)
496 e = Decimal(d)
497 self.assertEqual(str(e), '500000123')
498 self.assertNotEqual(id(d), id(e))
499
500 #negative
501 d = Decimal(-45)
502 e = Decimal(d)
503 self.assertEqual(str(e), '-45')
504 self.assertNotEqual(id(d), id(e))
505
506 #zero
507 d = Decimal(0)
508 e = Decimal(d)
509 self.assertEqual(str(e), '0')
510 self.assertNotEqual(id(d), id(e))
511
Raymond Hettinger96798592010-04-02 16:58:27 +0000512 @requires_IEEE_754
513 def test_explicit_from_float(self):
514 r = Decimal(0.1)
515 self.assertEqual(type(r), Decimal)
516 self.assertEqual(str(r),
517 '0.1000000000000000055511151231257827021181583404541015625')
518 self.assertTrue(Decimal(float('nan')).is_qnan())
519 self.assertTrue(Decimal(float('inf')).is_infinite())
520 self.assertTrue(Decimal(float('-inf')).is_infinite())
521 self.assertEqual(str(Decimal(float('nan'))),
522 str(Decimal('NaN')))
523 self.assertEqual(str(Decimal(float('inf'))),
524 str(Decimal('Infinity')))
525 self.assertEqual(str(Decimal(float('-inf'))),
526 str(Decimal('-Infinity')))
527 self.assertEqual(str(Decimal(float('-0.0'))),
528 str(Decimal('-0')))
529 for i in range(200):
530 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
531 self.assertEqual(x, float(Decimal(x))) # roundtrip
532
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000533 def test_explicit_context_create_decimal(self):
534
535 nc = copy.copy(getcontext())
536 nc.prec = 3
537
538 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000539 d = Decimal()
540 self.assertEqual(str(d), '0')
541 d = nc.create_decimal()
542 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000543
544 # from None
545 self.assertRaises(TypeError, nc.create_decimal, None)
546
547 # from int
548 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000549 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000550 self.assertEqual(nc.create_decimal(45678),
551 nc.create_decimal('457E+2'))
552
553 # from string
554 d = Decimal('456789')
555 self.assertEqual(str(d), '456789')
556 d = nc.create_decimal('456789')
557 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000558 # leading and trailing whitespace should result in a NaN;
559 # spaces are already checked in Cowlishaw's test-suite, so
560 # here we just check that a trailing newline results in a NaN
561 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000562
563 # from tuples
564 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
565 self.assertEqual(str(d), '-4.34913534E-17')
566 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
567 self.assertEqual(str(d), '-4.35E-17')
568
569 # from Decimal
570 prevdec = Decimal(500000123)
571 d = Decimal(prevdec)
572 self.assertEqual(str(d), '500000123')
573 d = nc.create_decimal(prevdec)
574 self.assertEqual(str(d), '5.00E+8')
575
Mark Dickinson345adc42009-08-02 10:14:23 +0000576 def test_unicode_digits(self):
577 test_values = {
578 '\uff11': '1',
579 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
580 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
581 }
582 for input, expected in test_values.items():
583 self.assertEqual(str(Decimal(input)), expected)
584
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000585
586class DecimalImplicitConstructionTest(unittest.TestCase):
587 '''Unit tests for Implicit Construction cases of Decimal.'''
588
589 def test_implicit_from_None(self):
590 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
591
592 def test_implicit_from_int(self):
593 #normal
594 self.assertEqual(str(Decimal(5) + 45), '50')
595 #exceeding precision
596 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
597
598 def test_implicit_from_string(self):
599 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
600
601 def test_implicit_from_float(self):
602 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
603
604 def test_implicit_from_Decimal(self):
605 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
606
Raymond Hettinger267b8682005-03-27 10:47:39 +0000607 def test_rop(self):
608 # Allow other classes to be trained to interact with Decimals
609 class E:
610 def __divmod__(self, other):
611 return 'divmod ' + str(other)
612 def __rdivmod__(self, other):
613 return str(other) + ' rdivmod'
614 def __lt__(self, other):
615 return 'lt ' + str(other)
616 def __gt__(self, other):
617 return 'gt ' + str(other)
618 def __le__(self, other):
619 return 'le ' + str(other)
620 def __ge__(self, other):
621 return 'ge ' + str(other)
622 def __eq__(self, other):
623 return 'eq ' + str(other)
624 def __ne__(self, other):
625 return 'ne ' + str(other)
626
627 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
628 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
629 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
630 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
631 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
632 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
633 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
634 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
635
636 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000637 oplist = [
638 ('+', '__add__', '__radd__'),
639 ('-', '__sub__', '__rsub__'),
640 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000641 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000642 ('%', '__mod__', '__rmod__'),
643 ('//', '__floordiv__', '__rfloordiv__'),
644 ('**', '__pow__', '__rpow__')
645 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000646
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000647 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000648 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
649 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
650 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
651 'str' + lop + '10')
652 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
653 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000654
Mark Dickinson79f52032009-03-17 23:12:51 +0000655
Christian Heimesf16baeb2008-02-29 14:57:44 +0000656class DecimalFormatTest(unittest.TestCase):
657 '''Unit tests for the format function.'''
658 def test_formatting(self):
659 # triples giving a format, a Decimal, and the expected result
660 test_values = [
661 ('e', '0E-15', '0e-15'),
662 ('e', '2.3E-15', '2.3e-15'),
663 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
664 ('e', '2.30000E-15', '2.30000e-15'),
665 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
666 ('e', '1.5', '1.5e+0'),
667 ('e', '0.15', '1.5e-1'),
668 ('e', '0.015', '1.5e-2'),
669 ('e', '0.0000000000015', '1.5e-12'),
670 ('e', '15.0', '1.50e+1'),
671 ('e', '-15', '-1.5e+1'),
672 ('e', '0', '0e+0'),
673 ('e', '0E1', '0e+1'),
674 ('e', '0.0', '0e-1'),
675 ('e', '0.00', '0e-2'),
676 ('.6e', '0E-15', '0.000000e-9'),
677 ('.6e', '0', '0.000000e+6'),
678 ('.6e', '9.999999', '9.999999e+0'),
679 ('.6e', '9.9999999', '1.000000e+1'),
680 ('.6e', '-1.23e5', '-1.230000e+5'),
681 ('.6e', '1.23456789e-3', '1.234568e-3'),
682 ('f', '0', '0'),
683 ('f', '0.0', '0.0'),
684 ('f', '0E-2', '0.00'),
685 ('f', '0.00E-8', '0.0000000000'),
686 ('f', '0E1', '0'), # loses exponent information
687 ('f', '3.2E1', '32'),
688 ('f', '3.2E2', '320'),
689 ('f', '3.20E2', '320'),
690 ('f', '3.200E2', '320.0'),
691 ('f', '3.2E-6', '0.0000032'),
692 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
693 ('.6f', '0E1', '0.000000'),
694 ('.6f', '0', '0.000000'),
695 ('.0f', '0', '0'), # no decimal point
696 ('.0f', '0e-2', '0'),
697 ('.0f', '3.14159265', '3'),
698 ('.1f', '3.14159265', '3.1'),
699 ('.4f', '3.14159265', '3.1416'),
700 ('.6f', '3.14159265', '3.141593'),
701 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
702 ('.8f', '3.14159265', '3.14159265'),
703 ('.9f', '3.14159265', '3.141592650'),
704
705 ('g', '0', '0'),
706 ('g', '0.0', '0.0'),
707 ('g', '0E1', '0e+1'),
708 ('G', '0E1', '0E+1'),
709 ('g', '0E-5', '0.00000'),
710 ('g', '0E-6', '0.000000'),
711 ('g', '0E-7', '0e-7'),
712 ('g', '-0E2', '-0e+2'),
713 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
714 ('.1g', '3.14159265', '3'),
715 ('.2g', '3.14159265', '3.1'),
716 ('.5g', '3.14159265', '3.1416'),
717 ('.7g', '3.14159265', '3.141593'),
718 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
719 ('.9g', '3.14159265', '3.14159265'),
720 ('.10g', '3.14159265', '3.14159265'), # don't pad
721
722 ('%', '0E1', '0%'),
723 ('%', '0E0', '0%'),
724 ('%', '0E-1', '0%'),
725 ('%', '0E-2', '0%'),
726 ('%', '0E-3', '0.0%'),
727 ('%', '0E-4', '0.00%'),
728
729 ('.3%', '0', '0.000%'), # all zeros treated equally
730 ('.3%', '0E10', '0.000%'),
731 ('.3%', '0E-10', '0.000%'),
732 ('.3%', '2.34', '234.000%'),
733 ('.3%', '1.234567', '123.457%'),
734 ('.0%', '1.23', '123%'),
735
736 ('e', 'NaN', 'NaN'),
737 ('f', '-NaN123', '-NaN123'),
738 ('+g', 'NaN456', '+NaN456'),
739 ('.3e', 'Inf', 'Infinity'),
740 ('.16f', '-Inf', '-Infinity'),
741 ('.0g', '-sNaN', '-sNaN'),
742
743 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000744
Mark Dickinson79f52032009-03-17 23:12:51 +0000745 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000746 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000747 ('<6', '123', '123 '),
748 ('>6', '123', ' 123'),
749 ('^6', '123', ' 123 '),
750 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000751 ('#<10', 'NaN', 'NaN#######'),
752 ('#<10', '-4.3', '-4.3######'),
753 ('#<+10', '0.0130', '+0.0130###'),
754 ('#< 10', '0.0130', ' 0.0130###'),
755 ('@>10', '-Inf', '@-Infinity'),
756 ('#>5', '-Inf', '-Infinity'),
757 ('?^5', '123', '?123?'),
758 ('%^6', '123', '%123%%'),
759 (' ^6', '-45.6', '-45.6 '),
760 ('/=10', '-45.6', '-/////45.6'),
761 ('/=+10', '45.6', '+/////45.6'),
762 ('/= 10', '45.6', ' /////45.6'),
763
764 # thousands separator
765 (',', '1234567', '1,234,567'),
766 (',', '123456', '123,456'),
767 (',', '12345', '12,345'),
768 (',', '1234', '1,234'),
769 (',', '123', '123'),
770 (',', '12', '12'),
771 (',', '1', '1'),
772 (',', '0', '0'),
773 (',', '-1234567', '-1,234,567'),
774 (',', '-123456', '-123,456'),
775 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000776 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000777 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
778 ('+08,', '123456', '+123,456'), # but not if there's a sign
779 (' 08,', '123456', ' 123,456'),
780 ('08,', '-123456', '-123,456'),
781 ('+09,', '123456', '+0,123,456'),
782 # ... with fractional part...
783 ('07,', '1234.56', '1,234.56'),
784 ('08,', '1234.56', '1,234.56'),
785 ('09,', '1234.56', '01,234.56'),
786 ('010,', '1234.56', '001,234.56'),
787 ('011,', '1234.56', '0,001,234.56'),
788 ('012,', '1234.56', '0,001,234.56'),
789 ('08,.1f', '1234.5', '01,234.5'),
790 # no thousands separators in fraction part
791 (',', '1.23456789', '1.23456789'),
792 (',%', '123.456789', '12,345.6789%'),
793 (',e', '123456', '1.23456e+5'),
794 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000795
796 # issue 6850
797 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000798 ]
799 for fmt, d, result in test_values:
800 self.assertEqual(format(Decimal(d), fmt), result)
801
Mark Dickinson79f52032009-03-17 23:12:51 +0000802 def test_n_format(self):
803 try:
804 from locale import CHAR_MAX
805 except ImportError:
806 return
807
808 # Set up some localeconv-like dictionaries
809 en_US = {
810 'decimal_point' : '.',
811 'grouping' : [3, 3, 0],
812 'thousands_sep': ','
813 }
814
815 fr_FR = {
816 'decimal_point' : ',',
817 'grouping' : [CHAR_MAX],
818 'thousands_sep' : ''
819 }
820
821 ru_RU = {
822 'decimal_point' : ',',
823 'grouping' : [3, 3, 0],
824 'thousands_sep' : ' '
825 }
826
827 crazy = {
828 'decimal_point' : '&',
829 'grouping' : [1, 4, 2, CHAR_MAX],
830 'thousands_sep' : '-'
831 }
832
833
834 def get_fmt(x, locale, fmt='n'):
835 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
836
837 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
838 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
839 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
840 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
841
842 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
843 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
844 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
845 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
846
847 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
848 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
849 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
850 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
851
Mark Dickinson7303b592009-03-18 08:25:36 +0000852 # zero padding
853 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
854 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
855 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
856 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
857
858 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
859 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
860 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
861 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
862 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
863 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
864
865 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
866 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
867 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
868 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
869 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
870 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
871 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
872 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
873
Mark Dickinson79f52032009-03-17 23:12:51 +0000874
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000875class DecimalArithmeticOperatorsTest(unittest.TestCase):
876 '''Unit tests for all arithmetic operators, binary and unary.'''
877
878 def test_addition(self):
879
880 d1 = Decimal('-11.1')
881 d2 = Decimal('22.2')
882
883 #two Decimals
884 self.assertEqual(d1+d2, Decimal('11.1'))
885 self.assertEqual(d2+d1, Decimal('11.1'))
886
887 #with other type, left
888 c = d1 + 5
889 self.assertEqual(c, Decimal('-6.1'))
890 self.assertEqual(type(c), type(d1))
891
892 #with other type, right
893 c = 5 + d1
894 self.assertEqual(c, Decimal('-6.1'))
895 self.assertEqual(type(c), type(d1))
896
897 #inline with decimal
898 d1 += d2
899 self.assertEqual(d1, Decimal('11.1'))
900
901 #inline with other type
902 d1 += 5
903 self.assertEqual(d1, Decimal('16.1'))
904
905 def test_subtraction(self):
906
907 d1 = Decimal('-11.1')
908 d2 = Decimal('22.2')
909
910 #two Decimals
911 self.assertEqual(d1-d2, Decimal('-33.3'))
912 self.assertEqual(d2-d1, Decimal('33.3'))
913
914 #with other type, left
915 c = d1 - 5
916 self.assertEqual(c, Decimal('-16.1'))
917 self.assertEqual(type(c), type(d1))
918
919 #with other type, right
920 c = 5 - d1
921 self.assertEqual(c, Decimal('16.1'))
922 self.assertEqual(type(c), type(d1))
923
924 #inline with decimal
925 d1 -= d2
926 self.assertEqual(d1, Decimal('-33.3'))
927
928 #inline with other type
929 d1 -= 5
930 self.assertEqual(d1, Decimal('-38.3'))
931
932 def test_multiplication(self):
933
934 d1 = Decimal('-5')
935 d2 = Decimal('3')
936
937 #two Decimals
938 self.assertEqual(d1*d2, Decimal('-15'))
939 self.assertEqual(d2*d1, Decimal('-15'))
940
941 #with other type, left
942 c = d1 * 5
943 self.assertEqual(c, Decimal('-25'))
944 self.assertEqual(type(c), type(d1))
945
946 #with other type, right
947 c = 5 * d1
948 self.assertEqual(c, Decimal('-25'))
949 self.assertEqual(type(c), type(d1))
950
951 #inline with decimal
952 d1 *= d2
953 self.assertEqual(d1, Decimal('-15'))
954
955 #inline with other type
956 d1 *= 5
957 self.assertEqual(d1, Decimal('-75'))
958
959 def test_division(self):
960
961 d1 = Decimal('-5')
962 d2 = Decimal('2')
963
964 #two Decimals
965 self.assertEqual(d1/d2, Decimal('-2.5'))
966 self.assertEqual(d2/d1, Decimal('-0.4'))
967
968 #with other type, left
969 c = d1 / 4
970 self.assertEqual(c, Decimal('-1.25'))
971 self.assertEqual(type(c), type(d1))
972
973 #with other type, right
974 c = 4 / d1
975 self.assertEqual(c, Decimal('-0.8'))
976 self.assertEqual(type(c), type(d1))
977
978 #inline with decimal
979 d1 /= d2
980 self.assertEqual(d1, Decimal('-2.5'))
981
982 #inline with other type
983 d1 /= 4
984 self.assertEqual(d1, Decimal('-0.625'))
985
986 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000987
988 d1 = Decimal('5')
989 d2 = Decimal('2')
990
991 #two Decimals
992 self.assertEqual(d1//d2, Decimal('2'))
993 self.assertEqual(d2//d1, Decimal('0'))
994
995 #with other type, left
996 c = d1 // 4
997 self.assertEqual(c, Decimal('1'))
998 self.assertEqual(type(c), type(d1))
999
1000 #with other type, right
1001 c = 7 // d1
1002 self.assertEqual(c, Decimal('1'))
1003 self.assertEqual(type(c), type(d1))
1004
1005 #inline with decimal
1006 d1 //= d2
1007 self.assertEqual(d1, Decimal('2'))
1008
1009 #inline with other type
1010 d1 //= 2
1011 self.assertEqual(d1, Decimal('1'))
1012
1013 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001014
1015 d1 = Decimal('5')
1016 d2 = Decimal('2')
1017
1018 #two Decimals
1019 self.assertEqual(d1**d2, Decimal('25'))
1020 self.assertEqual(d2**d1, Decimal('32'))
1021
1022 #with other type, left
1023 c = d1 ** 4
1024 self.assertEqual(c, Decimal('625'))
1025 self.assertEqual(type(c), type(d1))
1026
1027 #with other type, right
1028 c = 7 ** d1
1029 self.assertEqual(c, Decimal('16807'))
1030 self.assertEqual(type(c), type(d1))
1031
1032 #inline with decimal
1033 d1 **= d2
1034 self.assertEqual(d1, Decimal('25'))
1035
1036 #inline with other type
1037 d1 **= 4
1038 self.assertEqual(d1, Decimal('390625'))
1039
1040 def test_module(self):
1041
1042 d1 = Decimal('5')
1043 d2 = Decimal('2')
1044
1045 #two Decimals
1046 self.assertEqual(d1%d2, Decimal('1'))
1047 self.assertEqual(d2%d1, Decimal('2'))
1048
1049 #with other type, left
1050 c = d1 % 4
1051 self.assertEqual(c, Decimal('1'))
1052 self.assertEqual(type(c), type(d1))
1053
1054 #with other type, right
1055 c = 7 % d1
1056 self.assertEqual(c, Decimal('2'))
1057 self.assertEqual(type(c), type(d1))
1058
1059 #inline with decimal
1060 d1 %= d2
1061 self.assertEqual(d1, Decimal('1'))
1062
1063 #inline with other type
1064 d1 %= 4
1065 self.assertEqual(d1, Decimal('1'))
1066
1067 def test_floor_div_module(self):
1068
1069 d1 = Decimal('5')
1070 d2 = Decimal('2')
1071
1072 #two Decimals
1073 (p, q) = divmod(d1, d2)
1074 self.assertEqual(p, Decimal('2'))
1075 self.assertEqual(q, Decimal('1'))
1076 self.assertEqual(type(p), type(d1))
1077 self.assertEqual(type(q), type(d1))
1078
1079 #with other type, left
1080 (p, q) = divmod(d1, 4)
1081 self.assertEqual(p, Decimal('1'))
1082 self.assertEqual(q, Decimal('1'))
1083 self.assertEqual(type(p), type(d1))
1084 self.assertEqual(type(q), type(d1))
1085
1086 #with other type, right
1087 (p, q) = divmod(7, d1)
1088 self.assertEqual(p, Decimal('1'))
1089 self.assertEqual(q, Decimal('2'))
1090 self.assertEqual(type(p), type(d1))
1091 self.assertEqual(type(q), type(d1))
1092
1093 def test_unary_operators(self):
1094 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1095 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1096 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1097
Christian Heimes77c02eb2008-02-09 02:18:51 +00001098 def test_nan_comparisons(self):
1099 n = Decimal('NaN')
1100 s = Decimal('sNaN')
1101 i = Decimal('Inf')
1102 f = Decimal('2')
1103 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1104 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001105 self.assertTrue(x != y)
1106 self.assertTrue(not (x == y))
1107 self.assertTrue(not (x < y))
1108 self.assertTrue(not (x <= y))
1109 self.assertTrue(not (x > y))
1110 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001111
Mark Dickinson84230a12010-02-18 14:49:50 +00001112 def test_copy_sign(self):
1113 d = Decimal(1).copy_sign(Decimal(-2))
1114
1115 self.assertEqual(Decimal(1).copy_sign(-2), d)
1116 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1117
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001118# The following are two functions used to test threading in the next class
1119
1120def thfunc1(cls):
1121 d1 = Decimal(1)
1122 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001123 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001124 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001125 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001126 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001127
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001128 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1129 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001130 return
1131
1132def thfunc2(cls):
1133 d1 = Decimal(1)
1134 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001135 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001136 thiscontext = getcontext()
1137 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001138 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001139 cls.synchro.set()
1140 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001141
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001142 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001143 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001144 return
1145
1146
1147class DecimalUseOfContextTest(unittest.TestCase):
1148 '''Unit tests for Use of Context cases in Decimal.'''
1149
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001150 try:
1151 import threading
1152 except ImportError:
1153 threading = None
1154
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001155 # Take care executing this test from IDLE, there's an issue in threading
1156 # that hangs IDLE and I couldn't find it
1157
1158 def test_threading(self):
1159 #Test the "threading isolation" of a Context.
1160
1161 self.synchro = threading.Event()
1162 self.finish1 = threading.Event()
1163 self.finish2 = threading.Event()
1164
1165 th1 = threading.Thread(target=thfunc1, args=(self,))
1166 th2 = threading.Thread(target=thfunc2, args=(self,))
1167
1168 th1.start()
1169 th2.start()
1170
1171 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001172 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001173 return
1174
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001175 if threading is None:
1176 del test_threading
1177
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178
1179class DecimalUsabilityTest(unittest.TestCase):
1180 '''Unit tests for Usability cases of Decimal.'''
1181
1182 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183
1184 da = Decimal('23.42')
1185 db = Decimal('23.42')
1186 dc = Decimal('45')
1187
1188 #two Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001189 self.assertTrue(dc > da)
1190 self.assertTrue(dc >= da)
1191 self.assertTrue(da < dc)
1192 self.assertTrue(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001193 self.assertEqual(da, db)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001194 self.assertTrue(da != dc)
1195 self.assertTrue(da <= db)
1196 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001197
1198 #a Decimal and an int
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001199 self.assertTrue(dc > 23)
1200 self.assertTrue(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001201 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001202
1203 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001204 self.assertNotEqual(da, 'ugly')
1205 self.assertNotEqual(da, 32.7)
1206 self.assertNotEqual(da, object())
1207 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001209 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001210 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001211 b = a[:]
1212 random.shuffle(a)
1213 a.sort()
1214 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001215
1216 def test_copy_and_deepcopy_methods(self):
1217 d = Decimal('43.24')
1218 c = copy.copy(d)
1219 self.assertEqual(id(c), id(d))
1220 dc = copy.deepcopy(d)
1221 self.assertEqual(id(dc), id(d))
1222
1223 def test_hash_method(self):
1224 #just that it's hashable
1225 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001226
1227 test_values = [Decimal(sign*(2**m + n))
1228 for m in [0, 14, 15, 16, 17, 30, 31,
1229 32, 33, 62, 63, 64, 65, 66]
1230 for n in range(-10, 10)
1231 for sign in [-1, 1]]
1232 test_values.extend([
1233 Decimal("-0"), # zeros
1234 Decimal("0.00"),
1235 Decimal("-0.000"),
1236 Decimal("0E10"),
1237 Decimal("-0E12"),
1238 Decimal("10.0"), # negative exponent
1239 Decimal("-23.00000"),
1240 Decimal("1230E100"), # positive exponent
1241 Decimal("-4.5678E50"),
1242 # a value for which hash(n) != hash(n % (2**64-1))
1243 # in Python pre-2.6
1244 Decimal(2**64 + 2**32 - 1),
1245 # selection of values which fail with the old (before
1246 # version 2.6) long.__hash__
1247 Decimal("1.634E100"),
1248 Decimal("90.697E100"),
1249 Decimal("188.83E100"),
1250 Decimal("1652.9E100"),
1251 Decimal("56531E100"),
1252 ])
1253
1254 # check that hash(d) == hash(int(d)) for integral values
1255 for value in test_values:
1256 self.assertEqual(hash(value), hash(int(value)))
1257
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001258 #the same hash that to an int
1259 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001260 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001261 self.assertTrue(hash(Decimal('Inf')))
1262 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
Christian Heimes2380ac72008-01-09 00:17:24 +00001264 # check that the value of the hash doesn't depend on the
1265 # current context (issue #1757)
1266 c = getcontext()
1267 old_precision = c.prec
1268 x = Decimal("123456789.1")
1269
1270 c.prec = 6
1271 h1 = hash(x)
1272 c.prec = 10
1273 h2 = hash(x)
1274 c.prec = 16
1275 h3 = hash(x)
1276
1277 self.assertEqual(h1, h2)
1278 self.assertEqual(h1, h3)
1279 c.prec = old_precision
1280
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001281 def test_min_and_max_methods(self):
1282
1283 d1 = Decimal('15.32')
1284 d2 = Decimal('28.5')
1285 l1 = 15
1286 l2 = 28
1287
1288 #between Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001289 self.assertTrue(min(d1,d2) is d1)
1290 self.assertTrue(min(d2,d1) is d1)
1291 self.assertTrue(max(d1,d2) is d2)
1292 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001293
1294 #between Decimal and long
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001295 self.assertTrue(min(d1,l2) is d1)
1296 self.assertTrue(min(l2,d1) is d1)
1297 self.assertTrue(max(l1,d2) is d2)
1298 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001299
1300 def test_as_nonzero(self):
1301 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001302 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001303 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001304 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001305
1306 def test_tostring_methods(self):
1307 #Test str and repr methods.
1308
1309 d = Decimal('15.32')
1310 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001311 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001312
1313 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001314 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001315
1316 d1 = Decimal('66')
1317 d2 = Decimal('15.32')
1318
1319 #int
1320 self.assertEqual(int(d1), 66)
1321 self.assertEqual(int(d2), 15)
1322
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001323 #float
1324 self.assertEqual(float(d1), 66)
1325 self.assertEqual(float(d2), 15.32)
1326
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001327 #floor
1328 test_pairs = [
1329 ('123.00', 123),
1330 ('3.2', 3),
1331 ('3.54', 3),
1332 ('3.899', 3),
1333 ('-2.3', -3),
1334 ('-11.0', -11),
1335 ('0.0', 0),
1336 ('-0E3', 0),
1337 ]
1338 for d, i in test_pairs:
1339 self.assertEqual(math.floor(Decimal(d)), i)
1340 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1341 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1342 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1343 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1344 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1345
1346 #ceiling
1347 test_pairs = [
1348 ('123.00', 123),
1349 ('3.2', 4),
1350 ('3.54', 4),
1351 ('3.899', 4),
1352 ('-2.3', -2),
1353 ('-11.0', -11),
1354 ('0.0', 0),
1355 ('-0E3', 0),
1356 ]
1357 for d, i in test_pairs:
1358 self.assertEqual(math.ceil(Decimal(d)), i)
1359 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1360 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1361 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1362 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1363 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1364
1365 #round, single argument
1366 test_pairs = [
1367 ('123.00', 123),
1368 ('3.2', 3),
1369 ('3.54', 4),
1370 ('3.899', 4),
1371 ('-2.3', -2),
1372 ('-11.0', -11),
1373 ('0.0', 0),
1374 ('-0E3', 0),
1375 ('-3.5', -4),
1376 ('-2.5', -2),
1377 ('-1.5', -2),
1378 ('-0.5', 0),
1379 ('0.5', 0),
1380 ('1.5', 2),
1381 ('2.5', 2),
1382 ('3.5', 4),
1383 ]
1384 for d, i in test_pairs:
1385 self.assertEqual(round(Decimal(d)), i)
1386 self.assertRaises(ValueError, round, Decimal('-NaN'))
1387 self.assertRaises(ValueError, round, Decimal('sNaN'))
1388 self.assertRaises(ValueError, round, Decimal('NaN123'))
1389 self.assertRaises(OverflowError, round, Decimal('Inf'))
1390 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1391
1392 #round, two arguments; this is essentially equivalent
1393 #to quantize, which is already extensively tested
1394 test_triples = [
1395 ('123.456', -4, '0E+4'),
1396 ('123.456', -3, '0E+3'),
1397 ('123.456', -2, '1E+2'),
1398 ('123.456', -1, '1.2E+2'),
1399 ('123.456', 0, '123'),
1400 ('123.456', 1, '123.5'),
1401 ('123.456', 2, '123.46'),
1402 ('123.456', 3, '123.456'),
1403 ('123.456', 4, '123.4560'),
1404 ('123.455', 2, '123.46'),
1405 ('123.445', 2, '123.44'),
1406 ('Inf', 4, 'NaN'),
1407 ('-Inf', -23, 'NaN'),
1408 ('sNaN314', 3, 'NaN314'),
1409 ]
1410 for d, n, r in test_triples:
1411 self.assertEqual(str(round(Decimal(d), n)), r)
1412
1413
1414
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001415 def test_eval_round_trip(self):
1416
1417 #with zero
1418 d = Decimal( (0, (0,), 0) )
1419 self.assertEqual(d, eval(repr(d)))
1420
1421 #int
1422 d = Decimal( (1, (4, 5), 0) )
1423 self.assertEqual(d, eval(repr(d)))
1424
1425 #float
1426 d = Decimal( (0, (4, 5, 3, 4), -2) )
1427 self.assertEqual(d, eval(repr(d)))
1428
1429 #weird
1430 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1431 self.assertEqual(d, eval(repr(d)))
1432
1433 def test_as_tuple(self):
1434
1435 #with zero
1436 d = Decimal(0)
1437 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1438
1439 #int
1440 d = Decimal(-45)
1441 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1442
1443 #complicated string
1444 d = Decimal("-4.34913534E-17")
1445 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1446
1447 #inf
1448 d = Decimal("Infinity")
1449 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1450
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001451 #leading zeros in coefficient should be stripped
1452 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1453 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1454 d = Decimal( (1, (0, 0, 0), 37) )
1455 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1456 d = Decimal( (1, (), 37) )
1457 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1458
1459 #leading zeros in NaN diagnostic info should be stripped
1460 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1461 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1462 d = Decimal( (1, (0, 0, 0), 'N') )
1463 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1464 d = Decimal( (1, (), 'n') )
1465 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1466
1467 #coefficient in infinity should be ignored
1468 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1469 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1470 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1471 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1472
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001473 def test_immutability_operations(self):
1474 # Do operations and check that it didn't change change internal objects.
1475
1476 d1 = Decimal('-25e55')
1477 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001478 d2 = Decimal('33e+33')
1479 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001480
1481 def checkSameDec(operation, useOther=False):
1482 if useOther:
1483 eval("d1." + operation + "(d2)")
1484 self.assertEqual(d1._sign, b1._sign)
1485 self.assertEqual(d1._int, b1._int)
1486 self.assertEqual(d1._exp, b1._exp)
1487 self.assertEqual(d2._sign, b2._sign)
1488 self.assertEqual(d2._int, b2._int)
1489 self.assertEqual(d2._exp, b2._exp)
1490 else:
1491 eval("d1." + operation + "()")
1492 self.assertEqual(d1._sign, b1._sign)
1493 self.assertEqual(d1._int, b1._int)
1494 self.assertEqual(d1._exp, b1._exp)
1495 return
1496
1497 Decimal(d1)
1498 self.assertEqual(d1._sign, b1._sign)
1499 self.assertEqual(d1._int, b1._int)
1500 self.assertEqual(d1._exp, b1._exp)
1501
1502 checkSameDec("__abs__")
1503 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001504 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001505 checkSameDec("__eq__", True)
1506 checkSameDec("__ne__", True)
1507 checkSameDec("__le__", True)
1508 checkSameDec("__lt__", True)
1509 checkSameDec("__ge__", True)
1510 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001511 checkSameDec("__float__")
1512 checkSameDec("__floordiv__", True)
1513 checkSameDec("__hash__")
1514 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001515 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001516 checkSameDec("__mod__", True)
1517 checkSameDec("__mul__", True)
1518 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001519 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001520 checkSameDec("__pos__")
1521 checkSameDec("__pow__", True)
1522 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001523 checkSameDec("__rdivmod__", True)
1524 checkSameDec("__repr__")
1525 checkSameDec("__rfloordiv__", True)
1526 checkSameDec("__rmod__", True)
1527 checkSameDec("__rmul__", True)
1528 checkSameDec("__rpow__", True)
1529 checkSameDec("__rsub__", True)
1530 checkSameDec("__str__")
1531 checkSameDec("__sub__", True)
1532 checkSameDec("__truediv__", True)
1533 checkSameDec("adjusted")
1534 checkSameDec("as_tuple")
1535 checkSameDec("compare", True)
1536 checkSameDec("max", True)
1537 checkSameDec("min", True)
1538 checkSameDec("normalize")
1539 checkSameDec("quantize", True)
1540 checkSameDec("remainder_near", True)
1541 checkSameDec("same_quantum", True)
1542 checkSameDec("sqrt")
1543 checkSameDec("to_eng_string")
1544 checkSameDec("to_integral")
1545
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001546 def test_subclassing(self):
1547 # Different behaviours when subclassing Decimal
1548
1549 class MyDecimal(Decimal):
1550 pass
1551
1552 d1 = MyDecimal(1)
1553 d2 = MyDecimal(2)
1554 d = d1 + d2
1555 self.assertTrue(type(d) is Decimal)
1556
1557 d = d1.max(d2)
1558 self.assertTrue(type(d) is Decimal)
1559
Christian Heimes0348fb62008-03-26 12:55:56 +00001560 def test_implicit_context(self):
1561 # Check results when context given implicitly. (Issue 2478)
1562 c = getcontext()
1563 self.assertEqual(str(Decimal(0).sqrt()),
1564 str(c.sqrt(Decimal(0))))
1565
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001566 def test_conversions_from_int(self):
1567 # Check that methods taking a second Decimal argument will
1568 # always accept an integer in place of a Decimal.
1569 self.assertEqual(Decimal(4).compare(3),
1570 Decimal(4).compare(Decimal(3)))
1571 self.assertEqual(Decimal(4).compare_signal(3),
1572 Decimal(4).compare_signal(Decimal(3)))
1573 self.assertEqual(Decimal(4).compare_total(3),
1574 Decimal(4).compare_total(Decimal(3)))
1575 self.assertEqual(Decimal(4).compare_total_mag(3),
1576 Decimal(4).compare_total_mag(Decimal(3)))
1577 self.assertEqual(Decimal(10101).logical_and(1001),
1578 Decimal(10101).logical_and(Decimal(1001)))
1579 self.assertEqual(Decimal(10101).logical_or(1001),
1580 Decimal(10101).logical_or(Decimal(1001)))
1581 self.assertEqual(Decimal(10101).logical_xor(1001),
1582 Decimal(10101).logical_xor(Decimal(1001)))
1583 self.assertEqual(Decimal(567).max(123),
1584 Decimal(567).max(Decimal(123)))
1585 self.assertEqual(Decimal(567).max_mag(123),
1586 Decimal(567).max_mag(Decimal(123)))
1587 self.assertEqual(Decimal(567).min(123),
1588 Decimal(567).min(Decimal(123)))
1589 self.assertEqual(Decimal(567).min_mag(123),
1590 Decimal(567).min_mag(Decimal(123)))
1591 self.assertEqual(Decimal(567).next_toward(123),
1592 Decimal(567).next_toward(Decimal(123)))
1593 self.assertEqual(Decimal(1234).quantize(100),
1594 Decimal(1234).quantize(Decimal(100)))
1595 self.assertEqual(Decimal(768).remainder_near(1234),
1596 Decimal(768).remainder_near(Decimal(1234)))
1597 self.assertEqual(Decimal(123).rotate(1),
1598 Decimal(123).rotate(Decimal(1)))
1599 self.assertEqual(Decimal(1234).same_quantum(1000),
1600 Decimal(1234).same_quantum(Decimal(1000)))
1601 self.assertEqual(Decimal('9.123').scaleb(-100),
1602 Decimal('9.123').scaleb(Decimal(-100)))
1603 self.assertEqual(Decimal(456).shift(-1),
1604 Decimal(456).shift(Decimal(-1)))
1605
1606 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1607 Decimal(-12).fma(Decimal(45), Decimal(67)))
1608 self.assertEqual(Decimal(-12).fma(45, 67),
1609 Decimal(-12).fma(Decimal(45), Decimal(67)))
1610 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1611 Decimal(-12).fma(Decimal(45), Decimal(67)))
1612
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001613
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614class DecimalPythonAPItests(unittest.TestCase):
1615
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001616 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001617 self.assertTrue(issubclass(Decimal, numbers.Number))
1618 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001619 self.assertIsInstance(Decimal(0), numbers.Number)
1620 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001621
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001622 def test_pickle(self):
1623 d = Decimal('-3.141590000')
1624 p = pickle.dumps(d)
1625 e = pickle.loads(p)
1626 self.assertEqual(d, e)
1627
Raymond Hettinger5548be22004-07-05 18:49:38 +00001628 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001629 for x in range(-250, 250):
1630 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001631 # should work the same as for floats
1632 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001633 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001634 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001635 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001636 self.assertEqual(Decimal(int(d)), r)
1637
Mark Dickinson825fce32009-09-07 18:08:12 +00001638 self.assertRaises(ValueError, int, Decimal('-nan'))
1639 self.assertRaises(ValueError, int, Decimal('snan'))
1640 self.assertRaises(OverflowError, int, Decimal('inf'))
1641 self.assertRaises(OverflowError, int, Decimal('-inf'))
1642
Christian Heimes969fe572008-01-25 11:23:10 +00001643 def test_trunc(self):
1644 for x in range(-250, 250):
1645 s = '%0.2f' % (x / 100.0)
1646 # should work the same as for floats
1647 self.assertEqual(int(Decimal(s)), int(float(s)))
1648 # should work the same as to_integral in the ROUND_DOWN mode
1649 d = Decimal(s)
1650 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001651 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001652
Raymond Hettinger771ed762009-01-03 19:20:32 +00001653 def test_from_float(self):
1654
1655 class MyDecimal(Decimal):
1656 pass
1657
1658 r = MyDecimal.from_float(0.1)
1659 self.assertEqual(type(r), MyDecimal)
1660 self.assertEqual(str(r),
1661 '0.1000000000000000055511151231257827021181583404541015625')
1662 bigint = 12345678901234567890123456789
1663 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001664 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1665 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1666 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001667 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1668 str(Decimal('NaN')))
1669 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1670 str(Decimal('Infinity')))
1671 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1672 str(Decimal('-Infinity')))
1673 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1674 for i in range(200):
1675 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1676 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1677
1678 def test_create_decimal_from_float(self):
1679 context = Context(prec=5, rounding=ROUND_DOWN)
1680 self.assertEqual(
1681 context.create_decimal_from_float(math.pi),
1682 Decimal('3.1415')
1683 )
1684 context = Context(prec=5, rounding=ROUND_UP)
1685 self.assertEqual(
1686 context.create_decimal_from_float(math.pi),
1687 Decimal('3.1416')
1688 )
1689 context = Context(prec=5, traps=[Inexact])
1690 self.assertRaises(
1691 Inexact,
1692 context.create_decimal_from_float,
1693 math.pi
1694 )
1695 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1696 "Decimal('-0')")
1697 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1698 "Decimal('1')")
1699 self.assertEqual(repr(context.create_decimal_from_float(10)),
1700 "Decimal('10')")
1701
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001702class ContextAPItests(unittest.TestCase):
1703
1704 def test_pickle(self):
1705 c = Context()
1706 e = pickle.loads(pickle.dumps(c))
1707 for k in vars(c):
1708 v1 = vars(c)[k]
1709 v2 = vars(e)[k]
1710 self.assertEqual(v1, v2)
1711
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001712 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001713 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1714 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001715
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001716 def test_copy(self):
1717 # All copies should be deep
1718 c = Context()
1719 d = c.copy()
1720 self.assertNotEqual(id(c), id(d))
1721 self.assertNotEqual(id(c.flags), id(d.flags))
1722 self.assertNotEqual(id(c.traps), id(d.traps))
1723
Mark Dickinson84230a12010-02-18 14:49:50 +00001724 def test_abs(self):
1725 c = Context()
1726 d = c.abs(Decimal(-1))
1727 self.assertEqual(c.abs(-1), d)
1728 self.assertRaises(TypeError, c.abs, '-1')
1729
1730 def test_add(self):
1731 c = Context()
1732 d = c.add(Decimal(1), Decimal(1))
1733 self.assertEqual(c.add(1, 1), d)
1734 self.assertEqual(c.add(Decimal(1), 1), d)
1735 self.assertEqual(c.add(1, Decimal(1)), d)
1736 self.assertRaises(TypeError, c.add, '1', 1)
1737 self.assertRaises(TypeError, c.add, 1, '1')
1738
1739 def test_compare(self):
1740 c = Context()
1741 d = c.compare(Decimal(1), Decimal(1))
1742 self.assertEqual(c.compare(1, 1), d)
1743 self.assertEqual(c.compare(Decimal(1), 1), d)
1744 self.assertEqual(c.compare(1, Decimal(1)), d)
1745 self.assertRaises(TypeError, c.compare, '1', 1)
1746 self.assertRaises(TypeError, c.compare, 1, '1')
1747
1748 def test_compare_signal(self):
1749 c = Context()
1750 d = c.compare_signal(Decimal(1), Decimal(1))
1751 self.assertEqual(c.compare_signal(1, 1), d)
1752 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1753 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1754 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1755 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1756
1757 def test_compare_total(self):
1758 c = Context()
1759 d = c.compare_total(Decimal(1), Decimal(1))
1760 self.assertEqual(c.compare_total(1, 1), d)
1761 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1762 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1763 self.assertRaises(TypeError, c.compare_total, '1', 1)
1764 self.assertRaises(TypeError, c.compare_total, 1, '1')
1765
1766 def test_compare_total_mag(self):
1767 c = Context()
1768 d = c.compare_total_mag(Decimal(1), Decimal(1))
1769 self.assertEqual(c.compare_total_mag(1, 1), d)
1770 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1771 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1772 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1773 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1774
1775 def test_copy_abs(self):
1776 c = Context()
1777 d = c.copy_abs(Decimal(-1))
1778 self.assertEqual(c.copy_abs(-1), d)
1779 self.assertRaises(TypeError, c.copy_abs, '-1')
1780
1781 def test_copy_decimal(self):
1782 c = Context()
1783 d = c.copy_decimal(Decimal(-1))
1784 self.assertEqual(c.copy_decimal(-1), d)
1785 self.assertRaises(TypeError, c.copy_decimal, '-1')
1786
1787 def test_copy_negate(self):
1788 c = Context()
1789 d = c.copy_negate(Decimal(-1))
1790 self.assertEqual(c.copy_negate(-1), d)
1791 self.assertRaises(TypeError, c.copy_negate, '-1')
1792
1793 def test_copy_sign(self):
1794 c = Context()
1795 d = c.copy_sign(Decimal(1), Decimal(-2))
1796 self.assertEqual(c.copy_sign(1, -2), d)
1797 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1798 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1799 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1800 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1801
1802 def test_divide(self):
1803 c = Context()
1804 d = c.divide(Decimal(1), Decimal(2))
1805 self.assertEqual(c.divide(1, 2), d)
1806 self.assertEqual(c.divide(Decimal(1), 2), d)
1807 self.assertEqual(c.divide(1, Decimal(2)), d)
1808 self.assertRaises(TypeError, c.divide, '1', 2)
1809 self.assertRaises(TypeError, c.divide, 1, '2')
1810
1811 def test_divide_int(self):
1812 c = Context()
1813 d = c.divide_int(Decimal(1), Decimal(2))
1814 self.assertEqual(c.divide_int(1, 2), d)
1815 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1816 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1817 self.assertRaises(TypeError, c.divide_int, '1', 2)
1818 self.assertRaises(TypeError, c.divide_int, 1, '2')
1819
1820 def test_divmod(self):
1821 c = Context()
1822 d = c.divmod(Decimal(1), Decimal(2))
1823 self.assertEqual(c.divmod(1, 2), d)
1824 self.assertEqual(c.divmod(Decimal(1), 2), d)
1825 self.assertEqual(c.divmod(1, Decimal(2)), d)
1826 self.assertRaises(TypeError, c.divmod, '1', 2)
1827 self.assertRaises(TypeError, c.divmod, 1, '2')
1828
1829 def test_exp(self):
1830 c = Context()
1831 d = c.exp(Decimal(10))
1832 self.assertEqual(c.exp(10), d)
1833 self.assertRaises(TypeError, c.exp, '10')
1834
1835 def test_fma(self):
1836 c = Context()
1837 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1838 self.assertEqual(c.fma(2, 3, 4), d)
1839 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1840 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1841 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1842 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1843 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1844 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1845 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1846
1847 def test_is_finite(self):
1848 c = Context()
1849 d = c.is_finite(Decimal(10))
1850 self.assertEqual(c.is_finite(10), d)
1851 self.assertRaises(TypeError, c.is_finite, '10')
1852
1853 def test_is_infinite(self):
1854 c = Context()
1855 d = c.is_infinite(Decimal(10))
1856 self.assertEqual(c.is_infinite(10), d)
1857 self.assertRaises(TypeError, c.is_infinite, '10')
1858
1859 def test_is_nan(self):
1860 c = Context()
1861 d = c.is_nan(Decimal(10))
1862 self.assertEqual(c.is_nan(10), d)
1863 self.assertRaises(TypeError, c.is_nan, '10')
1864
1865 def test_is_normal(self):
1866 c = Context()
1867 d = c.is_normal(Decimal(10))
1868 self.assertEqual(c.is_normal(10), d)
1869 self.assertRaises(TypeError, c.is_normal, '10')
1870
1871 def test_is_qnan(self):
1872 c = Context()
1873 d = c.is_qnan(Decimal(10))
1874 self.assertEqual(c.is_qnan(10), d)
1875 self.assertRaises(TypeError, c.is_qnan, '10')
1876
1877 def test_is_signed(self):
1878 c = Context()
1879 d = c.is_signed(Decimal(10))
1880 self.assertEqual(c.is_signed(10), d)
1881 self.assertRaises(TypeError, c.is_signed, '10')
1882
1883 def test_is_snan(self):
1884 c = Context()
1885 d = c.is_snan(Decimal(10))
1886 self.assertEqual(c.is_snan(10), d)
1887 self.assertRaises(TypeError, c.is_snan, '10')
1888
1889 def test_is_subnormal(self):
1890 c = Context()
1891 d = c.is_subnormal(Decimal(10))
1892 self.assertEqual(c.is_subnormal(10), d)
1893 self.assertRaises(TypeError, c.is_subnormal, '10')
1894
1895 def test_is_zero(self):
1896 c = Context()
1897 d = c.is_zero(Decimal(10))
1898 self.assertEqual(c.is_zero(10), d)
1899 self.assertRaises(TypeError, c.is_zero, '10')
1900
1901 def test_ln(self):
1902 c = Context()
1903 d = c.ln(Decimal(10))
1904 self.assertEqual(c.ln(10), d)
1905 self.assertRaises(TypeError, c.ln, '10')
1906
1907 def test_log10(self):
1908 c = Context()
1909 d = c.log10(Decimal(10))
1910 self.assertEqual(c.log10(10), d)
1911 self.assertRaises(TypeError, c.log10, '10')
1912
1913 def test_logb(self):
1914 c = Context()
1915 d = c.logb(Decimal(10))
1916 self.assertEqual(c.logb(10), d)
1917 self.assertRaises(TypeError, c.logb, '10')
1918
1919 def test_logical_and(self):
1920 c = Context()
1921 d = c.logical_and(Decimal(1), Decimal(1))
1922 self.assertEqual(c.logical_and(1, 1), d)
1923 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1924 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1925 self.assertRaises(TypeError, c.logical_and, '1', 1)
1926 self.assertRaises(TypeError, c.logical_and, 1, '1')
1927
1928 def test_logical_invert(self):
1929 c = Context()
1930 d = c.logical_invert(Decimal(1000))
1931 self.assertEqual(c.logical_invert(1000), d)
1932 self.assertRaises(TypeError, c.logical_invert, '1000')
1933
1934 def test_logical_or(self):
1935 c = Context()
1936 d = c.logical_or(Decimal(1), Decimal(1))
1937 self.assertEqual(c.logical_or(1, 1), d)
1938 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1939 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1940 self.assertRaises(TypeError, c.logical_or, '1', 1)
1941 self.assertRaises(TypeError, c.logical_or, 1, '1')
1942
1943 def test_logical_xor(self):
1944 c = Context()
1945 d = c.logical_xor(Decimal(1), Decimal(1))
1946 self.assertEqual(c.logical_xor(1, 1), d)
1947 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1948 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1949 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1950 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1951
1952 def test_max(self):
1953 c = Context()
1954 d = c.max(Decimal(1), Decimal(2))
1955 self.assertEqual(c.max(1, 2), d)
1956 self.assertEqual(c.max(Decimal(1), 2), d)
1957 self.assertEqual(c.max(1, Decimal(2)), d)
1958 self.assertRaises(TypeError, c.max, '1', 2)
1959 self.assertRaises(TypeError, c.max, 1, '2')
1960
1961 def test_max_mag(self):
1962 c = Context()
1963 d = c.max_mag(Decimal(1), Decimal(2))
1964 self.assertEqual(c.max_mag(1, 2), d)
1965 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1966 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1967 self.assertRaises(TypeError, c.max_mag, '1', 2)
1968 self.assertRaises(TypeError, c.max_mag, 1, '2')
1969
1970 def test_min(self):
1971 c = Context()
1972 d = c.min(Decimal(1), Decimal(2))
1973 self.assertEqual(c.min(1, 2), d)
1974 self.assertEqual(c.min(Decimal(1), 2), d)
1975 self.assertEqual(c.min(1, Decimal(2)), d)
1976 self.assertRaises(TypeError, c.min, '1', 2)
1977 self.assertRaises(TypeError, c.min, 1, '2')
1978
1979 def test_min_mag(self):
1980 c = Context()
1981 d = c.min_mag(Decimal(1), Decimal(2))
1982 self.assertEqual(c.min_mag(1, 2), d)
1983 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1984 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1985 self.assertRaises(TypeError, c.min_mag, '1', 2)
1986 self.assertRaises(TypeError, c.min_mag, 1, '2')
1987
1988 def test_minus(self):
1989 c = Context()
1990 d = c.minus(Decimal(10))
1991 self.assertEqual(c.minus(10), d)
1992 self.assertRaises(TypeError, c.minus, '10')
1993
1994 def test_multiply(self):
1995 c = Context()
1996 d = c.multiply(Decimal(1), Decimal(2))
1997 self.assertEqual(c.multiply(1, 2), d)
1998 self.assertEqual(c.multiply(Decimal(1), 2), d)
1999 self.assertEqual(c.multiply(1, Decimal(2)), d)
2000 self.assertRaises(TypeError, c.multiply, '1', 2)
2001 self.assertRaises(TypeError, c.multiply, 1, '2')
2002
2003 def test_next_minus(self):
2004 c = Context()
2005 d = c.next_minus(Decimal(10))
2006 self.assertEqual(c.next_minus(10), d)
2007 self.assertRaises(TypeError, c.next_minus, '10')
2008
2009 def test_next_plus(self):
2010 c = Context()
2011 d = c.next_plus(Decimal(10))
2012 self.assertEqual(c.next_plus(10), d)
2013 self.assertRaises(TypeError, c.next_plus, '10')
2014
2015 def test_next_toward(self):
2016 c = Context()
2017 d = c.next_toward(Decimal(1), Decimal(2))
2018 self.assertEqual(c.next_toward(1, 2), d)
2019 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2020 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2021 self.assertRaises(TypeError, c.next_toward, '1', 2)
2022 self.assertRaises(TypeError, c.next_toward, 1, '2')
2023
2024 def test_normalize(self):
2025 c = Context()
2026 d = c.normalize(Decimal(10))
2027 self.assertEqual(c.normalize(10), d)
2028 self.assertRaises(TypeError, c.normalize, '10')
2029
2030 def test_number_class(self):
2031 c = Context()
2032 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2033 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2034 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2035
2036 def test_power(self):
2037 c = Context()
2038 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2039 self.assertEqual(c.power(1, 4, 2), d)
2040 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2041 self.assertEqual(c.power(1, Decimal(4), 2), d)
2042 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2043 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2044 self.assertRaises(TypeError, c.power, '1', 4, 2)
2045 self.assertRaises(TypeError, c.power, 1, '4', 2)
2046 self.assertRaises(TypeError, c.power, 1, 4, '2')
2047
2048 def test_plus(self):
2049 c = Context()
2050 d = c.plus(Decimal(10))
2051 self.assertEqual(c.plus(10), d)
2052 self.assertRaises(TypeError, c.plus, '10')
2053
2054 def test_quantize(self):
2055 c = Context()
2056 d = c.quantize(Decimal(1), Decimal(2))
2057 self.assertEqual(c.quantize(1, 2), d)
2058 self.assertEqual(c.quantize(Decimal(1), 2), d)
2059 self.assertEqual(c.quantize(1, Decimal(2)), d)
2060 self.assertRaises(TypeError, c.quantize, '1', 2)
2061 self.assertRaises(TypeError, c.quantize, 1, '2')
2062
2063 def test_remainder(self):
2064 c = Context()
2065 d = c.remainder(Decimal(1), Decimal(2))
2066 self.assertEqual(c.remainder(1, 2), d)
2067 self.assertEqual(c.remainder(Decimal(1), 2), d)
2068 self.assertEqual(c.remainder(1, Decimal(2)), d)
2069 self.assertRaises(TypeError, c.remainder, '1', 2)
2070 self.assertRaises(TypeError, c.remainder, 1, '2')
2071
2072 def test_remainder_near(self):
2073 c = Context()
2074 d = c.remainder_near(Decimal(1), Decimal(2))
2075 self.assertEqual(c.remainder_near(1, 2), d)
2076 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2077 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2078 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2079 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2080
2081 def test_rotate(self):
2082 c = Context()
2083 d = c.rotate(Decimal(1), Decimal(2))
2084 self.assertEqual(c.rotate(1, 2), d)
2085 self.assertEqual(c.rotate(Decimal(1), 2), d)
2086 self.assertEqual(c.rotate(1, Decimal(2)), d)
2087 self.assertRaises(TypeError, c.rotate, '1', 2)
2088 self.assertRaises(TypeError, c.rotate, 1, '2')
2089
2090 def test_sqrt(self):
2091 c = Context()
2092 d = c.sqrt(Decimal(10))
2093 self.assertEqual(c.sqrt(10), d)
2094 self.assertRaises(TypeError, c.sqrt, '10')
2095
2096 def test_same_quantum(self):
2097 c = Context()
2098 d = c.same_quantum(Decimal(1), Decimal(2))
2099 self.assertEqual(c.same_quantum(1, 2), d)
2100 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2101 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2102 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2103 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2104
2105 def test_scaleb(self):
2106 c = Context()
2107 d = c.scaleb(Decimal(1), Decimal(2))
2108 self.assertEqual(c.scaleb(1, 2), d)
2109 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2110 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2111 self.assertRaises(TypeError, c.scaleb, '1', 2)
2112 self.assertRaises(TypeError, c.scaleb, 1, '2')
2113
2114 def test_shift(self):
2115 c = Context()
2116 d = c.shift(Decimal(1), Decimal(2))
2117 self.assertEqual(c.shift(1, 2), d)
2118 self.assertEqual(c.shift(Decimal(1), 2), d)
2119 self.assertEqual(c.shift(1, Decimal(2)), d)
2120 self.assertRaises(TypeError, c.shift, '1', 2)
2121 self.assertRaises(TypeError, c.shift, 1, '2')
2122
2123 def test_subtract(self):
2124 c = Context()
2125 d = c.subtract(Decimal(1), Decimal(2))
2126 self.assertEqual(c.subtract(1, 2), d)
2127 self.assertEqual(c.subtract(Decimal(1), 2), d)
2128 self.assertEqual(c.subtract(1, Decimal(2)), d)
2129 self.assertRaises(TypeError, c.subtract, '1', 2)
2130 self.assertRaises(TypeError, c.subtract, 1, '2')
2131
2132 def test_to_eng_string(self):
2133 c = Context()
2134 d = c.to_eng_string(Decimal(10))
2135 self.assertEqual(c.to_eng_string(10), d)
2136 self.assertRaises(TypeError, c.to_eng_string, '10')
2137
2138 def test_to_sci_string(self):
2139 c = Context()
2140 d = c.to_sci_string(Decimal(10))
2141 self.assertEqual(c.to_sci_string(10), d)
2142 self.assertRaises(TypeError, c.to_sci_string, '10')
2143
2144 def test_to_integral_exact(self):
2145 c = Context()
2146 d = c.to_integral_exact(Decimal(10))
2147 self.assertEqual(c.to_integral_exact(10), d)
2148 self.assertRaises(TypeError, c.to_integral_exact, '10')
2149
2150 def test_to_integral_value(self):
2151 c = Context()
2152 d = c.to_integral_value(Decimal(10))
2153 self.assertEqual(c.to_integral_value(10), d)
2154 self.assertRaises(TypeError, c.to_integral_value, '10')
2155
Thomas Wouters89f507f2006-12-13 04:49:30 +00002156class WithStatementTest(unittest.TestCase):
2157 # Can't do these as docstrings until Python 2.6
2158 # as doctest can't handle __future__ statements
2159
2160 def test_localcontext(self):
2161 # Use a copy of the current context in the block
2162 orig_ctx = getcontext()
2163 with localcontext() as enter_ctx:
2164 set_ctx = getcontext()
2165 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002166 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2167 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2168 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002169
2170 def test_localcontextarg(self):
2171 # Use a copy of the supplied context in the block
2172 orig_ctx = getcontext()
2173 new_ctx = Context(prec=42)
2174 with localcontext(new_ctx) as enter_ctx:
2175 set_ctx = getcontext()
2176 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002177 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2178 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2179 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2180 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002181
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002182class ContextFlags(unittest.TestCase):
2183 def test_flags_irrelevant(self):
2184 # check that the result (numeric result + flags raised) of an
2185 # arithmetic operation doesn't depend on the current flags
2186
2187 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2188 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2189
2190 # operations that raise various flags, in the form (function, arglist)
2191 operations = [
2192 (context._apply, [Decimal("100E-1000000009")]),
2193 (context.sqrt, [Decimal(2)]),
2194 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2195 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2196 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2197 ]
2198
2199 # try various flags individually, then a whole lot at once
2200 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2201 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2202
2203 for fn, args in operations:
2204 # find answer and flags raised using a clean context
2205 context.clear_flags()
2206 ans = fn(*args)
2207 flags = [k for k, v in context.flags.items() if v]
2208
2209 for extra_flags in flagsets:
2210 # set flags, before calling operation
2211 context.clear_flags()
2212 for flag in extra_flags:
2213 context._raise_error(flag)
2214 new_ans = fn(*args)
2215
2216 # flags that we expect to be set after the operation
2217 expected_flags = list(flags)
2218 for flag in extra_flags:
2219 if flag not in expected_flags:
2220 expected_flags.append(flag)
2221 expected_flags.sort(key=id)
2222
2223 # flags we actually got
2224 new_flags = [k for k,v in context.flags.items() if v]
2225 new_flags.sort(key=id)
2226
2227 self.assertEqual(ans, new_ans,
2228 "operation produces different answers depending on flags set: " +
2229 "expected %s, got %s." % (ans, new_ans))
2230 self.assertEqual(new_flags, expected_flags,
2231 "operation raises different flags depending on flags set: " +
2232 "expected %s, got %s" % (expected_flags, new_flags))
2233
2234def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002235 """ Execute the tests.
2236
Raymond Hettingered20ad82004-09-04 20:09:13 +00002237 Runs all arithmetic tests if arith is True or if the "decimal" resource
2238 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002239 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002240
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002241 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002242 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002243 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002244 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002245
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002246 if todo_tests is None:
2247 test_classes = [
2248 DecimalExplicitConstructionTest,
2249 DecimalImplicitConstructionTest,
2250 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002251 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002252 DecimalUseOfContextTest,
2253 DecimalUsabilityTest,
2254 DecimalPythonAPItests,
2255 ContextAPItests,
2256 DecimalTest,
2257 WithStatementTest,
2258 ContextFlags
2259 ]
2260 else:
2261 test_classes = [DecimalTest]
2262
2263 # Dynamically build custom test definition for each file in the test
2264 # directory and add the definitions to the DecimalTest class. This
2265 # procedure insures that new files do not get skipped.
2266 for filename in os.listdir(directory):
2267 if '.decTest' not in filename or filename.startswith("."):
2268 continue
2269 head, tail = filename.split('.')
2270 if todo_tests is not None and head not in todo_tests:
2271 continue
2272 tester = lambda self, f=filename: self.eval_file(directory + f)
2273 setattr(DecimalTest, 'test_' + head, tester)
2274 del filename, head, tail, tester
2275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002276
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002277 try:
2278 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002279 if todo_tests is None:
2280 import decimal as DecimalModule
2281 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002282 finally:
2283 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002284
2285if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002286 import optparse
2287 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2288 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2289 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2290 (opt, args) = p.parse_args()
2291
2292 if opt.skip:
2293 test_main(arith=False, verbose=True)
2294 elif args:
2295 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002296 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002297 test_main(arith=True, verbose=True)