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