blob: cc15c330fe8701171224edaa195d409ace00b3b6 [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
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000028import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000029import os, sys
30import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger45fd4762009-02-03 03:42:07 +000033import numbers
Tim Peters46cc7022006-03-31 04:11:16 +000034from test.test_support import (TestSkipped, run_unittest, run_doctest,
35 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
Mark Dickinson813f1182010-05-01 11:56:48 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Mark Dickinson1cdfa5f2010-05-04 14:30:32 +000045# Signals ordered with respect to precedence: when an operation
46# produces multiple signals, signals occurring later in the list
47# should be handled before those occurring earlier in the list.
48OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
49 Underflow, Overflow, DivisionByZero, InvalidOperation)
50
Tim Peters46cc7022006-03-31 04:11:16 +000051# Tests are built around these assumed context defaults.
52# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000053def init():
54 global ORIGINAL_CONTEXT
55 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000056 DefaultTestContext = Context(
57 prec = 9,
58 rounding = ROUND_HALF_EVEN,
59 traps = dict.fromkeys(Signals, 0)
60 )
61 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000062
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000063TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000064if __name__ == '__main__':
65 file = sys.argv[0]
66else:
67 file = __file__
68testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000069directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000070
Raymond Hettinger267b8682005-03-27 10:47:39 +000071skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000072
Mark Dickinson25567ef2009-10-27 17:02:46 +000073# list of individual .decTest test ids that correspond to tests that
74# we're skipping for one reason or another.
Mark Dickinson060d6552010-07-08 19:27:24 +000075skipped_test_ids = set([
76 # Skip implementation-specific scaleb tests.
77 'scbx164',
78 'scbx165',
79
80 # For some operations (currently exp, ln, log10, power), the decNumber
81 # reference implementation imposes additional restrictions on the context
82 # and operands. These restrictions are not part of the specification;
83 # however, the effect of these restrictions does show up in some of the
84 # testcases. We skip testcases that violate these restrictions, since
85 # Decimal behaves differently from decNumber for these testcases so these
86 # testcases would otherwise fail.
87 'expx901',
88 'expx902',
89 'expx903',
90 'expx905',
91 'lnx901',
92 'lnx902',
93 'lnx903',
94 'lnx905',
95 'logx901',
96 'logx902',
97 'logx903',
98 'logx905',
99 'powx1183',
100 'powx1184',
101 'powx4001',
102 'powx4002',
103 'powx4003',
104 'powx4005',
105 'powx4008',
106 'powx4010',
107 'powx4012',
108 'powx4014',
109 ])
Mark Dickinson25567ef2009-10-27 17:02:46 +0000110
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000111# Make sure it actually raises errors when not expected and caught in flags
112# Slower, since it runs some things several times.
113EXTENDEDERRORTEST = False
114
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000117 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000119 'division_impossible' : InvalidOperation,
120 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000122 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123 'invalid_operation' : InvalidOperation,
124 'overflow' : Overflow,
125 'rounded' : Rounded,
126 'subnormal' : Subnormal,
127 'underflow' : Underflow}
128
129
130def Nonfunction(*args):
131 """Doesn't do anything."""
132 return None
133
134RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
135 'down' : ROUND_DOWN,
136 'floor' : ROUND_FLOOR,
137 'half_down' : ROUND_HALF_DOWN,
138 'half_even' : ROUND_HALF_EVEN,
139 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000140 'up' : ROUND_UP,
141 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000142
143# Name adapter to be able to change the Decimal and Context
144# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000145nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000146 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000147 'class':'number_class',
148 'comparesig':'compare_signal',
149 'comparetotal':'compare_total',
150 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000151 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000152 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000153 'copynegate':'copy_negate',
154 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000155 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000156 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000157 'iscanonical':'is_canonical',
158 'isfinite':'is_finite',
159 'isinfinite':'is_infinite',
160 'isnan':'is_nan',
161 'isnormal':'is_normal',
162 'isqnan':'is_qnan',
163 'issigned':'is_signed',
164 'issnan':'is_snan',
165 'issubnormal':'is_subnormal',
166 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000167 'maxmag':'max_mag',
168 'minmag':'min_mag',
169 'nextminus':'next_minus',
170 'nextplus':'next_plus',
171 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000172 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000173 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000174 'remaindernear':'remainder_near',
175 'samequantum':'same_quantum',
176 'squareroot':'sqrt',
177 'toeng':'to_eng_string',
178 'tointegral':'to_integral_value',
179 'tointegralx':'to_integral_exact',
180 'tosci':'to_sci_string',
181 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000182 }
183
Facundo Batista1a191df2007-10-02 17:01:24 +0000184# The following functions return True/False rather than a Decimal instance
185
186LOGICAL_FUNCTIONS = (
187 'is_canonical',
188 'is_finite',
189 'is_infinite',
190 'is_nan',
191 'is_normal',
192 'is_qnan',
193 'is_signed',
194 'is_snan',
195 'is_subnormal',
196 'is_zero',
197 'same_quantum',
198 )
199
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200class DecimalTest(unittest.TestCase):
201 """Class which tests the Decimal class against the test cases.
202
203 Changed for unittest.
204 """
205 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000207 self.ignore_list = ['#']
208 # Basically, a # means return NaN InvalidOperation.
209 # Different from a sNaN in trim
210
211 self.ChangeDict = {'precision' : self.change_precision,
212 'rounding' : self.change_rounding_method,
213 'maxexponent' : self.change_max_exponent,
214 'minexponent' : self.change_min_exponent,
215 'clamp' : self.change_clamp}
216
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000217 def eval_file(self, file):
218 global skip_expected
219 if skip_expected:
220 raise TestSkipped
221 return
222 for line in open(file).xreadlines():
223 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000224 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000225 try:
226 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000227 except DecimalException, exception:
228 #Exception raised where there shoudn't have been one.
229 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
230
231 return
232
233 def eval_line(self, s):
234 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
235 s = (s.split('->')[0] + '->' +
236 s.split('->')[1].split('--')[0]).strip()
237 else:
238 s = s.split('--')[0].strip()
239
240 for ignore in self.ignore_list:
241 if s.find(ignore) >= 0:
242 #print s.split()[0], 'NotImplemented--', ignore
243 return
244 if not s:
245 return
246 elif ':' in s:
247 return self.eval_directive(s)
248 else:
249 return self.eval_equation(s)
250
251 def eval_directive(self, s):
252 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
253 if funct == 'rounding':
254 value = RoundingDict[value]
255 else:
256 try:
257 value = int(value)
258 except ValueError:
259 pass
260
261 funct = self.ChangeDict.get(funct, Nonfunction)
262 funct(value)
263
264 def eval_equation(self, s):
265 #global DEFAULT_PRECISION
266 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000267
268 if not TEST_ALL and random.random() < 0.90:
269 return
270
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000271 try:
272 Sides = s.split('->')
273 L = Sides[0].strip().split()
274 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000275 if DEBUG:
276 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 funct = L[1].lower()
278 valstemp = L[2:]
279 L = Sides[1].strip().split()
280 ans = L[0]
281 exceptions = L[1:]
282 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000283 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000284 def FixQuotes(val):
285 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
286 val = val.replace("'", '').replace('"', '')
287 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
288 return val
Mark Dickinson25567ef2009-10-27 17:02:46 +0000289
290 if id in skipped_test_ids:
291 return
292
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 fname = nameAdapter.get(funct, funct)
294 if fname == 'rescale':
295 return
296 funct = getattr(self.context, fname)
297 vals = []
298 conglomerate = ''
299 quote = 0
300 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
301
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000302 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000303 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000305 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000306 for i, val in enumerate(valstemp):
307 if val.count("'") % 2 == 1:
308 quote = 1 - quote
309 if quote:
310 conglomerate = conglomerate + ' ' + val
311 continue
312 else:
313 val = conglomerate + val
314 conglomerate = ''
315 v = FixQuotes(val)
316 if fname in ('to_sci_string', 'to_eng_string'):
317 if EXTENDEDERRORTEST:
318 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000319 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 try:
321 funct(self.context.create_decimal(v))
322 except error:
323 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000324 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 self.fail("Raised %s in %s when %s disabled" % \
326 (e, s, error))
327 else:
328 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000329 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 v = self.context.create_decimal(v)
331 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000332 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000333 vals.append(v)
334
335 ans = FixQuotes(ans)
336
337 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
338 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000339 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 try:
341 funct(*vals)
342 except error:
343 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000344 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 self.fail("Raised %s in %s when %s disabled" % \
346 (e, s, error))
347 else:
348 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000349 self.context.traps[error] = 0
Mark Dickinson1cdfa5f2010-05-04 14:30:32 +0000350
351 # as above, but add traps cumulatively, to check precedence
352 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
353 for error in ordered_errors:
354 self.context.traps[error] = 1
355 try:
356 funct(*vals)
357 except error:
358 pass
359 except Signals, e:
360 self.fail("Raised %s in %s; expected %s" %
361 (type(e), s, error))
362 else:
363 self.fail("Did not raise %s in %s" % (error, s))
364 # reset traps
365 for error in ordered_errors:
366 self.context.traps[error] = 0
367
368
Facundo Batista353750c2007-09-13 18:13:15 +0000369 if DEBUG:
370 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371 try:
372 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000373 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000375 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 self.fail("Raised %s in %s" % (error, s))
377 except: #Catch any error long enough to state the test case.
378 print "ERROR:", s
379 raise
380
381 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000382 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000383
384 myexceptions.sort()
385 theirexceptions.sort()
386
387 self.assertEqual(result, ans,
388 'Incorrect answer for ' + s + ' -- got ' + result)
389 self.assertEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000390 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 return
392
393 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000394 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 def change_precision(self, prec):
397 self.context.prec = prec
398 def change_rounding_method(self, rounding):
399 self.context.rounding = rounding
400 def change_min_exponent(self, exp):
401 self.context.Emin = exp
402 def change_max_exponent(self, exp):
403 self.context.Emax = exp
404 def change_clamp(self, clamp):
405 self.context._clamp = clamp
406
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407
408
409# The following classes test the behaviour of Decimal according to PEP 327
410
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411class DecimalExplicitConstructionTest(unittest.TestCase):
412 '''Unit tests for Explicit Construction cases of Decimal.'''
413
414 def test_explicit_empty(self):
415 self.assertEqual(Decimal(), Decimal("0"))
416
417 def test_explicit_from_None(self):
418 self.assertRaises(TypeError, Decimal, None)
419
420 def test_explicit_from_int(self):
421
422 #positive
423 d = Decimal(45)
424 self.assertEqual(str(d), '45')
425
426 #very large positive
427 d = Decimal(500000123)
428 self.assertEqual(str(d), '500000123')
429
430 #negative
431 d = Decimal(-45)
432 self.assertEqual(str(d), '-45')
433
434 #zero
435 d = Decimal(0)
436 self.assertEqual(str(d), '0')
437
438 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000439
440 #empty
441 self.assertEqual(str(Decimal('')), 'NaN')
442
443 #int
444 self.assertEqual(str(Decimal('45')), '45')
445
446 #float
447 self.assertEqual(str(Decimal('45.34')), '45.34')
448
449 #engineer notation
450 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
451
452 #just not a number
453 self.assertEqual(str(Decimal('ugly')), 'NaN')
454
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000455 #leading and trailing whitespace permitted
456 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
457 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
458
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000459 #unicode strings should be permitted
460 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
461 self.assertEqual(str(Decimal(u'45')), '45')
462 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
463 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465 def test_explicit_from_tuples(self):
466
467 #zero
468 d = Decimal( (0, (0,), 0) )
469 self.assertEqual(str(d), '0')
470
471 #int
472 d = Decimal( (1, (4, 5), 0) )
473 self.assertEqual(str(d), '-45')
474
475 #float
476 d = Decimal( (0, (4, 5, 3, 4), -2) )
477 self.assertEqual(str(d), '45.34')
478
479 #weird
480 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
481 self.assertEqual(str(d), '-4.34913534E-17')
482
483 #wrong number of items
484 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
485
486 #bad sign
487 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000488 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
489 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490
491 #bad exp
492 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495
496 #bad coefficients
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
498 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
502 def test_explicit_from_Decimal(self):
503
504 #positive
505 d = Decimal(45)
506 e = Decimal(d)
507 self.assertEqual(str(e), '45')
508 self.assertNotEqual(id(d), id(e))
509
510 #very large positive
511 d = Decimal(500000123)
512 e = Decimal(d)
513 self.assertEqual(str(e), '500000123')
514 self.assertNotEqual(id(d), id(e))
515
516 #negative
517 d = Decimal(-45)
518 e = Decimal(d)
519 self.assertEqual(str(e), '-45')
520 self.assertNotEqual(id(d), id(e))
521
522 #zero
523 d = Decimal(0)
524 e = Decimal(d)
525 self.assertEqual(str(e), '0')
526 self.assertNotEqual(id(d), id(e))
527
528 def test_explicit_context_create_decimal(self):
529
530 nc = copy.copy(getcontext())
531 nc.prec = 3
532
533 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000534 d = Decimal()
535 self.assertEqual(str(d), '0')
536 d = nc.create_decimal()
537 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538
539 # from None
540 self.assertRaises(TypeError, nc.create_decimal, None)
541
542 # from int
543 d = nc.create_decimal(456)
544 self.failUnless(isinstance(d, Decimal))
545 self.assertEqual(nc.create_decimal(45678),
546 nc.create_decimal('457E+2'))
547
548 # from string
549 d = Decimal('456789')
550 self.assertEqual(str(d), '456789')
551 d = nc.create_decimal('456789')
552 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000553 # leading and trailing whitespace should result in a NaN;
554 # spaces are already checked in Cowlishaw's test-suite, so
555 # here we just check that a trailing newline results in a NaN
556 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000557
558 # from tuples
559 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
560 self.assertEqual(str(d), '-4.34913534E-17')
561 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
562 self.assertEqual(str(d), '-4.35E-17')
563
564 # from Decimal
565 prevdec = Decimal(500000123)
566 d = Decimal(prevdec)
567 self.assertEqual(str(d), '500000123')
568 d = nc.create_decimal(prevdec)
569 self.assertEqual(str(d), '5.00E+8')
570
Mark Dickinson9a6e6452009-08-02 11:01:01 +0000571 def test_unicode_digits(self):
572 test_values = {
573 u'\uff11': '1',
574 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
575 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
576 }
577 for input, expected in test_values.items():
578 self.assertEqual(str(Decimal(input)), expected)
579
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000580
581class DecimalImplicitConstructionTest(unittest.TestCase):
582 '''Unit tests for Implicit Construction cases of Decimal.'''
583
584 def test_implicit_from_None(self):
585 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
586
587 def test_implicit_from_int(self):
588 #normal
589 self.assertEqual(str(Decimal(5) + 45), '50')
590 #exceeding precision
591 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
592
593 def test_implicit_from_string(self):
594 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
595
596 def test_implicit_from_float(self):
597 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
598
599 def test_implicit_from_Decimal(self):
600 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
601
Raymond Hettinger267b8682005-03-27 10:47:39 +0000602 def test_rop(self):
603 # Allow other classes to be trained to interact with Decimals
604 class E:
605 def __divmod__(self, other):
606 return 'divmod ' + str(other)
607 def __rdivmod__(self, other):
608 return str(other) + ' rdivmod'
609 def __lt__(self, other):
610 return 'lt ' + str(other)
611 def __gt__(self, other):
612 return 'gt ' + str(other)
613 def __le__(self, other):
614 return 'le ' + str(other)
615 def __ge__(self, other):
616 return 'ge ' + str(other)
617 def __eq__(self, other):
618 return 'eq ' + str(other)
619 def __ne__(self, other):
620 return 'ne ' + str(other)
621
622 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
623 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
624 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
625 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
626 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
627 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
628 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
629 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
630
631 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000632 oplist = [
633 ('+', '__add__', '__radd__'),
634 ('-', '__sub__', '__rsub__'),
635 ('*', '__mul__', '__rmul__'),
636 ('%', '__mod__', '__rmod__'),
637 ('//', '__floordiv__', '__rfloordiv__'),
638 ('**', '__pow__', '__rpow__')
639 ]
640 if 1/2 == 0:
641 # testing with classic division, so add __div__
642 oplist.append(('/', '__div__', '__rdiv__'))
643 else:
644 # testing with -Qnew, so add __truediv__
645 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000646
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000647 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000648 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
649 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
650 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
651 'str' + lop + '10')
652 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
653 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000654
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000655class DecimalFormatTest(unittest.TestCase):
656 '''Unit tests for the format function.'''
657 def test_formatting(self):
658 # triples giving a format, a Decimal, and the expected result
659 test_values = [
660 ('e', '0E-15', '0e-15'),
661 ('e', '2.3E-15', '2.3e-15'),
662 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
663 ('e', '2.30000E-15', '2.30000e-15'),
664 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
665 ('e', '1.5', '1.5e+0'),
666 ('e', '0.15', '1.5e-1'),
667 ('e', '0.015', '1.5e-2'),
668 ('e', '0.0000000000015', '1.5e-12'),
669 ('e', '15.0', '1.50e+1'),
670 ('e', '-15', '-1.5e+1'),
671 ('e', '0', '0e+0'),
672 ('e', '0E1', '0e+1'),
673 ('e', '0.0', '0e-1'),
674 ('e', '0.00', '0e-2'),
675 ('.6e', '0E-15', '0.000000e-9'),
676 ('.6e', '0', '0.000000e+6'),
677 ('.6e', '9.999999', '9.999999e+0'),
678 ('.6e', '9.9999999', '1.000000e+1'),
679 ('.6e', '-1.23e5', '-1.230000e+5'),
680 ('.6e', '1.23456789e-3', '1.234568e-3'),
681 ('f', '0', '0'),
682 ('f', '0.0', '0.0'),
683 ('f', '0E-2', '0.00'),
684 ('f', '0.00E-8', '0.0000000000'),
685 ('f', '0E1', '0'), # loses exponent information
686 ('f', '3.2E1', '32'),
687 ('f', '3.2E2', '320'),
688 ('f', '3.20E2', '320'),
689 ('f', '3.200E2', '320.0'),
690 ('f', '3.2E-6', '0.0000032'),
691 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
692 ('.6f', '0E1', '0.000000'),
693 ('.6f', '0', '0.000000'),
694 ('.0f', '0', '0'), # no decimal point
695 ('.0f', '0e-2', '0'),
696 ('.0f', '3.14159265', '3'),
697 ('.1f', '3.14159265', '3.1'),
698 ('.4f', '3.14159265', '3.1416'),
699 ('.6f', '3.14159265', '3.141593'),
700 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
701 ('.8f', '3.14159265', '3.14159265'),
702 ('.9f', '3.14159265', '3.141592650'),
703
704 ('g', '0', '0'),
705 ('g', '0.0', '0.0'),
706 ('g', '0E1', '0e+1'),
707 ('G', '0E1', '0E+1'),
708 ('g', '0E-5', '0.00000'),
709 ('g', '0E-6', '0.000000'),
710 ('g', '0E-7', '0e-7'),
711 ('g', '-0E2', '-0e+2'),
712 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
713 ('.1g', '3.14159265', '3'),
714 ('.2g', '3.14159265', '3.1'),
715 ('.5g', '3.14159265', '3.1416'),
716 ('.7g', '3.14159265', '3.141593'),
717 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
718 ('.9g', '3.14159265', '3.14159265'),
719 ('.10g', '3.14159265', '3.14159265'), # don't pad
720
721 ('%', '0E1', '0%'),
722 ('%', '0E0', '0%'),
723 ('%', '0E-1', '0%'),
724 ('%', '0E-2', '0%'),
725 ('%', '0E-3', '0.0%'),
726 ('%', '0E-4', '0.00%'),
727
728 ('.3%', '0', '0.000%'), # all zeros treated equally
729 ('.3%', '0E10', '0.000%'),
730 ('.3%', '0E-10', '0.000%'),
731 ('.3%', '2.34', '234.000%'),
732 ('.3%', '1.234567', '123.457%'),
733 ('.0%', '1.23', '123%'),
734
735 ('e', 'NaN', 'NaN'),
736 ('f', '-NaN123', '-NaN123'),
737 ('+g', 'NaN456', '+NaN456'),
738 ('.3e', 'Inf', 'Infinity'),
739 ('.16f', '-Inf', '-Infinity'),
740 ('.0g', '-sNaN', '-sNaN'),
741
742 ('', '1.00', '1.00'),
Mark Dickinson71416822009-03-17 18:07:41 +0000743
744 # check alignment
745 ('<6', '123', '123 '),
746 ('>6', '123', ' 123'),
747 ('^6', '123', ' 123 '),
748 ('=+6', '123', '+ 123'),
Mark Dickinsonc3c112d2009-09-07 16:19:35 +0000749
750 # issue 6850
751 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000752 ]
753 for fmt, d, result in test_values:
754 self.assertEqual(format(Decimal(d), fmt), result)
755
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000756class DecimalArithmeticOperatorsTest(unittest.TestCase):
757 '''Unit tests for all arithmetic operators, binary and unary.'''
758
759 def test_addition(self):
760
761 d1 = Decimal('-11.1')
762 d2 = Decimal('22.2')
763
764 #two Decimals
765 self.assertEqual(d1+d2, Decimal('11.1'))
766 self.assertEqual(d2+d1, Decimal('11.1'))
767
768 #with other type, left
769 c = d1 + 5
770 self.assertEqual(c, Decimal('-6.1'))
771 self.assertEqual(type(c), type(d1))
772
773 #with other type, right
774 c = 5 + d1
775 self.assertEqual(c, Decimal('-6.1'))
776 self.assertEqual(type(c), type(d1))
777
778 #inline with decimal
779 d1 += d2
780 self.assertEqual(d1, Decimal('11.1'))
781
782 #inline with other type
783 d1 += 5
784 self.assertEqual(d1, Decimal('16.1'))
785
786 def test_subtraction(self):
787
788 d1 = Decimal('-11.1')
789 d2 = Decimal('22.2')
790
791 #two Decimals
792 self.assertEqual(d1-d2, Decimal('-33.3'))
793 self.assertEqual(d2-d1, Decimal('33.3'))
794
795 #with other type, left
796 c = d1 - 5
797 self.assertEqual(c, Decimal('-16.1'))
798 self.assertEqual(type(c), type(d1))
799
800 #with other type, right
801 c = 5 - d1
802 self.assertEqual(c, Decimal('16.1'))
803 self.assertEqual(type(c), type(d1))
804
805 #inline with decimal
806 d1 -= d2
807 self.assertEqual(d1, Decimal('-33.3'))
808
809 #inline with other type
810 d1 -= 5
811 self.assertEqual(d1, Decimal('-38.3'))
812
813 def test_multiplication(self):
814
815 d1 = Decimal('-5')
816 d2 = Decimal('3')
817
818 #two Decimals
819 self.assertEqual(d1*d2, Decimal('-15'))
820 self.assertEqual(d2*d1, Decimal('-15'))
821
822 #with other type, left
823 c = d1 * 5
824 self.assertEqual(c, Decimal('-25'))
825 self.assertEqual(type(c), type(d1))
826
827 #with other type, right
828 c = 5 * d1
829 self.assertEqual(c, Decimal('-25'))
830 self.assertEqual(type(c), type(d1))
831
832 #inline with decimal
833 d1 *= d2
834 self.assertEqual(d1, Decimal('-15'))
835
836 #inline with other type
837 d1 *= 5
838 self.assertEqual(d1, Decimal('-75'))
839
840 def test_division(self):
841
842 d1 = Decimal('-5')
843 d2 = Decimal('2')
844
845 #two Decimals
846 self.assertEqual(d1/d2, Decimal('-2.5'))
847 self.assertEqual(d2/d1, Decimal('-0.4'))
848
849 #with other type, left
850 c = d1 / 4
851 self.assertEqual(c, Decimal('-1.25'))
852 self.assertEqual(type(c), type(d1))
853
854 #with other type, right
855 c = 4 / d1
856 self.assertEqual(c, Decimal('-0.8'))
857 self.assertEqual(type(c), type(d1))
858
859 #inline with decimal
860 d1 /= d2
861 self.assertEqual(d1, Decimal('-2.5'))
862
863 #inline with other type
864 d1 /= 4
865 self.assertEqual(d1, Decimal('-0.625'))
866
867 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000868
869 d1 = Decimal('5')
870 d2 = Decimal('2')
871
872 #two Decimals
873 self.assertEqual(d1//d2, Decimal('2'))
874 self.assertEqual(d2//d1, Decimal('0'))
875
876 #with other type, left
877 c = d1 // 4
878 self.assertEqual(c, Decimal('1'))
879 self.assertEqual(type(c), type(d1))
880
881 #with other type, right
882 c = 7 // d1
883 self.assertEqual(c, Decimal('1'))
884 self.assertEqual(type(c), type(d1))
885
886 #inline with decimal
887 d1 //= d2
888 self.assertEqual(d1, Decimal('2'))
889
890 #inline with other type
891 d1 //= 2
892 self.assertEqual(d1, Decimal('1'))
893
894 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000895
896 d1 = Decimal('5')
897 d2 = Decimal('2')
898
899 #two Decimals
900 self.assertEqual(d1**d2, Decimal('25'))
901 self.assertEqual(d2**d1, Decimal('32'))
902
903 #with other type, left
904 c = d1 ** 4
905 self.assertEqual(c, Decimal('625'))
906 self.assertEqual(type(c), type(d1))
907
908 #with other type, right
909 c = 7 ** d1
910 self.assertEqual(c, Decimal('16807'))
911 self.assertEqual(type(c), type(d1))
912
913 #inline with decimal
914 d1 **= d2
915 self.assertEqual(d1, Decimal('25'))
916
917 #inline with other type
918 d1 **= 4
919 self.assertEqual(d1, Decimal('390625'))
920
921 def test_module(self):
922
923 d1 = Decimal('5')
924 d2 = Decimal('2')
925
926 #two Decimals
927 self.assertEqual(d1%d2, Decimal('1'))
928 self.assertEqual(d2%d1, Decimal('2'))
929
930 #with other type, left
931 c = d1 % 4
932 self.assertEqual(c, Decimal('1'))
933 self.assertEqual(type(c), type(d1))
934
935 #with other type, right
936 c = 7 % d1
937 self.assertEqual(c, Decimal('2'))
938 self.assertEqual(type(c), type(d1))
939
940 #inline with decimal
941 d1 %= d2
942 self.assertEqual(d1, Decimal('1'))
943
944 #inline with other type
945 d1 %= 4
946 self.assertEqual(d1, Decimal('1'))
947
948 def test_floor_div_module(self):
949
950 d1 = Decimal('5')
951 d2 = Decimal('2')
952
953 #two Decimals
954 (p, q) = divmod(d1, d2)
955 self.assertEqual(p, Decimal('2'))
956 self.assertEqual(q, Decimal('1'))
957 self.assertEqual(type(p), type(d1))
958 self.assertEqual(type(q), type(d1))
959
960 #with other type, left
961 (p, q) = divmod(d1, 4)
962 self.assertEqual(p, Decimal('1'))
963 self.assertEqual(q, Decimal('1'))
964 self.assertEqual(type(p), type(d1))
965 self.assertEqual(type(q), type(d1))
966
967 #with other type, right
968 (p, q) = divmod(7, d1)
969 self.assertEqual(p, Decimal('1'))
970 self.assertEqual(q, Decimal('2'))
971 self.assertEqual(type(p), type(d1))
972 self.assertEqual(type(q), type(d1))
973
974 def test_unary_operators(self):
975 self.assertEqual(+Decimal(45), Decimal(+45)) # +
976 self.assertEqual(-Decimal(45), Decimal(-45)) # -
977 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
978
Mark Dickinson2fc92632008-02-06 22:10:50 +0000979 def test_nan_comparisons(self):
980 n = Decimal('NaN')
981 s = Decimal('sNaN')
982 i = Decimal('Inf')
983 f = Decimal('2')
984 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
985 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
986 self.assert_(x != y)
987 self.assert_(not (x == y))
988 self.assert_(not (x < y))
989 self.assert_(not (x <= y))
990 self.assert_(not (x > y))
991 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000992
993# The following are two functions used to test threading in the next class
994
995def thfunc1(cls):
996 d1 = Decimal(1)
997 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +0000998 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000999 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001000 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001001 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001002
Facundo Batistaee340e52008-05-02 17:39:00 +00001003 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1004 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001005 return
1006
1007def thfunc2(cls):
1008 d1 = Decimal(1)
1009 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001010 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001011 thiscontext = getcontext()
1012 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001013 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001014 cls.synchro.set()
1015 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001016
Facundo Batistaee340e52008-05-02 17:39:00 +00001017 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001018 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001019 return
1020
1021
1022class DecimalUseOfContextTest(unittest.TestCase):
1023 '''Unit tests for Use of Context cases in Decimal.'''
1024
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001025 try:
1026 import threading
1027 except ImportError:
1028 threading = None
1029
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001030 # Take care executing this test from IDLE, there's an issue in threading
1031 # that hangs IDLE and I couldn't find it
1032
1033 def test_threading(self):
1034 #Test the "threading isolation" of a Context.
1035
1036 self.synchro = threading.Event()
1037 self.finish1 = threading.Event()
1038 self.finish2 = threading.Event()
1039
1040 th1 = threading.Thread(target=thfunc1, args=(self,))
1041 th2 = threading.Thread(target=thfunc2, args=(self,))
1042
1043 th1.start()
1044 th2.start()
1045
1046 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001047 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001048 return
1049
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001050 if threading is None:
1051 del test_threading
1052
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001053
1054class DecimalUsabilityTest(unittest.TestCase):
1055 '''Unit tests for Usability cases of Decimal.'''
1056
1057 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001058
1059 da = Decimal('23.42')
1060 db = Decimal('23.42')
1061 dc = Decimal('45')
1062
1063 #two Decimals
1064 self.failUnless(dc > da)
1065 self.failUnless(dc >= da)
1066 self.failUnless(da < dc)
1067 self.failUnless(da <= dc)
1068 self.failUnless(da == db)
1069 self.failUnless(da != dc)
1070 self.failUnless(da <= db)
1071 self.failUnless(da >= db)
1072 self.assertEqual(cmp(dc,da), 1)
1073 self.assertEqual(cmp(da,dc), -1)
1074 self.assertEqual(cmp(da,db), 0)
1075
1076 #a Decimal and an int
1077 self.failUnless(dc > 23)
1078 self.failUnless(23 < dc)
1079 self.failUnless(dc == 45)
1080 self.assertEqual(cmp(dc,23), 1)
1081 self.assertEqual(cmp(23,dc), -1)
1082 self.assertEqual(cmp(dc,45), 0)
1083
1084 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001085 self.assertNotEqual(da, 'ugly')
1086 self.assertNotEqual(da, 32.7)
1087 self.assertNotEqual(da, object())
1088 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001089
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001090 # sortable
1091 a = map(Decimal, xrange(100))
1092 b = a[:]
1093 random.shuffle(a)
1094 a.sort()
1095 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001096
Facundo Batista353750c2007-09-13 18:13:15 +00001097 # with None
1098 self.assertFalse(Decimal(1) < None)
1099 self.assertTrue(Decimal(1) > None)
1100
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001101 def test_copy_and_deepcopy_methods(self):
1102 d = Decimal('43.24')
1103 c = copy.copy(d)
1104 self.assertEqual(id(c), id(d))
1105 dc = copy.deepcopy(d)
1106 self.assertEqual(id(dc), id(d))
1107
1108 def test_hash_method(self):
1109 #just that it's hashable
1110 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001111
1112 test_values = [Decimal(sign*(2**m + n))
1113 for m in [0, 14, 15, 16, 17, 30, 31,
1114 32, 33, 62, 63, 64, 65, 66]
1115 for n in range(-10, 10)
1116 for sign in [-1, 1]]
1117 test_values.extend([
1118 Decimal("-0"), # zeros
1119 Decimal("0.00"),
1120 Decimal("-0.000"),
1121 Decimal("0E10"),
1122 Decimal("-0E12"),
1123 Decimal("10.0"), # negative exponent
1124 Decimal("-23.00000"),
1125 Decimal("1230E100"), # positive exponent
1126 Decimal("-4.5678E50"),
1127 # a value for which hash(n) != hash(n % (2**64-1))
1128 # in Python pre-2.6
1129 Decimal(2**64 + 2**32 - 1),
1130 # selection of values which fail with the old (before
1131 # version 2.6) long.__hash__
1132 Decimal("1.634E100"),
1133 Decimal("90.697E100"),
1134 Decimal("188.83E100"),
1135 Decimal("1652.9E100"),
1136 Decimal("56531E100"),
1137 ])
1138
1139 # check that hash(d) == hash(int(d)) for integral values
1140 for value in test_values:
1141 self.assertEqual(hash(value), hash(int(value)))
1142
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001143 #the same hash that to an int
1144 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001145 self.assertRaises(TypeError, hash, Decimal('NaN'))
1146 self.assert_(hash(Decimal('Inf')))
1147 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001148
Facundo Batista52b25792008-01-08 12:25:20 +00001149 # check that the value of the hash doesn't depend on the
1150 # current context (issue #1757)
1151 c = getcontext()
1152 old_precision = c.prec
1153 x = Decimal("123456789.1")
1154
1155 c.prec = 6
1156 h1 = hash(x)
1157 c.prec = 10
1158 h2 = hash(x)
1159 c.prec = 16
1160 h3 = hash(x)
1161
1162 self.assertEqual(h1, h2)
1163 self.assertEqual(h1, h3)
1164 c.prec = old_precision
1165
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001166 def test_min_and_max_methods(self):
1167
1168 d1 = Decimal('15.32')
1169 d2 = Decimal('28.5')
1170 l1 = 15
1171 l2 = 28
1172
1173 #between Decimals
1174 self.failUnless(min(d1,d2) is d1)
1175 self.failUnless(min(d2,d1) is d1)
1176 self.failUnless(max(d1,d2) is d2)
1177 self.failUnless(max(d2,d1) is d2)
1178
1179 #between Decimal and long
1180 self.failUnless(min(d1,l2) is d1)
1181 self.failUnless(min(l2,d1) is d1)
1182 self.failUnless(max(l1,d2) is d2)
1183 self.failUnless(max(d2,l1) is d2)
1184
1185 def test_as_nonzero(self):
1186 #as false
1187 self.failIf(Decimal(0))
1188 #as true
1189 self.failUnless(Decimal('0.372'))
1190
1191 def test_tostring_methods(self):
1192 #Test str and repr methods.
1193
1194 d = Decimal('15.32')
1195 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001196 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001197
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001198 # result type of string methods should be str, not unicode
1199 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1200 u'-0.0E100', u'-NaN001', u'-Inf']
1201
1202 for u in unicode_inputs:
1203 d = Decimal(u)
1204 self.assertEqual(type(str(d)), str)
1205 self.assertEqual(type(repr(d)), str)
1206 self.assertEqual(type(d.to_eng_string()), str)
1207
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208 def test_tonum_methods(self):
1209 #Test float, int and long methods.
1210
1211 d1 = Decimal('66')
1212 d2 = Decimal('15.32')
1213
1214 #int
1215 self.assertEqual(int(d1), 66)
1216 self.assertEqual(int(d2), 15)
1217
1218 #long
1219 self.assertEqual(long(d1), 66)
1220 self.assertEqual(long(d2), 15)
1221
1222 #float
1223 self.assertEqual(float(d1), 66)
1224 self.assertEqual(float(d2), 15.32)
1225
1226 def test_eval_round_trip(self):
1227
1228 #with zero
1229 d = Decimal( (0, (0,), 0) )
1230 self.assertEqual(d, eval(repr(d)))
1231
1232 #int
1233 d = Decimal( (1, (4, 5), 0) )
1234 self.assertEqual(d, eval(repr(d)))
1235
1236 #float
1237 d = Decimal( (0, (4, 5, 3, 4), -2) )
1238 self.assertEqual(d, eval(repr(d)))
1239
1240 #weird
1241 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1242 self.assertEqual(d, eval(repr(d)))
1243
1244 def test_as_tuple(self):
1245
1246 #with zero
1247 d = Decimal(0)
1248 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1249
1250 #int
1251 d = Decimal(-45)
1252 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1253
1254 #complicated string
1255 d = Decimal("-4.34913534E-17")
1256 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1257
1258 #inf
1259 d = Decimal("Infinity")
1260 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1261
Facundo Batista9b5e2312007-10-19 19:25:57 +00001262 #leading zeros in coefficient should be stripped
1263 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1264 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1265 d = Decimal( (1, (0, 0, 0), 37) )
1266 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1267 d = Decimal( (1, (), 37) )
1268 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1269
1270 #leading zeros in NaN diagnostic info should be stripped
1271 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1272 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1273 d = Decimal( (1, (0, 0, 0), 'N') )
1274 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1275 d = Decimal( (1, (), 'n') )
1276 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1277
1278 #coefficient in infinity should be ignored
1279 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1280 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1281 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1282 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1283
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001284 def test_immutability_operations(self):
1285 # Do operations and check that it didn't change change internal objects.
1286
1287 d1 = Decimal('-25e55')
1288 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001289 d2 = Decimal('33e+33')
1290 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001291
1292 def checkSameDec(operation, useOther=False):
1293 if useOther:
1294 eval("d1." + operation + "(d2)")
1295 self.assertEqual(d1._sign, b1._sign)
1296 self.assertEqual(d1._int, b1._int)
1297 self.assertEqual(d1._exp, b1._exp)
1298 self.assertEqual(d2._sign, b2._sign)
1299 self.assertEqual(d2._int, b2._int)
1300 self.assertEqual(d2._exp, b2._exp)
1301 else:
1302 eval("d1." + operation + "()")
1303 self.assertEqual(d1._sign, b1._sign)
1304 self.assertEqual(d1._int, b1._int)
1305 self.assertEqual(d1._exp, b1._exp)
1306 return
1307
1308 Decimal(d1)
1309 self.assertEqual(d1._sign, b1._sign)
1310 self.assertEqual(d1._int, b1._int)
1311 self.assertEqual(d1._exp, b1._exp)
1312
1313 checkSameDec("__abs__")
1314 checkSameDec("__add__", True)
1315 checkSameDec("__div__", True)
1316 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001317 checkSameDec("__eq__", True)
1318 checkSameDec("__ne__", True)
1319 checkSameDec("__le__", True)
1320 checkSameDec("__lt__", True)
1321 checkSameDec("__ge__", True)
1322 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001323 checkSameDec("__float__")
1324 checkSameDec("__floordiv__", True)
1325 checkSameDec("__hash__")
1326 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001327 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001328 checkSameDec("__long__")
1329 checkSameDec("__mod__", True)
1330 checkSameDec("__mul__", True)
1331 checkSameDec("__neg__")
1332 checkSameDec("__nonzero__")
1333 checkSameDec("__pos__")
1334 checkSameDec("__pow__", True)
1335 checkSameDec("__radd__", True)
1336 checkSameDec("__rdiv__", True)
1337 checkSameDec("__rdivmod__", True)
1338 checkSameDec("__repr__")
1339 checkSameDec("__rfloordiv__", True)
1340 checkSameDec("__rmod__", True)
1341 checkSameDec("__rmul__", True)
1342 checkSameDec("__rpow__", True)
1343 checkSameDec("__rsub__", True)
1344 checkSameDec("__str__")
1345 checkSameDec("__sub__", True)
1346 checkSameDec("__truediv__", True)
1347 checkSameDec("adjusted")
1348 checkSameDec("as_tuple")
1349 checkSameDec("compare", True)
1350 checkSameDec("max", True)
1351 checkSameDec("min", True)
1352 checkSameDec("normalize")
1353 checkSameDec("quantize", True)
1354 checkSameDec("remainder_near", True)
1355 checkSameDec("same_quantum", True)
1356 checkSameDec("sqrt")
1357 checkSameDec("to_eng_string")
1358 checkSameDec("to_integral")
1359
Facundo Batista6c398da2007-09-17 17:30:13 +00001360 def test_subclassing(self):
1361 # Different behaviours when subclassing Decimal
1362
1363 class MyDecimal(Decimal):
1364 pass
1365
1366 d1 = MyDecimal(1)
1367 d2 = MyDecimal(2)
1368 d = d1 + d2
1369 self.assertTrue(type(d) is Decimal)
1370
1371 d = d1.max(d2)
1372 self.assertTrue(type(d) is Decimal)
1373
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001374 def test_implicit_context(self):
1375 # Check results when context given implicitly. (Issue 2478)
1376 c = getcontext()
1377 self.assertEqual(str(Decimal(0).sqrt()),
1378 str(c.sqrt(Decimal(0))))
1379
Mark Dickinsond8a2e2b2009-10-29 12:16:15 +00001380 def test_conversions_from_int(self):
1381 # Check that methods taking a second Decimal argument will
1382 # always accept an integer in place of a Decimal.
1383 self.assertEqual(Decimal(4).compare(3),
1384 Decimal(4).compare(Decimal(3)))
1385 self.assertEqual(Decimal(4).compare_signal(3),
1386 Decimal(4).compare_signal(Decimal(3)))
1387 self.assertEqual(Decimal(4).compare_total(3),
1388 Decimal(4).compare_total(Decimal(3)))
1389 self.assertEqual(Decimal(4).compare_total_mag(3),
1390 Decimal(4).compare_total_mag(Decimal(3)))
1391 self.assertEqual(Decimal(10101).logical_and(1001),
1392 Decimal(10101).logical_and(Decimal(1001)))
1393 self.assertEqual(Decimal(10101).logical_or(1001),
1394 Decimal(10101).logical_or(Decimal(1001)))
1395 self.assertEqual(Decimal(10101).logical_xor(1001),
1396 Decimal(10101).logical_xor(Decimal(1001)))
1397 self.assertEqual(Decimal(567).max(123),
1398 Decimal(567).max(Decimal(123)))
1399 self.assertEqual(Decimal(567).max_mag(123),
1400 Decimal(567).max_mag(Decimal(123)))
1401 self.assertEqual(Decimal(567).min(123),
1402 Decimal(567).min(Decimal(123)))
1403 self.assertEqual(Decimal(567).min_mag(123),
1404 Decimal(567).min_mag(Decimal(123)))
1405 self.assertEqual(Decimal(567).next_toward(123),
1406 Decimal(567).next_toward(Decimal(123)))
1407 self.assertEqual(Decimal(1234).quantize(100),
1408 Decimal(1234).quantize(Decimal(100)))
1409 self.assertEqual(Decimal(768).remainder_near(1234),
1410 Decimal(768).remainder_near(Decimal(1234)))
1411 self.assertEqual(Decimal(123).rotate(1),
1412 Decimal(123).rotate(Decimal(1)))
1413 self.assertEqual(Decimal(1234).same_quantum(1000),
1414 Decimal(1234).same_quantum(Decimal(1000)))
1415 self.assertEqual(Decimal('9.123').scaleb(-100),
1416 Decimal('9.123').scaleb(Decimal(-100)))
1417 self.assertEqual(Decimal(456).shift(-1),
1418 Decimal(456).shift(Decimal(-1)))
1419
1420 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1421 Decimal(-12).fma(Decimal(45), Decimal(67)))
1422 self.assertEqual(Decimal(-12).fma(45, 67),
1423 Decimal(-12).fma(Decimal(45), Decimal(67)))
1424 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1425 Decimal(-12).fma(Decimal(45), Decimal(67)))
1426
Facundo Batista6c398da2007-09-17 17:30:13 +00001427
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001428class DecimalPythonAPItests(unittest.TestCase):
1429
Raymond Hettinger45fd4762009-02-03 03:42:07 +00001430 def test_abc(self):
1431 self.assert_(issubclass(Decimal, numbers.Number))
1432 self.assert_(not issubclass(Decimal, numbers.Real))
1433 self.assert_(isinstance(Decimal(0), numbers.Number))
1434 self.assert_(not isinstance(Decimal(0), numbers.Real))
1435
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001436 def test_pickle(self):
1437 d = Decimal('-3.141590000')
1438 p = pickle.dumps(d)
1439 e = pickle.loads(p)
1440 self.assertEqual(d, e)
1441
Raymond Hettinger5548be22004-07-05 18:49:38 +00001442 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001443 for x in range(-250, 250):
1444 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001445 # should work the same as for floats
1446 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001447 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001448 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001449 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001450 self.assertEqual(Decimal(int(d)), r)
1451
Mark Dickinsonc05b7892009-09-08 19:22:18 +00001452 self.assertRaises(ValueError, int, Decimal('-nan'))
1453 self.assertRaises(ValueError, int, Decimal('snan'))
1454 self.assertRaises(OverflowError, int, Decimal('inf'))
1455 self.assertRaises(OverflowError, int, Decimal('-inf'))
1456
1457 self.assertRaises(ValueError, long, Decimal('-nan'))
1458 self.assertRaises(ValueError, long, Decimal('snan'))
1459 self.assertRaises(OverflowError, long, Decimal('inf'))
1460 self.assertRaises(OverflowError, long, Decimal('-inf'))
1461
Raymond Hettinger5a053642008-01-24 19:05:29 +00001462 def test_trunc(self):
1463 for x in range(-250, 250):
1464 s = '%0.2f' % (x / 100.0)
1465 # should work the same as for floats
1466 self.assertEqual(int(Decimal(s)), int(float(s)))
1467 # should work the same as to_integral in the ROUND_DOWN mode
1468 d = Decimal(s)
1469 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001470 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001471
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
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001494class WithStatementTest(unittest.TestCase):
1495 # Can't do these as docstrings until Python 2.6
1496 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001497
1498 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001499 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001500 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):
Nick Coghlanced12182006-09-02 03:54:17 +00001509 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001510 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
Facundo Batista353750c2007-09-13 18:13:15 +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()
1560
1561 # flags we actually got
1562 new_flags = [k for k,v in context.flags.items() if v]
1563 new_flags.sort()
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
Neal Norwitzce4a9c92006-04-09 08:36:46 +00001579 init()
Facundo Batista353750c2007-09-13 18:13:15 +00001580 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001581 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00001582 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001583
Facundo Batista353750c2007-09-13 18:13:15 +00001584 if todo_tests is None:
1585 test_classes = [
1586 DecimalExplicitConstructionTest,
1587 DecimalImplicitConstructionTest,
1588 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00001589 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +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
Tim Peters46cc7022006-03-31 04:11:16 +00001615 try:
1616 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00001617 if todo_tests is None:
1618 import decimal as DecimalModule
1619 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00001620 finally:
1621 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001622
1623if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +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:
Facundo Batista353750c2007-09-13 18:13:15 +00001635 test_main(arith=True, verbose=True)