blob: eaf9f0bf0c4fa742111700d8cd737faa6603016a [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'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000696
697 # check alignment
698 ('<6', '123', '123 '),
699 ('>6', '123', ' 123'),
700 ('^6', '123', ' 123 '),
701 ('=+6', '123', '+ 123'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000702 ]
703 for fmt, d, result in test_values:
704 self.assertEqual(format(Decimal(d), fmt), result)
705
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000706class DecimalArithmeticOperatorsTest(unittest.TestCase):
707 '''Unit tests for all arithmetic operators, binary and unary.'''
708
709 def test_addition(self):
710
711 d1 = Decimal('-11.1')
712 d2 = Decimal('22.2')
713
714 #two Decimals
715 self.assertEqual(d1+d2, Decimal('11.1'))
716 self.assertEqual(d2+d1, Decimal('11.1'))
717
718 #with other type, left
719 c = d1 + 5
720 self.assertEqual(c, Decimal('-6.1'))
721 self.assertEqual(type(c), type(d1))
722
723 #with other type, right
724 c = 5 + d1
725 self.assertEqual(c, Decimal('-6.1'))
726 self.assertEqual(type(c), type(d1))
727
728 #inline with decimal
729 d1 += d2
730 self.assertEqual(d1, Decimal('11.1'))
731
732 #inline with other type
733 d1 += 5
734 self.assertEqual(d1, Decimal('16.1'))
735
736 def test_subtraction(self):
737
738 d1 = Decimal('-11.1')
739 d2 = Decimal('22.2')
740
741 #two Decimals
742 self.assertEqual(d1-d2, Decimal('-33.3'))
743 self.assertEqual(d2-d1, Decimal('33.3'))
744
745 #with other type, left
746 c = d1 - 5
747 self.assertEqual(c, Decimal('-16.1'))
748 self.assertEqual(type(c), type(d1))
749
750 #with other type, right
751 c = 5 - d1
752 self.assertEqual(c, Decimal('16.1'))
753 self.assertEqual(type(c), type(d1))
754
755 #inline with decimal
756 d1 -= d2
757 self.assertEqual(d1, Decimal('-33.3'))
758
759 #inline with other type
760 d1 -= 5
761 self.assertEqual(d1, Decimal('-38.3'))
762
763 def test_multiplication(self):
764
765 d1 = Decimal('-5')
766 d2 = Decimal('3')
767
768 #two Decimals
769 self.assertEqual(d1*d2, Decimal('-15'))
770 self.assertEqual(d2*d1, Decimal('-15'))
771
772 #with other type, left
773 c = d1 * 5
774 self.assertEqual(c, Decimal('-25'))
775 self.assertEqual(type(c), type(d1))
776
777 #with other type, right
778 c = 5 * d1
779 self.assertEqual(c, Decimal('-25'))
780 self.assertEqual(type(c), type(d1))
781
782 #inline with decimal
783 d1 *= d2
784 self.assertEqual(d1, Decimal('-15'))
785
786 #inline with other type
787 d1 *= 5
788 self.assertEqual(d1, Decimal('-75'))
789
790 def test_division(self):
791
792 d1 = Decimal('-5')
793 d2 = Decimal('2')
794
795 #two Decimals
796 self.assertEqual(d1/d2, Decimal('-2.5'))
797 self.assertEqual(d2/d1, Decimal('-0.4'))
798
799 #with other type, left
800 c = d1 / 4
801 self.assertEqual(c, Decimal('-1.25'))
802 self.assertEqual(type(c), type(d1))
803
804 #with other type, right
805 c = 4 / d1
806 self.assertEqual(c, Decimal('-0.8'))
807 self.assertEqual(type(c), type(d1))
808
809 #inline with decimal
810 d1 /= d2
811 self.assertEqual(d1, Decimal('-2.5'))
812
813 #inline with other type
814 d1 /= 4
815 self.assertEqual(d1, Decimal('-0.625'))
816
817 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000818
819 d1 = Decimal('5')
820 d2 = Decimal('2')
821
822 #two Decimals
823 self.assertEqual(d1//d2, Decimal('2'))
824 self.assertEqual(d2//d1, Decimal('0'))
825
826 #with other type, left
827 c = d1 // 4
828 self.assertEqual(c, Decimal('1'))
829 self.assertEqual(type(c), type(d1))
830
831 #with other type, right
832 c = 7 // d1
833 self.assertEqual(c, Decimal('1'))
834 self.assertEqual(type(c), type(d1))
835
836 #inline with decimal
837 d1 //= d2
838 self.assertEqual(d1, Decimal('2'))
839
840 #inline with other type
841 d1 //= 2
842 self.assertEqual(d1, Decimal('1'))
843
844 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000845
846 d1 = Decimal('5')
847 d2 = Decimal('2')
848
849 #two Decimals
850 self.assertEqual(d1**d2, Decimal('25'))
851 self.assertEqual(d2**d1, Decimal('32'))
852
853 #with other type, left
854 c = d1 ** 4
855 self.assertEqual(c, Decimal('625'))
856 self.assertEqual(type(c), type(d1))
857
858 #with other type, right
859 c = 7 ** d1
860 self.assertEqual(c, Decimal('16807'))
861 self.assertEqual(type(c), type(d1))
862
863 #inline with decimal
864 d1 **= d2
865 self.assertEqual(d1, Decimal('25'))
866
867 #inline with other type
868 d1 **= 4
869 self.assertEqual(d1, Decimal('390625'))
870
871 def test_module(self):
872
873 d1 = Decimal('5')
874 d2 = Decimal('2')
875
876 #two Decimals
877 self.assertEqual(d1%d2, Decimal('1'))
878 self.assertEqual(d2%d1, Decimal('2'))
879
880 #with other type, left
881 c = d1 % 4
882 self.assertEqual(c, Decimal('1'))
883 self.assertEqual(type(c), type(d1))
884
885 #with other type, right
886 c = 7 % d1
887 self.assertEqual(c, Decimal('2'))
888 self.assertEqual(type(c), type(d1))
889
890 #inline with decimal
891 d1 %= d2
892 self.assertEqual(d1, Decimal('1'))
893
894 #inline with other type
895 d1 %= 4
896 self.assertEqual(d1, Decimal('1'))
897
898 def test_floor_div_module(self):
899
900 d1 = Decimal('5')
901 d2 = Decimal('2')
902
903 #two Decimals
904 (p, q) = divmod(d1, d2)
905 self.assertEqual(p, Decimal('2'))
906 self.assertEqual(q, Decimal('1'))
907 self.assertEqual(type(p), type(d1))
908 self.assertEqual(type(q), type(d1))
909
910 #with other type, left
911 (p, q) = divmod(d1, 4)
912 self.assertEqual(p, Decimal('1'))
913 self.assertEqual(q, Decimal('1'))
914 self.assertEqual(type(p), type(d1))
915 self.assertEqual(type(q), type(d1))
916
917 #with other type, right
918 (p, q) = divmod(7, d1)
919 self.assertEqual(p, Decimal('1'))
920 self.assertEqual(q, Decimal('2'))
921 self.assertEqual(type(p), type(d1))
922 self.assertEqual(type(q), type(d1))
923
924 def test_unary_operators(self):
925 self.assertEqual(+Decimal(45), Decimal(+45)) # +
926 self.assertEqual(-Decimal(45), Decimal(-45)) # -
927 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
928
Christian Heimes77c02eb2008-02-09 02:18:51 +0000929 def test_nan_comparisons(self):
930 n = Decimal('NaN')
931 s = Decimal('sNaN')
932 i = Decimal('Inf')
933 f = Decimal('2')
934 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
935 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
936 self.assert_(x != y)
937 self.assert_(not (x == y))
938 self.assert_(not (x < y))
939 self.assert_(not (x <= y))
940 self.assert_(not (x > y))
941 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000942
943# The following are two functions used to test threading in the next class
944
945def thfunc1(cls):
946 d1 = Decimal(1)
947 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +0000948 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000949 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000950 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000951 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000952
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000953 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
954 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000955 return
956
957def thfunc2(cls):
958 d1 = Decimal(1)
959 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +0000960 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000961 thiscontext = getcontext()
962 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +0000963 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000964 cls.synchro.set()
965 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +0000966
Christian Heimes81ee3ef2008-05-04 22:42:01 +0000967 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +0000968 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000969 return
970
971
972class DecimalUseOfContextTest(unittest.TestCase):
973 '''Unit tests for Use of Context cases in Decimal.'''
974
Raymond Hettinger7e71fa52004-12-18 19:07:19 +0000975 try:
976 import threading
977 except ImportError:
978 threading = None
979
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000980 # Take care executing this test from IDLE, there's an issue in threading
981 # that hangs IDLE and I couldn't find it
982
983 def test_threading(self):
984 #Test the "threading isolation" of a Context.
985
986 self.synchro = threading.Event()
987 self.finish1 = threading.Event()
988 self.finish2 = threading.Event()
989
990 th1 = threading.Thread(target=thfunc1, args=(self,))
991 th2 = threading.Thread(target=thfunc2, args=(self,))
992
993 th1.start()
994 th2.start()
995
996 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000997 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000998 return
999
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001000 if threading is None:
1001 del test_threading
1002
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001003
1004class DecimalUsabilityTest(unittest.TestCase):
1005 '''Unit tests for Usability cases of Decimal.'''
1006
1007 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001008
1009 da = Decimal('23.42')
1010 db = Decimal('23.42')
1011 dc = Decimal('45')
1012
1013 #two Decimals
1014 self.failUnless(dc > da)
1015 self.failUnless(dc >= da)
1016 self.failUnless(da < dc)
1017 self.failUnless(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001018 self.assertEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001019 self.failUnless(da != dc)
1020 self.failUnless(da <= db)
1021 self.failUnless(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001022
1023 #a Decimal and an int
1024 self.failUnless(dc > 23)
1025 self.failUnless(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001026 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001027
1028 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001029 self.assertNotEqual(da, 'ugly')
1030 self.assertNotEqual(da, 32.7)
1031 self.assertNotEqual(da, object())
1032 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001033
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001034 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001035 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001036 b = a[:]
1037 random.shuffle(a)
1038 a.sort()
1039 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001040
1041 def test_copy_and_deepcopy_methods(self):
1042 d = Decimal('43.24')
1043 c = copy.copy(d)
1044 self.assertEqual(id(c), id(d))
1045 dc = copy.deepcopy(d)
1046 self.assertEqual(id(dc), id(d))
1047
1048 def test_hash_method(self):
1049 #just that it's hashable
1050 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001051
1052 test_values = [Decimal(sign*(2**m + n))
1053 for m in [0, 14, 15, 16, 17, 30, 31,
1054 32, 33, 62, 63, 64, 65, 66]
1055 for n in range(-10, 10)
1056 for sign in [-1, 1]]
1057 test_values.extend([
1058 Decimal("-0"), # zeros
1059 Decimal("0.00"),
1060 Decimal("-0.000"),
1061 Decimal("0E10"),
1062 Decimal("-0E12"),
1063 Decimal("10.0"), # negative exponent
1064 Decimal("-23.00000"),
1065 Decimal("1230E100"), # positive exponent
1066 Decimal("-4.5678E50"),
1067 # a value for which hash(n) != hash(n % (2**64-1))
1068 # in Python pre-2.6
1069 Decimal(2**64 + 2**32 - 1),
1070 # selection of values which fail with the old (before
1071 # version 2.6) long.__hash__
1072 Decimal("1.634E100"),
1073 Decimal("90.697E100"),
1074 Decimal("188.83E100"),
1075 Decimal("1652.9E100"),
1076 Decimal("56531E100"),
1077 ])
1078
1079 # check that hash(d) == hash(int(d)) for integral values
1080 for value in test_values:
1081 self.assertEqual(hash(value), hash(int(value)))
1082
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001083 #the same hash that to an int
1084 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001085 self.assertRaises(TypeError, hash, Decimal('NaN'))
1086 self.assert_(hash(Decimal('Inf')))
1087 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001088
Christian Heimes2380ac72008-01-09 00:17:24 +00001089 # check that the value of the hash doesn't depend on the
1090 # current context (issue #1757)
1091 c = getcontext()
1092 old_precision = c.prec
1093 x = Decimal("123456789.1")
1094
1095 c.prec = 6
1096 h1 = hash(x)
1097 c.prec = 10
1098 h2 = hash(x)
1099 c.prec = 16
1100 h3 = hash(x)
1101
1102 self.assertEqual(h1, h2)
1103 self.assertEqual(h1, h3)
1104 c.prec = old_precision
1105
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001106 def test_min_and_max_methods(self):
1107
1108 d1 = Decimal('15.32')
1109 d2 = Decimal('28.5')
1110 l1 = 15
1111 l2 = 28
1112
1113 #between Decimals
1114 self.failUnless(min(d1,d2) is d1)
1115 self.failUnless(min(d2,d1) is d1)
1116 self.failUnless(max(d1,d2) is d2)
1117 self.failUnless(max(d2,d1) is d2)
1118
1119 #between Decimal and long
1120 self.failUnless(min(d1,l2) is d1)
1121 self.failUnless(min(l2,d1) is d1)
1122 self.failUnless(max(l1,d2) is d2)
1123 self.failUnless(max(d2,l1) is d2)
1124
1125 def test_as_nonzero(self):
1126 #as false
1127 self.failIf(Decimal(0))
1128 #as true
1129 self.failUnless(Decimal('0.372'))
1130
1131 def test_tostring_methods(self):
1132 #Test str and repr methods.
1133
1134 d = Decimal('15.32')
1135 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001136 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001137
1138 def test_tonum_methods(self):
1139 #Test float, int and long methods.
1140
1141 d1 = Decimal('66')
1142 d2 = Decimal('15.32')
1143
1144 #int
1145 self.assertEqual(int(d1), 66)
1146 self.assertEqual(int(d2), 15)
1147
1148 #long
Guido van Rossume2a383d2007-01-15 16:59:06 +00001149 self.assertEqual(int(d1), 66)
1150 self.assertEqual(int(d2), 15)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001151
1152 #float
1153 self.assertEqual(float(d1), 66)
1154 self.assertEqual(float(d2), 15.32)
1155
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001156 #floor
1157 test_pairs = [
1158 ('123.00', 123),
1159 ('3.2', 3),
1160 ('3.54', 3),
1161 ('3.899', 3),
1162 ('-2.3', -3),
1163 ('-11.0', -11),
1164 ('0.0', 0),
1165 ('-0E3', 0),
1166 ]
1167 for d, i in test_pairs:
1168 self.assertEqual(math.floor(Decimal(d)), i)
1169 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1170 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1171 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1172 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1173 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1174
1175 #ceiling
1176 test_pairs = [
1177 ('123.00', 123),
1178 ('3.2', 4),
1179 ('3.54', 4),
1180 ('3.899', 4),
1181 ('-2.3', -2),
1182 ('-11.0', -11),
1183 ('0.0', 0),
1184 ('-0E3', 0),
1185 ]
1186 for d, i in test_pairs:
1187 self.assertEqual(math.ceil(Decimal(d)), i)
1188 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1189 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1190 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1191 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1192 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1193
1194 #round, single argument
1195 test_pairs = [
1196 ('123.00', 123),
1197 ('3.2', 3),
1198 ('3.54', 4),
1199 ('3.899', 4),
1200 ('-2.3', -2),
1201 ('-11.0', -11),
1202 ('0.0', 0),
1203 ('-0E3', 0),
1204 ('-3.5', -4),
1205 ('-2.5', -2),
1206 ('-1.5', -2),
1207 ('-0.5', 0),
1208 ('0.5', 0),
1209 ('1.5', 2),
1210 ('2.5', 2),
1211 ('3.5', 4),
1212 ]
1213 for d, i in test_pairs:
1214 self.assertEqual(round(Decimal(d)), i)
1215 self.assertRaises(ValueError, round, Decimal('-NaN'))
1216 self.assertRaises(ValueError, round, Decimal('sNaN'))
1217 self.assertRaises(ValueError, round, Decimal('NaN123'))
1218 self.assertRaises(OverflowError, round, Decimal('Inf'))
1219 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1220
1221 #round, two arguments; this is essentially equivalent
1222 #to quantize, which is already extensively tested
1223 test_triples = [
1224 ('123.456', -4, '0E+4'),
1225 ('123.456', -3, '0E+3'),
1226 ('123.456', -2, '1E+2'),
1227 ('123.456', -1, '1.2E+2'),
1228 ('123.456', 0, '123'),
1229 ('123.456', 1, '123.5'),
1230 ('123.456', 2, '123.46'),
1231 ('123.456', 3, '123.456'),
1232 ('123.456', 4, '123.4560'),
1233 ('123.455', 2, '123.46'),
1234 ('123.445', 2, '123.44'),
1235 ('Inf', 4, 'NaN'),
1236 ('-Inf', -23, 'NaN'),
1237 ('sNaN314', 3, 'NaN314'),
1238 ]
1239 for d, n, r in test_triples:
1240 self.assertEqual(str(round(Decimal(d), n)), r)
1241
1242
1243
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244 def test_eval_round_trip(self):
1245
1246 #with zero
1247 d = Decimal( (0, (0,), 0) )
1248 self.assertEqual(d, eval(repr(d)))
1249
1250 #int
1251 d = Decimal( (1, (4, 5), 0) )
1252 self.assertEqual(d, eval(repr(d)))
1253
1254 #float
1255 d = Decimal( (0, (4, 5, 3, 4), -2) )
1256 self.assertEqual(d, eval(repr(d)))
1257
1258 #weird
1259 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1260 self.assertEqual(d, eval(repr(d)))
1261
1262 def test_as_tuple(self):
1263
1264 #with zero
1265 d = Decimal(0)
1266 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1267
1268 #int
1269 d = Decimal(-45)
1270 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1271
1272 #complicated string
1273 d = Decimal("-4.34913534E-17")
1274 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1275
1276 #inf
1277 d = Decimal("Infinity")
1278 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1279
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001280 #leading zeros in coefficient should be stripped
1281 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1282 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1283 d = Decimal( (1, (0, 0, 0), 37) )
1284 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1285 d = Decimal( (1, (), 37) )
1286 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1287
1288 #leading zeros in NaN diagnostic info should be stripped
1289 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1290 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1291 d = Decimal( (1, (0, 0, 0), 'N') )
1292 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1293 d = Decimal( (1, (), 'n') )
1294 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1295
1296 #coefficient in infinity should be ignored
1297 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1298 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1299 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1300 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1301
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001302 def test_immutability_operations(self):
1303 # Do operations and check that it didn't change change internal objects.
1304
1305 d1 = Decimal('-25e55')
1306 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001307 d2 = Decimal('33e+33')
1308 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001309
1310 def checkSameDec(operation, useOther=False):
1311 if useOther:
1312 eval("d1." + operation + "(d2)")
1313 self.assertEqual(d1._sign, b1._sign)
1314 self.assertEqual(d1._int, b1._int)
1315 self.assertEqual(d1._exp, b1._exp)
1316 self.assertEqual(d2._sign, b2._sign)
1317 self.assertEqual(d2._int, b2._int)
1318 self.assertEqual(d2._exp, b2._exp)
1319 else:
1320 eval("d1." + operation + "()")
1321 self.assertEqual(d1._sign, b1._sign)
1322 self.assertEqual(d1._int, b1._int)
1323 self.assertEqual(d1._exp, b1._exp)
1324 return
1325
1326 Decimal(d1)
1327 self.assertEqual(d1._sign, b1._sign)
1328 self.assertEqual(d1._int, b1._int)
1329 self.assertEqual(d1._exp, b1._exp)
1330
1331 checkSameDec("__abs__")
1332 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001333 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001334 checkSameDec("__eq__", True)
1335 checkSameDec("__ne__", True)
1336 checkSameDec("__le__", True)
1337 checkSameDec("__lt__", True)
1338 checkSameDec("__ge__", True)
1339 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001340 checkSameDec("__float__")
1341 checkSameDec("__floordiv__", True)
1342 checkSameDec("__hash__")
1343 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001344 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001345 checkSameDec("__mod__", True)
1346 checkSameDec("__mul__", True)
1347 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001348 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001349 checkSameDec("__pos__")
1350 checkSameDec("__pow__", True)
1351 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001352 checkSameDec("__rdivmod__", True)
1353 checkSameDec("__repr__")
1354 checkSameDec("__rfloordiv__", True)
1355 checkSameDec("__rmod__", True)
1356 checkSameDec("__rmul__", True)
1357 checkSameDec("__rpow__", True)
1358 checkSameDec("__rsub__", True)
1359 checkSameDec("__str__")
1360 checkSameDec("__sub__", True)
1361 checkSameDec("__truediv__", True)
1362 checkSameDec("adjusted")
1363 checkSameDec("as_tuple")
1364 checkSameDec("compare", True)
1365 checkSameDec("max", True)
1366 checkSameDec("min", True)
1367 checkSameDec("normalize")
1368 checkSameDec("quantize", True)
1369 checkSameDec("remainder_near", True)
1370 checkSameDec("same_quantum", True)
1371 checkSameDec("sqrt")
1372 checkSameDec("to_eng_string")
1373 checkSameDec("to_integral")
1374
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001375 def test_subclassing(self):
1376 # Different behaviours when subclassing Decimal
1377
1378 class MyDecimal(Decimal):
1379 pass
1380
1381 d1 = MyDecimal(1)
1382 d2 = MyDecimal(2)
1383 d = d1 + d2
1384 self.assertTrue(type(d) is Decimal)
1385
1386 d = d1.max(d2)
1387 self.assertTrue(type(d) is Decimal)
1388
Christian Heimes0348fb62008-03-26 12:55:56 +00001389 def test_implicit_context(self):
1390 # Check results when context given implicitly. (Issue 2478)
1391 c = getcontext()
1392 self.assertEqual(str(Decimal(0).sqrt()),
1393 str(c.sqrt(Decimal(0))))
1394
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396class DecimalPythonAPItests(unittest.TestCase):
1397
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001398 def test_abc(self):
1399 self.assert_(issubclass(Decimal, numbers.Number))
1400 self.assert_(not issubclass(Decimal, numbers.Real))
1401 self.assert_(isinstance(Decimal(0), numbers.Number))
1402 self.assert_(not isinstance(Decimal(0), numbers.Real))
1403
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001404 def test_pickle(self):
1405 d = Decimal('-3.141590000')
1406 p = pickle.dumps(d)
1407 e = pickle.loads(p)
1408 self.assertEqual(d, e)
1409
Raymond Hettinger5548be22004-07-05 18:49:38 +00001410 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001411 for x in range(-250, 250):
1412 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001413 # should work the same as for floats
1414 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001415 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001416 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001417 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001418 self.assertEqual(Decimal(int(d)), r)
1419
Christian Heimes969fe572008-01-25 11:23:10 +00001420 def test_trunc(self):
1421 for x in range(-250, 250):
1422 s = '%0.2f' % (x / 100.0)
1423 # should work the same as for floats
1424 self.assertEqual(int(Decimal(s)), int(float(s)))
1425 # should work the same as to_integral in the ROUND_DOWN mode
1426 d = Decimal(s)
1427 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001428 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001429
Raymond Hettinger771ed762009-01-03 19:20:32 +00001430 def test_from_float(self):
1431
1432 class MyDecimal(Decimal):
1433 pass
1434
1435 r = MyDecimal.from_float(0.1)
1436 self.assertEqual(type(r), MyDecimal)
1437 self.assertEqual(str(r),
1438 '0.1000000000000000055511151231257827021181583404541015625')
1439 bigint = 12345678901234567890123456789
1440 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
1441 self.assert_(MyDecimal.from_float(float('nan')).is_qnan())
1442 self.assert_(MyDecimal.from_float(float('inf')).is_infinite())
1443 self.assert_(MyDecimal.from_float(float('-inf')).is_infinite())
1444 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1445 str(Decimal('NaN')))
1446 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1447 str(Decimal('Infinity')))
1448 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1449 str(Decimal('-Infinity')))
1450 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1451 for i in range(200):
1452 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1453 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1454
1455 def test_create_decimal_from_float(self):
1456 context = Context(prec=5, rounding=ROUND_DOWN)
1457 self.assertEqual(
1458 context.create_decimal_from_float(math.pi),
1459 Decimal('3.1415')
1460 )
1461 context = Context(prec=5, rounding=ROUND_UP)
1462 self.assertEqual(
1463 context.create_decimal_from_float(math.pi),
1464 Decimal('3.1416')
1465 )
1466 context = Context(prec=5, traps=[Inexact])
1467 self.assertRaises(
1468 Inexact,
1469 context.create_decimal_from_float,
1470 math.pi
1471 )
1472 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1473 "Decimal('-0')")
1474 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1475 "Decimal('1')")
1476 self.assertEqual(repr(context.create_decimal_from_float(10)),
1477 "Decimal('10')")
1478
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001479class ContextAPItests(unittest.TestCase):
1480
1481 def test_pickle(self):
1482 c = Context()
1483 e = pickle.loads(pickle.dumps(c))
1484 for k in vars(c):
1485 v1 = vars(c)[k]
1486 v2 = vars(e)[k]
1487 self.assertEqual(v1, v2)
1488
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001489 def test_equality_with_other_types(self):
1490 self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1491 self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1492
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001493 def test_copy(self):
1494 # All copies should be deep
1495 c = Context()
1496 d = c.copy()
1497 self.assertNotEqual(id(c), id(d))
1498 self.assertNotEqual(id(c.flags), id(d.flags))
1499 self.assertNotEqual(id(c.traps), id(d.traps))
1500
Thomas Wouters89f507f2006-12-13 04:49:30 +00001501class WithStatementTest(unittest.TestCase):
1502 # Can't do these as docstrings until Python 2.6
1503 # as doctest can't handle __future__ statements
1504
1505 def test_localcontext(self):
1506 # Use a copy of the current context in the block
1507 orig_ctx = getcontext()
1508 with localcontext() as enter_ctx:
1509 set_ctx = getcontext()
1510 final_ctx = getcontext()
1511 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1512 self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
1513 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1514
1515 def test_localcontextarg(self):
1516 # Use a copy of the supplied context in the block
1517 orig_ctx = getcontext()
1518 new_ctx = Context(prec=42)
1519 with localcontext(new_ctx) as enter_ctx:
1520 set_ctx = getcontext()
1521 final_ctx = getcontext()
1522 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1523 self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1524 self.assert_(new_ctx is not set_ctx, 'did not copy the context')
1525 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1526
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001527class ContextFlags(unittest.TestCase):
1528 def test_flags_irrelevant(self):
1529 # check that the result (numeric result + flags raised) of an
1530 # arithmetic operation doesn't depend on the current flags
1531
1532 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1533 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1534
1535 # operations that raise various flags, in the form (function, arglist)
1536 operations = [
1537 (context._apply, [Decimal("100E-1000000009")]),
1538 (context.sqrt, [Decimal(2)]),
1539 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1540 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1541 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1542 ]
1543
1544 # try various flags individually, then a whole lot at once
1545 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1546 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1547
1548 for fn, args in operations:
1549 # find answer and flags raised using a clean context
1550 context.clear_flags()
1551 ans = fn(*args)
1552 flags = [k for k, v in context.flags.items() if v]
1553
1554 for extra_flags in flagsets:
1555 # set flags, before calling operation
1556 context.clear_flags()
1557 for flag in extra_flags:
1558 context._raise_error(flag)
1559 new_ans = fn(*args)
1560
1561 # flags that we expect to be set after the operation
1562 expected_flags = list(flags)
1563 for flag in extra_flags:
1564 if flag not in expected_flags:
1565 expected_flags.append(flag)
1566 expected_flags.sort(key=id)
1567
1568 # flags we actually got
1569 new_flags = [k for k,v in context.flags.items() if v]
1570 new_flags.sort(key=id)
1571
1572 self.assertEqual(ans, new_ans,
1573 "operation produces different answers depending on flags set: " +
1574 "expected %s, got %s." % (ans, new_ans))
1575 self.assertEqual(new_flags, expected_flags,
1576 "operation raises different flags depending on flags set: " +
1577 "expected %s, got %s" % (expected_flags, new_flags))
1578
1579def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001580 """ Execute the tests.
1581
Raymond Hettingered20ad82004-09-04 20:09:13 +00001582 Runs all arithmetic tests if arith is True or if the "decimal" resource
1583 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001585
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001586 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001587 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001588 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001589 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001590
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001591 if todo_tests is None:
1592 test_classes = [
1593 DecimalExplicitConstructionTest,
1594 DecimalImplicitConstructionTest,
1595 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00001596 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001597 DecimalUseOfContextTest,
1598 DecimalUsabilityTest,
1599 DecimalPythonAPItests,
1600 ContextAPItests,
1601 DecimalTest,
1602 WithStatementTest,
1603 ContextFlags
1604 ]
1605 else:
1606 test_classes = [DecimalTest]
1607
1608 # Dynamically build custom test definition for each file in the test
1609 # directory and add the definitions to the DecimalTest class. This
1610 # procedure insures that new files do not get skipped.
1611 for filename in os.listdir(directory):
1612 if '.decTest' not in filename or filename.startswith("."):
1613 continue
1614 head, tail = filename.split('.')
1615 if todo_tests is not None and head not in todo_tests:
1616 continue
1617 tester = lambda self, f=filename: self.eval_file(directory + f)
1618 setattr(DecimalTest, 'test_' + head, tester)
1619 del filename, head, tail, tester
1620
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001621
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001622 try:
1623 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001624 if todo_tests is None:
1625 import decimal as DecimalModule
1626 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001627 finally:
1628 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001629
1630if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001631 import optparse
1632 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1633 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1634 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1635 (opt, args) = p.parse_args()
1636
1637 if opt.skip:
1638 test_main(arith=False, verbose=True)
1639 elif args:
1640 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001641 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001642 test_main(arith=True, verbose=True)