blob: f40de8f2078cf9fb15c5b1b60dcb80a2ca44e851 [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 Petersonee8712c2008-05-20 21:35:26 +000034from test.support import (TestSkipped, run_unittest, run_doctest,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000035 is_resource_enabled)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000036import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000037try:
38 import threading
39except ImportError:
40 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000041
Raymond Hettingerfed52962004-07-14 15:41:57 +000042# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000045# Tests are built around these assumed context defaults.
46# test_main() restores the original context.
47def init():
48 global ORIGINAL_CONTEXT
49 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000050 DefaultTestContext = Context(
51 prec = 9,
52 rounding = ROUND_HALF_EVEN,
53 traps = dict.fromkeys(Signals, 0)
54 )
55 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000056
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000057TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000058if __name__ == '__main__':
59 file = sys.argv[0]
60else:
61 file = __file__
62testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000063directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000064
Raymond Hettinger267b8682005-03-27 10:47:39 +000065skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000066
67# Make sure it actually raises errors when not expected and caught in flags
68# Slower, since it runs some things several times.
69EXTENDEDERRORTEST = False
70
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000071#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000072ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000073 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000074 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000075 'division_impossible' : InvalidOperation,
76 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000078 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000079 'invalid_operation' : InvalidOperation,
80 'overflow' : Overflow,
81 'rounded' : Rounded,
82 'subnormal' : Subnormal,
83 'underflow' : Underflow}
84
85
86def Nonfunction(*args):
87 """Doesn't do anything."""
88 return None
89
90RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
91 'down' : ROUND_DOWN,
92 'floor' : ROUND_FLOOR,
93 'half_down' : ROUND_HALF_DOWN,
94 'half_even' : ROUND_HALF_EVEN,
95 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +000096 'up' : ROUND_UP,
97 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000098
99# Name adapter to be able to change the Decimal and Context
100# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000101nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000102 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000103 'class':'number_class',
104 'comparesig':'compare_signal',
105 'comparetotal':'compare_total',
106 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000108 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000109 'copynegate':'copy_negate',
110 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000111 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000113 'iscanonical':'is_canonical',
114 'isfinite':'is_finite',
115 'isinfinite':'is_infinite',
116 'isnan':'is_nan',
117 'isnormal':'is_normal',
118 'isqnan':'is_qnan',
119 'issigned':'is_signed',
120 'issnan':'is_snan',
121 'issubnormal':'is_subnormal',
122 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 'maxmag':'max_mag',
124 'minmag':'min_mag',
125 'nextminus':'next_minus',
126 'nextplus':'next_plus',
127 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000128 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000130 'remaindernear':'remainder_near',
131 'samequantum':'same_quantum',
132 'squareroot':'sqrt',
133 'toeng':'to_eng_string',
134 'tointegral':'to_integral_value',
135 'tointegralx':'to_integral_exact',
136 'tosci':'to_sci_string',
137 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000138 }
139
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000140# The following functions return True/False rather than a Decimal instance
141
142LOGICAL_FUNCTIONS = (
143 'is_canonical',
144 'is_finite',
145 'is_infinite',
146 'is_nan',
147 'is_normal',
148 'is_qnan',
149 'is_signed',
150 'is_snan',
151 'is_subnormal',
152 'is_zero',
153 'same_quantum',
154 )
155
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000156# For some operations (currently exp, ln, log10, power), the decNumber
157# reference implementation imposes additional restrictions on the
158# context and operands. These restrictions are not part of the
159# specification; however, the effect of these restrictions does show
160# up in some of the testcases. We skip testcases that violate these
161# restrictions, since Decimal behaves differently from decNumber for
162# these testcases so these testcases would otherwise fail.
163
164decNumberRestricted = ('power', 'ln', 'log10', 'exp')
165DEC_MAX_MATH = 999999
166def outside_decNumber_bounds(v, context):
167 if (context.prec > DEC_MAX_MATH or
168 context.Emax > DEC_MAX_MATH or
169 -context.Emin > DEC_MAX_MATH):
170 return True
171 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000172 v.adjusted() > DEC_MAX_MATH or
173 v.adjusted() < 1-2*DEC_MAX_MATH):
174 return True
175 return False
176
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000177class DecimalTest(unittest.TestCase):
178 """Class which tests the Decimal class against the test cases.
179
180 Changed for unittest.
181 """
182 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000183 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184 self.ignore_list = ['#']
185 # Basically, a # means return NaN InvalidOperation.
186 # Different from a sNaN in trim
187
188 self.ChangeDict = {'precision' : self.change_precision,
189 'rounding' : self.change_rounding_method,
190 'maxexponent' : self.change_max_exponent,
191 'minexponent' : self.change_min_exponent,
192 'clamp' : self.change_clamp}
193
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000194 def eval_file(self, file):
195 global skip_expected
196 if skip_expected:
197 raise TestSkipped
198 return
Neal Norwitz70967602006-03-17 08:29:44 +0000199 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000201 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000202 try:
203 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000204 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205 #Exception raised where there shoudn't have been one.
206 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
207
208 return
209
210 def eval_line(self, s):
211 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
212 s = (s.split('->')[0] + '->' +
213 s.split('->')[1].split('--')[0]).strip()
214 else:
215 s = s.split('--')[0].strip()
216
217 for ignore in self.ignore_list:
218 if s.find(ignore) >= 0:
219 #print s.split()[0], 'NotImplemented--', ignore
220 return
221 if not s:
222 return
223 elif ':' in s:
224 return self.eval_directive(s)
225 else:
226 return self.eval_equation(s)
227
228 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000229 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000230 if funct == 'rounding':
231 value = RoundingDict[value]
232 else:
233 try:
234 value = int(value)
235 except ValueError:
236 pass
237
238 funct = self.ChangeDict.get(funct, Nonfunction)
239 funct(value)
240
241 def eval_equation(self, s):
242 #global DEFAULT_PRECISION
243 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000244
245 if not TEST_ALL and random.random() < 0.90:
246 return
247
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000248 try:
249 Sides = s.split('->')
250 L = Sides[0].strip().split()
251 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000252 if DEBUG:
253 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000254 funct = L[1].lower()
255 valstemp = L[2:]
256 L = Sides[1].strip().split()
257 ans = L[0]
258 exceptions = L[1:]
259 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000260 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000261 def FixQuotes(val):
262 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
263 val = val.replace("'", '').replace('"', '')
264 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
265 return val
266 fname = nameAdapter.get(funct, funct)
267 if fname == 'rescale':
268 return
269 funct = getattr(self.context, fname)
270 vals = []
271 conglomerate = ''
272 quote = 0
273 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
274
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000275 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000276 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000278 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000279 for i, val in enumerate(valstemp):
280 if val.count("'") % 2 == 1:
281 quote = 1 - quote
282 if quote:
283 conglomerate = conglomerate + ' ' + val
284 continue
285 else:
286 val = conglomerate + val
287 conglomerate = ''
288 v = FixQuotes(val)
289 if fname in ('to_sci_string', 'to_eng_string'):
290 if EXTENDEDERRORTEST:
291 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000292 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 try:
294 funct(self.context.create_decimal(v))
295 except error:
296 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000297 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000298 self.fail("Raised %s in %s when %s disabled" % \
299 (e, s, error))
300 else:
301 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000302 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303 v = self.context.create_decimal(v)
304 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000305 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000306 vals.append(v)
307
308 ans = FixQuotes(ans)
309
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000310 # skip tests that are related to bounds imposed in the decNumber
311 # reference implementation
312 if fname in decNumberRestricted:
313 if fname == 'power':
314 if not (vals[1]._isinteger() and
315 -1999999997 <= vals[1] <= 999999999):
316 if outside_decNumber_bounds(vals[0], self.context) or \
317 outside_decNumber_bounds(vals[1], self.context):
318 #print "Skipping test %s" % s
319 return
320 else:
321 if outside_decNumber_bounds(vals[0], self.context):
322 #print "Skipping test %s" % s
323 return
324
325
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
327 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000328 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 try:
330 funct(*vals)
331 except error:
332 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000333 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000334 self.fail("Raised %s in %s when %s disabled" % \
335 (e, s, error))
336 else:
337 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000338 self.context.traps[error] = 0
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000339 if DEBUG:
340 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000341 try:
342 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000343 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000345 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000346 self.fail("Raised %s in %s" % (error, s))
347 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000348 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 raise
350
351 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000352 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000353
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000354 myexceptions.sort(key=repr)
355 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356
357 self.assertEqual(result, ans,
358 'Incorrect answer for ' + s + ' -- got ' + result)
359 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000360 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000361 return
362
363 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000364 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000365
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000366 def change_precision(self, prec):
367 self.context.prec = prec
368 def change_rounding_method(self, rounding):
369 self.context.rounding = rounding
370 def change_min_exponent(self, exp):
371 self.context.Emin = exp
372 def change_max_exponent(self, exp):
373 self.context.Emax = exp
374 def change_clamp(self, clamp):
375 self.context._clamp = clamp
376
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377
378
379# The following classes test the behaviour of Decimal according to PEP 327
380
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381class DecimalExplicitConstructionTest(unittest.TestCase):
382 '''Unit tests for Explicit Construction cases of Decimal.'''
383
384 def test_explicit_empty(self):
385 self.assertEqual(Decimal(), Decimal("0"))
386
387 def test_explicit_from_None(self):
388 self.assertRaises(TypeError, Decimal, None)
389
390 def test_explicit_from_int(self):
391
392 #positive
393 d = Decimal(45)
394 self.assertEqual(str(d), '45')
395
396 #very large positive
397 d = Decimal(500000123)
398 self.assertEqual(str(d), '500000123')
399
400 #negative
401 d = Decimal(-45)
402 self.assertEqual(str(d), '-45')
403
404 #zero
405 d = Decimal(0)
406 self.assertEqual(str(d), '0')
407
408 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000409
410 #empty
411 self.assertEqual(str(Decimal('')), 'NaN')
412
413 #int
414 self.assertEqual(str(Decimal('45')), '45')
415
416 #float
417 self.assertEqual(str(Decimal('45.34')), '45.34')
418
419 #engineer notation
420 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
421
422 #just not a number
423 self.assertEqual(str(Decimal('ugly')), 'NaN')
424
Christian Heimesa62da1d2008-01-12 19:39:10 +0000425 #leading and trailing whitespace permitted
426 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
427 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
428
Benjamin Peterson41181742008-07-02 20:22:54 +0000429 #but alternate unicode digits should not
430 self.assertEqual(str(Decimal('\uff11')), 'NaN')
431
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000432 def test_explicit_from_tuples(self):
433
434 #zero
435 d = Decimal( (0, (0,), 0) )
436 self.assertEqual(str(d), '0')
437
438 #int
439 d = Decimal( (1, (4, 5), 0) )
440 self.assertEqual(str(d), '-45')
441
442 #float
443 d = Decimal( (0, (4, 5, 3, 4), -2) )
444 self.assertEqual(str(d), '45.34')
445
446 #weird
447 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
448 self.assertEqual(str(d), '-4.34913534E-17')
449
450 #wrong number of items
451 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
452
453 #bad sign
454 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000455 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
456 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000457
458 #bad exp
459 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000460 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
461 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462
463 #bad coefficients
464 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
465 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000466 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000467 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
469 def test_explicit_from_Decimal(self):
470
471 #positive
472 d = Decimal(45)
473 e = Decimal(d)
474 self.assertEqual(str(e), '45')
475 self.assertNotEqual(id(d), id(e))
476
477 #very large positive
478 d = Decimal(500000123)
479 e = Decimal(d)
480 self.assertEqual(str(e), '500000123')
481 self.assertNotEqual(id(d), id(e))
482
483 #negative
484 d = Decimal(-45)
485 e = Decimal(d)
486 self.assertEqual(str(e), '-45')
487 self.assertNotEqual(id(d), id(e))
488
489 #zero
490 d = Decimal(0)
491 e = Decimal(d)
492 self.assertEqual(str(e), '0')
493 self.assertNotEqual(id(d), id(e))
494
495 def test_explicit_context_create_decimal(self):
496
497 nc = copy.copy(getcontext())
498 nc.prec = 3
499
500 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000501 d = Decimal()
502 self.assertEqual(str(d), '0')
503 d = nc.create_decimal()
504 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505
506 # from None
507 self.assertRaises(TypeError, nc.create_decimal, None)
508
509 # from int
510 d = nc.create_decimal(456)
511 self.failUnless(isinstance(d, Decimal))
512 self.assertEqual(nc.create_decimal(45678),
513 nc.create_decimal('457E+2'))
514
515 # from string
516 d = Decimal('456789')
517 self.assertEqual(str(d), '456789')
518 d = nc.create_decimal('456789')
519 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000520 # leading and trailing whitespace should result in a NaN;
521 # spaces are already checked in Cowlishaw's test-suite, so
522 # here we just check that a trailing newline results in a NaN
523 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000524
525 # from tuples
526 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
527 self.assertEqual(str(d), '-4.34913534E-17')
528 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
529 self.assertEqual(str(d), '-4.35E-17')
530
531 # from Decimal
532 prevdec = Decimal(500000123)
533 d = Decimal(prevdec)
534 self.assertEqual(str(d), '500000123')
535 d = nc.create_decimal(prevdec)
536 self.assertEqual(str(d), '5.00E+8')
537
538
539class DecimalImplicitConstructionTest(unittest.TestCase):
540 '''Unit tests for Implicit Construction cases of Decimal.'''
541
542 def test_implicit_from_None(self):
543 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
544
545 def test_implicit_from_int(self):
546 #normal
547 self.assertEqual(str(Decimal(5) + 45), '50')
548 #exceeding precision
549 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
550
551 def test_implicit_from_string(self):
552 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
553
554 def test_implicit_from_float(self):
555 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
556
557 def test_implicit_from_Decimal(self):
558 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
559
Raymond Hettinger267b8682005-03-27 10:47:39 +0000560 def test_rop(self):
561 # Allow other classes to be trained to interact with Decimals
562 class E:
563 def __divmod__(self, other):
564 return 'divmod ' + str(other)
565 def __rdivmod__(self, other):
566 return str(other) + ' rdivmod'
567 def __lt__(self, other):
568 return 'lt ' + str(other)
569 def __gt__(self, other):
570 return 'gt ' + str(other)
571 def __le__(self, other):
572 return 'le ' + str(other)
573 def __ge__(self, other):
574 return 'ge ' + str(other)
575 def __eq__(self, other):
576 return 'eq ' + str(other)
577 def __ne__(self, other):
578 return 'ne ' + str(other)
579
580 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
581 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
582 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
583 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
584 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
585 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
586 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
587 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
588
589 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000590 oplist = [
591 ('+', '__add__', '__radd__'),
592 ('-', '__sub__', '__rsub__'),
593 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000594 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000595 ('%', '__mod__', '__rmod__'),
596 ('//', '__floordiv__', '__rfloordiv__'),
597 ('**', '__pow__', '__rpow__')
598 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000599
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000600 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000601 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
602 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
603 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
604 'str' + lop + '10')
605 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
606 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
Christian Heimesf16baeb2008-02-29 14:57:44 +0000608class DecimalFormatTest(unittest.TestCase):
609 '''Unit tests for the format function.'''
610 def test_formatting(self):
611 # triples giving a format, a Decimal, and the expected result
612 test_values = [
613 ('e', '0E-15', '0e-15'),
614 ('e', '2.3E-15', '2.3e-15'),
615 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
616 ('e', '2.30000E-15', '2.30000e-15'),
617 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
618 ('e', '1.5', '1.5e+0'),
619 ('e', '0.15', '1.5e-1'),
620 ('e', '0.015', '1.5e-2'),
621 ('e', '0.0000000000015', '1.5e-12'),
622 ('e', '15.0', '1.50e+1'),
623 ('e', '-15', '-1.5e+1'),
624 ('e', '0', '0e+0'),
625 ('e', '0E1', '0e+1'),
626 ('e', '0.0', '0e-1'),
627 ('e', '0.00', '0e-2'),
628 ('.6e', '0E-15', '0.000000e-9'),
629 ('.6e', '0', '0.000000e+6'),
630 ('.6e', '9.999999', '9.999999e+0'),
631 ('.6e', '9.9999999', '1.000000e+1'),
632 ('.6e', '-1.23e5', '-1.230000e+5'),
633 ('.6e', '1.23456789e-3', '1.234568e-3'),
634 ('f', '0', '0'),
635 ('f', '0.0', '0.0'),
636 ('f', '0E-2', '0.00'),
637 ('f', '0.00E-8', '0.0000000000'),
638 ('f', '0E1', '0'), # loses exponent information
639 ('f', '3.2E1', '32'),
640 ('f', '3.2E2', '320'),
641 ('f', '3.20E2', '320'),
642 ('f', '3.200E2', '320.0'),
643 ('f', '3.2E-6', '0.0000032'),
644 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
645 ('.6f', '0E1', '0.000000'),
646 ('.6f', '0', '0.000000'),
647 ('.0f', '0', '0'), # no decimal point
648 ('.0f', '0e-2', '0'),
649 ('.0f', '3.14159265', '3'),
650 ('.1f', '3.14159265', '3.1'),
651 ('.4f', '3.14159265', '3.1416'),
652 ('.6f', '3.14159265', '3.141593'),
653 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
654 ('.8f', '3.14159265', '3.14159265'),
655 ('.9f', '3.14159265', '3.141592650'),
656
657 ('g', '0', '0'),
658 ('g', '0.0', '0.0'),
659 ('g', '0E1', '0e+1'),
660 ('G', '0E1', '0E+1'),
661 ('g', '0E-5', '0.00000'),
662 ('g', '0E-6', '0.000000'),
663 ('g', '0E-7', '0e-7'),
664 ('g', '-0E2', '-0e+2'),
665 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
666 ('.1g', '3.14159265', '3'),
667 ('.2g', '3.14159265', '3.1'),
668 ('.5g', '3.14159265', '3.1416'),
669 ('.7g', '3.14159265', '3.141593'),
670 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
671 ('.9g', '3.14159265', '3.14159265'),
672 ('.10g', '3.14159265', '3.14159265'), # don't pad
673
674 ('%', '0E1', '0%'),
675 ('%', '0E0', '0%'),
676 ('%', '0E-1', '0%'),
677 ('%', '0E-2', '0%'),
678 ('%', '0E-3', '0.0%'),
679 ('%', '0E-4', '0.00%'),
680
681 ('.3%', '0', '0.000%'), # all zeros treated equally
682 ('.3%', '0E10', '0.000%'),
683 ('.3%', '0E-10', '0.000%'),
684 ('.3%', '2.34', '234.000%'),
685 ('.3%', '1.234567', '123.457%'),
686 ('.0%', '1.23', '123%'),
687
688 ('e', 'NaN', 'NaN'),
689 ('f', '-NaN123', '-NaN123'),
690 ('+g', 'NaN456', '+NaN456'),
691 ('.3e', 'Inf', 'Infinity'),
692 ('.16f', '-Inf', '-Infinity'),
693 ('.0g', '-sNaN', '-sNaN'),
694
695 ('', '1.00', '1.00'),
696 ]
697 for fmt, d, result in test_values:
698 self.assertEqual(format(Decimal(d), fmt), result)
699
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000700class DecimalArithmeticOperatorsTest(unittest.TestCase):
701 '''Unit tests for all arithmetic operators, binary and unary.'''
702
703 def test_addition(self):
704
705 d1 = Decimal('-11.1')
706 d2 = Decimal('22.2')
707
708 #two Decimals
709 self.assertEqual(d1+d2, Decimal('11.1'))
710 self.assertEqual(d2+d1, Decimal('11.1'))
711
712 #with other type, left
713 c = d1 + 5
714 self.assertEqual(c, Decimal('-6.1'))
715 self.assertEqual(type(c), type(d1))
716
717 #with other type, right
718 c = 5 + d1
719 self.assertEqual(c, Decimal('-6.1'))
720 self.assertEqual(type(c), type(d1))
721
722 #inline with decimal
723 d1 += d2
724 self.assertEqual(d1, Decimal('11.1'))
725
726 #inline with other type
727 d1 += 5
728 self.assertEqual(d1, Decimal('16.1'))
729
730 def test_subtraction(self):
731
732 d1 = Decimal('-11.1')
733 d2 = Decimal('22.2')
734
735 #two Decimals
736 self.assertEqual(d1-d2, Decimal('-33.3'))
737 self.assertEqual(d2-d1, Decimal('33.3'))
738
739 #with other type, left
740 c = d1 - 5
741 self.assertEqual(c, Decimal('-16.1'))
742 self.assertEqual(type(c), type(d1))
743
744 #with other type, right
745 c = 5 - d1
746 self.assertEqual(c, Decimal('16.1'))
747 self.assertEqual(type(c), type(d1))
748
749 #inline with decimal
750 d1 -= d2
751 self.assertEqual(d1, Decimal('-33.3'))
752
753 #inline with other type
754 d1 -= 5
755 self.assertEqual(d1, Decimal('-38.3'))
756
757 def test_multiplication(self):
758
759 d1 = Decimal('-5')
760 d2 = Decimal('3')
761
762 #two Decimals
763 self.assertEqual(d1*d2, Decimal('-15'))
764 self.assertEqual(d2*d1, Decimal('-15'))
765
766 #with other type, left
767 c = d1 * 5
768 self.assertEqual(c, Decimal('-25'))
769 self.assertEqual(type(c), type(d1))
770
771 #with other type, right
772 c = 5 * d1
773 self.assertEqual(c, Decimal('-25'))
774 self.assertEqual(type(c), type(d1))
775
776 #inline with decimal
777 d1 *= d2
778 self.assertEqual(d1, Decimal('-15'))
779
780 #inline with other type
781 d1 *= 5
782 self.assertEqual(d1, Decimal('-75'))
783
784 def test_division(self):
785
786 d1 = Decimal('-5')
787 d2 = Decimal('2')
788
789 #two Decimals
790 self.assertEqual(d1/d2, Decimal('-2.5'))
791 self.assertEqual(d2/d1, Decimal('-0.4'))
792
793 #with other type, left
794 c = d1 / 4
795 self.assertEqual(c, Decimal('-1.25'))
796 self.assertEqual(type(c), type(d1))
797
798 #with other type, right
799 c = 4 / d1
800 self.assertEqual(c, Decimal('-0.8'))
801 self.assertEqual(type(c), type(d1))
802
803 #inline with decimal
804 d1 /= d2
805 self.assertEqual(d1, Decimal('-2.5'))
806
807 #inline with other type
808 d1 /= 4
809 self.assertEqual(d1, Decimal('-0.625'))
810
811 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000812
813 d1 = Decimal('5')
814 d2 = Decimal('2')
815
816 #two Decimals
817 self.assertEqual(d1//d2, Decimal('2'))
818 self.assertEqual(d2//d1, Decimal('0'))
819
820 #with other type, left
821 c = d1 // 4
822 self.assertEqual(c, Decimal('1'))
823 self.assertEqual(type(c), type(d1))
824
825 #with other type, right
826 c = 7 // d1
827 self.assertEqual(c, Decimal('1'))
828 self.assertEqual(type(c), type(d1))
829
830 #inline with decimal
831 d1 //= d2
832 self.assertEqual(d1, Decimal('2'))
833
834 #inline with other type
835 d1 //= 2
836 self.assertEqual(d1, Decimal('1'))
837
838 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000839
840 d1 = Decimal('5')
841 d2 = Decimal('2')
842
843 #two Decimals
844 self.assertEqual(d1**d2, Decimal('25'))
845 self.assertEqual(d2**d1, Decimal('32'))
846
847 #with other type, left
848 c = d1 ** 4
849 self.assertEqual(c, Decimal('625'))
850 self.assertEqual(type(c), type(d1))
851
852 #with other type, right
853 c = 7 ** d1
854 self.assertEqual(c, Decimal('16807'))
855 self.assertEqual(type(c), type(d1))
856
857 #inline with decimal
858 d1 **= d2
859 self.assertEqual(d1, Decimal('25'))
860
861 #inline with other type
862 d1 **= 4
863 self.assertEqual(d1, Decimal('390625'))
864
865 def test_module(self):
866
867 d1 = Decimal('5')
868 d2 = Decimal('2')
869
870 #two Decimals
871 self.assertEqual(d1%d2, Decimal('1'))
872 self.assertEqual(d2%d1, Decimal('2'))
873
874 #with other type, left
875 c = d1 % 4
876 self.assertEqual(c, Decimal('1'))
877 self.assertEqual(type(c), type(d1))
878
879 #with other type, right
880 c = 7 % d1
881 self.assertEqual(c, Decimal('2'))
882 self.assertEqual(type(c), type(d1))
883
884 #inline with decimal
885 d1 %= d2
886 self.assertEqual(d1, Decimal('1'))
887
888 #inline with other type
889 d1 %= 4
890 self.assertEqual(d1, Decimal('1'))
891
892 def test_floor_div_module(self):
893
894 d1 = Decimal('5')
895 d2 = Decimal('2')
896
897 #two Decimals
898 (p, q) = divmod(d1, d2)
899 self.assertEqual(p, Decimal('2'))
900 self.assertEqual(q, Decimal('1'))
901 self.assertEqual(type(p), type(d1))
902 self.assertEqual(type(q), type(d1))
903
904 #with other type, left
905 (p, q) = divmod(d1, 4)
906 self.assertEqual(p, Decimal('1'))
907 self.assertEqual(q, Decimal('1'))
908 self.assertEqual(type(p), type(d1))
909 self.assertEqual(type(q), type(d1))
910
911 #with other type, right
912 (p, q) = divmod(7, d1)
913 self.assertEqual(p, Decimal('1'))
914 self.assertEqual(q, Decimal('2'))
915 self.assertEqual(type(p), type(d1))
916 self.assertEqual(type(q), type(d1))
917
918 def test_unary_operators(self):
919 self.assertEqual(+Decimal(45), Decimal(+45)) # +
920 self.assertEqual(-Decimal(45), Decimal(-45)) # -
921 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
922
Christian Heimes77c02eb2008-02-09 02:18:51 +0000923 def test_nan_comparisons(self):
924 n = Decimal('NaN')
925 s = Decimal('sNaN')
926 i = Decimal('Inf')
927 f = Decimal('2')
928 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
929 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
930 self.assert_(x != y)
931 self.assert_(not (x == y))
932 self.assert_(not (x < y))
933 self.assert_(not (x <= y))
934 self.assert_(not (x > y))
935 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000936
937# The following are two functions used to test threading in the next class
938
939def thfunc1(cls):
940 d1 = Decimal(1)
941 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +0000942 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000943 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000944 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000945 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000946
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000947 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
948 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000949 return
950
951def thfunc2(cls):
952 d1 = Decimal(1)
953 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +0000954 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000955 thiscontext = getcontext()
956 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +0000957 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000958 cls.synchro.set()
959 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000960
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000961 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +0000962 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000963 return
964
965
966class DecimalUseOfContextTest(unittest.TestCase):
967 '''Unit tests for Use of Context cases in Decimal.'''
968
Raymond Hettinger7e71fa52004-12-18 19:07:19 +0000969 try:
970 import threading
971 except ImportError:
972 threading = None
973
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000974 # Take care executing this test from IDLE, there's an issue in threading
975 # that hangs IDLE and I couldn't find it
976
977 def test_threading(self):
978 #Test the "threading isolation" of a Context.
979
980 self.synchro = threading.Event()
981 self.finish1 = threading.Event()
982 self.finish2 = threading.Event()
983
984 th1 = threading.Thread(target=thfunc1, args=(self,))
985 th2 = threading.Thread(target=thfunc2, args=(self,))
986
987 th1.start()
988 th2.start()
989
990 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000991 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000992 return
993
Raymond Hettinger7e71fa52004-12-18 19:07:19 +0000994 if threading is None:
995 del test_threading
996
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000997
998class DecimalUsabilityTest(unittest.TestCase):
999 '''Unit tests for Usability cases of Decimal.'''
1000
1001 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001002
1003 da = Decimal('23.42')
1004 db = Decimal('23.42')
1005 dc = Decimal('45')
1006
1007 #two Decimals
1008 self.failUnless(dc > da)
1009 self.failUnless(dc >= da)
1010 self.failUnless(da < dc)
1011 self.failUnless(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001012 self.assertEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001013 self.failUnless(da != dc)
1014 self.failUnless(da <= db)
1015 self.failUnless(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001016
1017 #a Decimal and an int
1018 self.failUnless(dc > 23)
1019 self.failUnless(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001020 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001021
1022 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001023 self.assertNotEqual(da, 'ugly')
1024 self.assertNotEqual(da, 32.7)
1025 self.assertNotEqual(da, object())
1026 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001027
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001028 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001029 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001030 b = a[:]
1031 random.shuffle(a)
1032 a.sort()
1033 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001034
1035 def test_copy_and_deepcopy_methods(self):
1036 d = Decimal('43.24')
1037 c = copy.copy(d)
1038 self.assertEqual(id(c), id(d))
1039 dc = copy.deepcopy(d)
1040 self.assertEqual(id(dc), id(d))
1041
1042 def test_hash_method(self):
1043 #just that it's hashable
1044 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001045
1046 test_values = [Decimal(sign*(2**m + n))
1047 for m in [0, 14, 15, 16, 17, 30, 31,
1048 32, 33, 62, 63, 64, 65, 66]
1049 for n in range(-10, 10)
1050 for sign in [-1, 1]]
1051 test_values.extend([
1052 Decimal("-0"), # zeros
1053 Decimal("0.00"),
1054 Decimal("-0.000"),
1055 Decimal("0E10"),
1056 Decimal("-0E12"),
1057 Decimal("10.0"), # negative exponent
1058 Decimal("-23.00000"),
1059 Decimal("1230E100"), # positive exponent
1060 Decimal("-4.5678E50"),
1061 # a value for which hash(n) != hash(n % (2**64-1))
1062 # in Python pre-2.6
1063 Decimal(2**64 + 2**32 - 1),
1064 # selection of values which fail with the old (before
1065 # version 2.6) long.__hash__
1066 Decimal("1.634E100"),
1067 Decimal("90.697E100"),
1068 Decimal("188.83E100"),
1069 Decimal("1652.9E100"),
1070 Decimal("56531E100"),
1071 ])
1072
1073 # check that hash(d) == hash(int(d)) for integral values
1074 for value in test_values:
1075 self.assertEqual(hash(value), hash(int(value)))
1076
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001077 #the same hash that to an int
1078 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001079 self.assertRaises(TypeError, hash, Decimal('NaN'))
1080 self.assert_(hash(Decimal('Inf')))
1081 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001082
Christian Heimes2380ac72008-01-09 00:17:24 +00001083 # check that the value of the hash doesn't depend on the
1084 # current context (issue #1757)
1085 c = getcontext()
1086 old_precision = c.prec
1087 x = Decimal("123456789.1")
1088
1089 c.prec = 6
1090 h1 = hash(x)
1091 c.prec = 10
1092 h2 = hash(x)
1093 c.prec = 16
1094 h3 = hash(x)
1095
1096 self.assertEqual(h1, h2)
1097 self.assertEqual(h1, h3)
1098 c.prec = old_precision
1099
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001100 def test_min_and_max_methods(self):
1101
1102 d1 = Decimal('15.32')
1103 d2 = Decimal('28.5')
1104 l1 = 15
1105 l2 = 28
1106
1107 #between Decimals
1108 self.failUnless(min(d1,d2) is d1)
1109 self.failUnless(min(d2,d1) is d1)
1110 self.failUnless(max(d1,d2) is d2)
1111 self.failUnless(max(d2,d1) is d2)
1112
1113 #between Decimal and long
1114 self.failUnless(min(d1,l2) is d1)
1115 self.failUnless(min(l2,d1) is d1)
1116 self.failUnless(max(l1,d2) is d2)
1117 self.failUnless(max(d2,l1) is d2)
1118
1119 def test_as_nonzero(self):
1120 #as false
1121 self.failIf(Decimal(0))
1122 #as true
1123 self.failUnless(Decimal('0.372'))
1124
1125 def test_tostring_methods(self):
1126 #Test str and repr methods.
1127
1128 d = Decimal('15.32')
1129 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001130 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001131
1132 def test_tonum_methods(self):
1133 #Test float, int and long methods.
1134
1135 d1 = Decimal('66')
1136 d2 = Decimal('15.32')
1137
1138 #int
1139 self.assertEqual(int(d1), 66)
1140 self.assertEqual(int(d2), 15)
1141
1142 #long
Guido van Rossume2a383d2007-01-15 16:59:06 +00001143 self.assertEqual(int(d1), 66)
1144 self.assertEqual(int(d2), 15)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001145
1146 #float
1147 self.assertEqual(float(d1), 66)
1148 self.assertEqual(float(d2), 15.32)
1149
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001150 #floor
1151 test_pairs = [
1152 ('123.00', 123),
1153 ('3.2', 3),
1154 ('3.54', 3),
1155 ('3.899', 3),
1156 ('-2.3', -3),
1157 ('-11.0', -11),
1158 ('0.0', 0),
1159 ('-0E3', 0),
1160 ]
1161 for d, i in test_pairs:
1162 self.assertEqual(math.floor(Decimal(d)), i)
1163 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1164 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1165 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1166 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1167 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1168
1169 #ceiling
1170 test_pairs = [
1171 ('123.00', 123),
1172 ('3.2', 4),
1173 ('3.54', 4),
1174 ('3.899', 4),
1175 ('-2.3', -2),
1176 ('-11.0', -11),
1177 ('0.0', 0),
1178 ('-0E3', 0),
1179 ]
1180 for d, i in test_pairs:
1181 self.assertEqual(math.ceil(Decimal(d)), i)
1182 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1183 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1184 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1185 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1186 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1187
1188 #round, single argument
1189 test_pairs = [
1190 ('123.00', 123),
1191 ('3.2', 3),
1192 ('3.54', 4),
1193 ('3.899', 4),
1194 ('-2.3', -2),
1195 ('-11.0', -11),
1196 ('0.0', 0),
1197 ('-0E3', 0),
1198 ('-3.5', -4),
1199 ('-2.5', -2),
1200 ('-1.5', -2),
1201 ('-0.5', 0),
1202 ('0.5', 0),
1203 ('1.5', 2),
1204 ('2.5', 2),
1205 ('3.5', 4),
1206 ]
1207 for d, i in test_pairs:
1208 self.assertEqual(round(Decimal(d)), i)
1209 self.assertRaises(ValueError, round, Decimal('-NaN'))
1210 self.assertRaises(ValueError, round, Decimal('sNaN'))
1211 self.assertRaises(ValueError, round, Decimal('NaN123'))
1212 self.assertRaises(OverflowError, round, Decimal('Inf'))
1213 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1214
1215 #round, two arguments; this is essentially equivalent
1216 #to quantize, which is already extensively tested
1217 test_triples = [
1218 ('123.456', -4, '0E+4'),
1219 ('123.456', -3, '0E+3'),
1220 ('123.456', -2, '1E+2'),
1221 ('123.456', -1, '1.2E+2'),
1222 ('123.456', 0, '123'),
1223 ('123.456', 1, '123.5'),
1224 ('123.456', 2, '123.46'),
1225 ('123.456', 3, '123.456'),
1226 ('123.456', 4, '123.4560'),
1227 ('123.455', 2, '123.46'),
1228 ('123.445', 2, '123.44'),
1229 ('Inf', 4, 'NaN'),
1230 ('-Inf', -23, 'NaN'),
1231 ('sNaN314', 3, 'NaN314'),
1232 ]
1233 for d, n, r in test_triples:
1234 self.assertEqual(str(round(Decimal(d), n)), r)
1235
1236
1237
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001238 def test_eval_round_trip(self):
1239
1240 #with zero
1241 d = Decimal( (0, (0,), 0) )
1242 self.assertEqual(d, eval(repr(d)))
1243
1244 #int
1245 d = Decimal( (1, (4, 5), 0) )
1246 self.assertEqual(d, eval(repr(d)))
1247
1248 #float
1249 d = Decimal( (0, (4, 5, 3, 4), -2) )
1250 self.assertEqual(d, eval(repr(d)))
1251
1252 #weird
1253 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1254 self.assertEqual(d, eval(repr(d)))
1255
1256 def test_as_tuple(self):
1257
1258 #with zero
1259 d = Decimal(0)
1260 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1261
1262 #int
1263 d = Decimal(-45)
1264 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1265
1266 #complicated string
1267 d = Decimal("-4.34913534E-17")
1268 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1269
1270 #inf
1271 d = Decimal("Infinity")
1272 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1273
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001274 #leading zeros in coefficient should be stripped
1275 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1276 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1277 d = Decimal( (1, (0, 0, 0), 37) )
1278 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1279 d = Decimal( (1, (), 37) )
1280 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1281
1282 #leading zeros in NaN diagnostic info should be stripped
1283 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1284 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1285 d = Decimal( (1, (0, 0, 0), 'N') )
1286 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1287 d = Decimal( (1, (), 'n') )
1288 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1289
1290 #coefficient in infinity should be ignored
1291 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1292 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1293 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1294 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1295
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001296 def test_immutability_operations(self):
1297 # Do operations and check that it didn't change change internal objects.
1298
1299 d1 = Decimal('-25e55')
1300 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001301 d2 = Decimal('33e+33')
1302 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001303
1304 def checkSameDec(operation, useOther=False):
1305 if useOther:
1306 eval("d1." + operation + "(d2)")
1307 self.assertEqual(d1._sign, b1._sign)
1308 self.assertEqual(d1._int, b1._int)
1309 self.assertEqual(d1._exp, b1._exp)
1310 self.assertEqual(d2._sign, b2._sign)
1311 self.assertEqual(d2._int, b2._int)
1312 self.assertEqual(d2._exp, b2._exp)
1313 else:
1314 eval("d1." + operation + "()")
1315 self.assertEqual(d1._sign, b1._sign)
1316 self.assertEqual(d1._int, b1._int)
1317 self.assertEqual(d1._exp, b1._exp)
1318 return
1319
1320 Decimal(d1)
1321 self.assertEqual(d1._sign, b1._sign)
1322 self.assertEqual(d1._int, b1._int)
1323 self.assertEqual(d1._exp, b1._exp)
1324
1325 checkSameDec("__abs__")
1326 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001327 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001328 checkSameDec("__eq__", True)
1329 checkSameDec("__ne__", True)
1330 checkSameDec("__le__", True)
1331 checkSameDec("__lt__", True)
1332 checkSameDec("__ge__", True)
1333 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001334 checkSameDec("__float__")
1335 checkSameDec("__floordiv__", True)
1336 checkSameDec("__hash__")
1337 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001338 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001339 checkSameDec("__mod__", True)
1340 checkSameDec("__mul__", True)
1341 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001342 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001343 checkSameDec("__pos__")
1344 checkSameDec("__pow__", True)
1345 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001346 checkSameDec("__rdivmod__", True)
1347 checkSameDec("__repr__")
1348 checkSameDec("__rfloordiv__", True)
1349 checkSameDec("__rmod__", True)
1350 checkSameDec("__rmul__", True)
1351 checkSameDec("__rpow__", True)
1352 checkSameDec("__rsub__", True)
1353 checkSameDec("__str__")
1354 checkSameDec("__sub__", True)
1355 checkSameDec("__truediv__", True)
1356 checkSameDec("adjusted")
1357 checkSameDec("as_tuple")
1358 checkSameDec("compare", True)
1359 checkSameDec("max", True)
1360 checkSameDec("min", True)
1361 checkSameDec("normalize")
1362 checkSameDec("quantize", True)
1363 checkSameDec("remainder_near", True)
1364 checkSameDec("same_quantum", True)
1365 checkSameDec("sqrt")
1366 checkSameDec("to_eng_string")
1367 checkSameDec("to_integral")
1368
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001369 def test_subclassing(self):
1370 # Different behaviours when subclassing Decimal
1371
1372 class MyDecimal(Decimal):
1373 pass
1374
1375 d1 = MyDecimal(1)
1376 d2 = MyDecimal(2)
1377 d = d1 + d2
1378 self.assertTrue(type(d) is Decimal)
1379
1380 d = d1.max(d2)
1381 self.assertTrue(type(d) is Decimal)
1382
Christian Heimes0348fb62008-03-26 12:55:56 +00001383 def test_implicit_context(self):
1384 # Check results when context given implicitly. (Issue 2478)
1385 c = getcontext()
1386 self.assertEqual(str(Decimal(0).sqrt()),
1387 str(c.sqrt(Decimal(0))))
1388
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001389
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001390class DecimalPythonAPItests(unittest.TestCase):
1391
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001392 def test_abc(self):
1393 self.assert_(issubclass(Decimal, numbers.Number))
1394 self.assert_(not issubclass(Decimal, numbers.Real))
1395 self.assert_(isinstance(Decimal(0), numbers.Number))
1396 self.assert_(not isinstance(Decimal(0), numbers.Real))
1397
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001398 def test_pickle(self):
1399 d = Decimal('-3.141590000')
1400 p = pickle.dumps(d)
1401 e = pickle.loads(p)
1402 self.assertEqual(d, e)
1403
Raymond Hettinger5548be22004-07-05 18:49:38 +00001404 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001405 for x in range(-250, 250):
1406 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001407 # should work the same as for floats
1408 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001409 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001410 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001411 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001412 self.assertEqual(Decimal(int(d)), r)
1413
Christian Heimes969fe572008-01-25 11:23:10 +00001414 def test_trunc(self):
1415 for x in range(-250, 250):
1416 s = '%0.2f' % (x / 100.0)
1417 # should work the same as for floats
1418 self.assertEqual(int(Decimal(s)), int(float(s)))
1419 # should work the same as to_integral in the ROUND_DOWN mode
1420 d = Decimal(s)
1421 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001422 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001423
Raymond Hettinger771ed762009-01-03 19:20:32 +00001424 def test_from_float(self):
1425
1426 class MyDecimal(Decimal):
1427 pass
1428
1429 r = MyDecimal.from_float(0.1)
1430 self.assertEqual(type(r), MyDecimal)
1431 self.assertEqual(str(r),
1432 '0.1000000000000000055511151231257827021181583404541015625')
1433 bigint = 12345678901234567890123456789
1434 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
1435 self.assert_(MyDecimal.from_float(float('nan')).is_qnan())
1436 self.assert_(MyDecimal.from_float(float('inf')).is_infinite())
1437 self.assert_(MyDecimal.from_float(float('-inf')).is_infinite())
1438 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1439 str(Decimal('NaN')))
1440 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1441 str(Decimal('Infinity')))
1442 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1443 str(Decimal('-Infinity')))
1444 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1445 for i in range(200):
1446 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1447 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1448
1449 def test_create_decimal_from_float(self):
1450 context = Context(prec=5, rounding=ROUND_DOWN)
1451 self.assertEqual(
1452 context.create_decimal_from_float(math.pi),
1453 Decimal('3.1415')
1454 )
1455 context = Context(prec=5, rounding=ROUND_UP)
1456 self.assertEqual(
1457 context.create_decimal_from_float(math.pi),
1458 Decimal('3.1416')
1459 )
1460 context = Context(prec=5, traps=[Inexact])
1461 self.assertRaises(
1462 Inexact,
1463 context.create_decimal_from_float,
1464 math.pi
1465 )
1466 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1467 "Decimal('-0')")
1468 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1469 "Decimal('1')")
1470 self.assertEqual(repr(context.create_decimal_from_float(10)),
1471 "Decimal('10')")
1472
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001473class ContextAPItests(unittest.TestCase):
1474
1475 def test_pickle(self):
1476 c = Context()
1477 e = pickle.loads(pickle.dumps(c))
1478 for k in vars(c):
1479 v1 = vars(c)[k]
1480 v2 = vars(e)[k]
1481 self.assertEqual(v1, v2)
1482
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001483 def test_equality_with_other_types(self):
1484 self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1485 self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1486
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001487 def test_copy(self):
1488 # All copies should be deep
1489 c = Context()
1490 d = c.copy()
1491 self.assertNotEqual(id(c), id(d))
1492 self.assertNotEqual(id(c.flags), id(d.flags))
1493 self.assertNotEqual(id(c.traps), id(d.traps))
1494
Thomas Wouters89f507f2006-12-13 04:49:30 +00001495class WithStatementTest(unittest.TestCase):
1496 # Can't do these as docstrings until Python 2.6
1497 # as doctest can't handle __future__ statements
1498
1499 def test_localcontext(self):
1500 # Use a copy of the current context in the block
1501 orig_ctx = getcontext()
1502 with localcontext() as enter_ctx:
1503 set_ctx = getcontext()
1504 final_ctx = getcontext()
1505 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1506 self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
1507 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1508
1509 def test_localcontextarg(self):
1510 # Use a copy of the supplied context in the block
1511 orig_ctx = getcontext()
1512 new_ctx = Context(prec=42)
1513 with localcontext(new_ctx) as enter_ctx:
1514 set_ctx = getcontext()
1515 final_ctx = getcontext()
1516 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1517 self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1518 self.assert_(new_ctx is not set_ctx, 'did not copy the context')
1519 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1520
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001521class ContextFlags(unittest.TestCase):
1522 def test_flags_irrelevant(self):
1523 # check that the result (numeric result + flags raised) of an
1524 # arithmetic operation doesn't depend on the current flags
1525
1526 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1527 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1528
1529 # operations that raise various flags, in the form (function, arglist)
1530 operations = [
1531 (context._apply, [Decimal("100E-1000000009")]),
1532 (context.sqrt, [Decimal(2)]),
1533 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1534 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1535 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1536 ]
1537
1538 # try various flags individually, then a whole lot at once
1539 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1540 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1541
1542 for fn, args in operations:
1543 # find answer and flags raised using a clean context
1544 context.clear_flags()
1545 ans = fn(*args)
1546 flags = [k for k, v in context.flags.items() if v]
1547
1548 for extra_flags in flagsets:
1549 # set flags, before calling operation
1550 context.clear_flags()
1551 for flag in extra_flags:
1552 context._raise_error(flag)
1553 new_ans = fn(*args)
1554
1555 # flags that we expect to be set after the operation
1556 expected_flags = list(flags)
1557 for flag in extra_flags:
1558 if flag not in expected_flags:
1559 expected_flags.append(flag)
1560 expected_flags.sort(key=id)
1561
1562 # flags we actually got
1563 new_flags = [k for k,v in context.flags.items() if v]
1564 new_flags.sort(key=id)
1565
1566 self.assertEqual(ans, new_ans,
1567 "operation produces different answers depending on flags set: " +
1568 "expected %s, got %s." % (ans, new_ans))
1569 self.assertEqual(new_flags, expected_flags,
1570 "operation raises different flags depending on flags set: " +
1571 "expected %s, got %s" % (expected_flags, new_flags))
1572
1573def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001574 """ Execute the tests.
1575
Raymond Hettingered20ad82004-09-04 20:09:13 +00001576 Runs all arithmetic tests if arith is True or if the "decimal" resource
1577 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001578 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001579
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001580 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001581 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001582 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001583 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001584
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001585 if todo_tests is None:
1586 test_classes = [
1587 DecimalExplicitConstructionTest,
1588 DecimalImplicitConstructionTest,
1589 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00001590 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001591 DecimalUseOfContextTest,
1592 DecimalUsabilityTest,
1593 DecimalPythonAPItests,
1594 ContextAPItests,
1595 DecimalTest,
1596 WithStatementTest,
1597 ContextFlags
1598 ]
1599 else:
1600 test_classes = [DecimalTest]
1601
1602 # Dynamically build custom test definition for each file in the test
1603 # directory and add the definitions to the DecimalTest class. This
1604 # procedure insures that new files do not get skipped.
1605 for filename in os.listdir(directory):
1606 if '.decTest' not in filename or filename.startswith("."):
1607 continue
1608 head, tail = filename.split('.')
1609 if todo_tests is not None and head not in todo_tests:
1610 continue
1611 tester = lambda self, f=filename: self.eval_file(directory + f)
1612 setattr(DecimalTest, 'test_' + head, tester)
1613 del filename, head, tail, tester
1614
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001615
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001616 try:
1617 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001618 if todo_tests is None:
1619 import decimal as DecimalModule
1620 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001621 finally:
1622 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001623
1624if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001625 import optparse
1626 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1627 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1628 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1629 (opt, args) = p.parse_args()
1630
1631 if opt.skip:
1632 test_main(arith=False, verbose=True)
1633 elif args:
1634 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001635 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636 test_main(arith=True, verbose=True)