blob: 9b5fe155b860a8df15bddc07b75ef68606598eba [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.
75skipped_test_ids = [
76 'scbx164', # skipping apparently implementation-specific scaleb
77 'scbx165', # tests, pending clarification of scaleb rules.
78]
79
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000080# Make sure it actually raises errors when not expected and caught in flags
81# Slower, since it runs some things several times.
82EXTENDEDERRORTEST = False
83
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000085ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000086 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000087 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000088 'division_impossible' : InvalidOperation,
89 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000090 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000091 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000092 'invalid_operation' : InvalidOperation,
93 'overflow' : Overflow,
94 'rounded' : Rounded,
95 'subnormal' : Subnormal,
96 'underflow' : Underflow}
97
98
99def Nonfunction(*args):
100 """Doesn't do anything."""
101 return None
102
103RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
104 'down' : ROUND_DOWN,
105 'floor' : ROUND_FLOOR,
106 'half_down' : ROUND_HALF_DOWN,
107 'half_even' : ROUND_HALF_EVEN,
108 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000109 'up' : ROUND_UP,
110 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000111
112# Name adapter to be able to change the Decimal and Context
113# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000114nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000116 'class':'number_class',
117 'comparesig':'compare_signal',
118 'comparetotal':'compare_total',
119 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000120 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000121 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000122 'copynegate':'copy_negate',
123 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000124 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000125 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000126 'iscanonical':'is_canonical',
127 'isfinite':'is_finite',
128 'isinfinite':'is_infinite',
129 'isnan':'is_nan',
130 'isnormal':'is_normal',
131 'isqnan':'is_qnan',
132 'issigned':'is_signed',
133 'issnan':'is_snan',
134 'issubnormal':'is_subnormal',
135 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000136 'maxmag':'max_mag',
137 'minmag':'min_mag',
138 'nextminus':'next_minus',
139 'nextplus':'next_plus',
140 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000141 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000142 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000143 'remaindernear':'remainder_near',
144 'samequantum':'same_quantum',
145 'squareroot':'sqrt',
146 'toeng':'to_eng_string',
147 'tointegral':'to_integral_value',
148 'tointegralx':'to_integral_exact',
149 'tosci':'to_sci_string',
150 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000151 }
152
Facundo Batista1a191df2007-10-02 17:01:24 +0000153# The following functions return True/False rather than a Decimal instance
154
155LOGICAL_FUNCTIONS = (
156 'is_canonical',
157 'is_finite',
158 'is_infinite',
159 'is_nan',
160 'is_normal',
161 'is_qnan',
162 'is_signed',
163 'is_snan',
164 'is_subnormal',
165 'is_zero',
166 'same_quantum',
167 )
168
Facundo Batista353750c2007-09-13 18:13:15 +0000169# For some operations (currently exp, ln, log10, power), the decNumber
170# reference implementation imposes additional restrictions on the
171# context and operands. These restrictions are not part of the
172# specification; however, the effect of these restrictions does show
173# up in some of the testcases. We skip testcases that violate these
174# restrictions, since Decimal behaves differently from decNumber for
175# these testcases so these testcases would otherwise fail.
176
177decNumberRestricted = ('power', 'ln', 'log10', 'exp')
178DEC_MAX_MATH = 999999
179def outside_decNumber_bounds(v, context):
180 if (context.prec > DEC_MAX_MATH or
181 context.Emax > DEC_MAX_MATH or
182 -context.Emin > DEC_MAX_MATH):
183 return True
184 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000185 v.adjusted() > DEC_MAX_MATH or
186 v.adjusted() < 1-2*DEC_MAX_MATH):
187 return True
188 return False
189
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190class DecimalTest(unittest.TestCase):
191 """Class which tests the Decimal class against the test cases.
192
193 Changed for unittest.
194 """
195 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000196 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000197 self.ignore_list = ['#']
198 # Basically, a # means return NaN InvalidOperation.
199 # Different from a sNaN in trim
200
201 self.ChangeDict = {'precision' : self.change_precision,
202 'rounding' : self.change_rounding_method,
203 'maxexponent' : self.change_max_exponent,
204 'minexponent' : self.change_min_exponent,
205 'clamp' : self.change_clamp}
206
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000207 def eval_file(self, file):
208 global skip_expected
209 if skip_expected:
210 raise TestSkipped
211 return
212 for line in open(file).xreadlines():
213 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000214 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000215 try:
216 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000217 except DecimalException, exception:
218 #Exception raised where there shoudn't have been one.
219 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
220
221 return
222
223 def eval_line(self, s):
224 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
225 s = (s.split('->')[0] + '->' +
226 s.split('->')[1].split('--')[0]).strip()
227 else:
228 s = s.split('--')[0].strip()
229
230 for ignore in self.ignore_list:
231 if s.find(ignore) >= 0:
232 #print s.split()[0], 'NotImplemented--', ignore
233 return
234 if not s:
235 return
236 elif ':' in s:
237 return self.eval_directive(s)
238 else:
239 return self.eval_equation(s)
240
241 def eval_directive(self, s):
242 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
243 if funct == 'rounding':
244 value = RoundingDict[value]
245 else:
246 try:
247 value = int(value)
248 except ValueError:
249 pass
250
251 funct = self.ChangeDict.get(funct, Nonfunction)
252 funct(value)
253
254 def eval_equation(self, s):
255 #global DEFAULT_PRECISION
256 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000257
258 if not TEST_ALL and random.random() < 0.90:
259 return
260
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000261 try:
262 Sides = s.split('->')
263 L = Sides[0].strip().split()
264 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000265 if DEBUG:
266 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000267 funct = L[1].lower()
268 valstemp = L[2:]
269 L = Sides[1].strip().split()
270 ans = L[0]
271 exceptions = L[1:]
272 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000273 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000274 def FixQuotes(val):
275 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
276 val = val.replace("'", '').replace('"', '')
277 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
278 return val
Mark Dickinson25567ef2009-10-27 17:02:46 +0000279
280 if id in skipped_test_ids:
281 return
282
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000283 fname = nameAdapter.get(funct, funct)
284 if fname == 'rescale':
285 return
286 funct = getattr(self.context, fname)
287 vals = []
288 conglomerate = ''
289 quote = 0
290 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
291
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000292 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000293 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000294 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000295 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000296 for i, val in enumerate(valstemp):
297 if val.count("'") % 2 == 1:
298 quote = 1 - quote
299 if quote:
300 conglomerate = conglomerate + ' ' + val
301 continue
302 else:
303 val = conglomerate + val
304 conglomerate = ''
305 v = FixQuotes(val)
306 if fname in ('to_sci_string', 'to_eng_string'):
307 if EXTENDEDERRORTEST:
308 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000309 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000310 try:
311 funct(self.context.create_decimal(v))
312 except error:
313 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000314 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000315 self.fail("Raised %s in %s when %s disabled" % \
316 (e, s, error))
317 else:
318 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000319 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 v = self.context.create_decimal(v)
321 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000322 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000323 vals.append(v)
324
325 ans = FixQuotes(ans)
326
Facundo Batista353750c2007-09-13 18:13:15 +0000327 # skip tests that are related to bounds imposed in the decNumber
328 # reference implementation
329 if fname in decNumberRestricted:
330 if fname == 'power':
331 if not (vals[1]._isinteger() and
332 -1999999997 <= vals[1] <= 999999999):
333 if outside_decNumber_bounds(vals[0], self.context) or \
334 outside_decNumber_bounds(vals[1], self.context):
335 #print "Skipping test %s" % s
336 return
337 else:
338 if outside_decNumber_bounds(vals[0], self.context):
339 #print "Skipping test %s" % s
340 return
341
342
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
344 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000345 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000346 try:
347 funct(*vals)
348 except error:
349 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000350 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 self.fail("Raised %s in %s when %s disabled" % \
352 (e, s, error))
353 else:
354 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000355 self.context.traps[error] = 0
Mark Dickinson1cdfa5f2010-05-04 14:30:32 +0000356
357 # as above, but add traps cumulatively, to check precedence
358 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
359 for error in ordered_errors:
360 self.context.traps[error] = 1
361 try:
362 funct(*vals)
363 except error:
364 pass
365 except Signals, e:
366 self.fail("Raised %s in %s; expected %s" %
367 (type(e), s, error))
368 else:
369 self.fail("Did not raise %s in %s" % (error, s))
370 # reset traps
371 for error in ordered_errors:
372 self.context.traps[error] = 0
373
374
Facundo Batista353750c2007-09-13 18:13:15 +0000375 if DEBUG:
376 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 try:
378 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000379 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000381 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382 self.fail("Raised %s in %s" % (error, s))
383 except: #Catch any error long enough to state the test case.
384 print "ERROR:", s
385 raise
386
387 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000388 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389
390 myexceptions.sort()
391 theirexceptions.sort()
392
393 self.assertEqual(result, ans,
394 'Incorrect answer for ' + s + ' -- got ' + result)
395 self.assertEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000396 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 return
398
399 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000400 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000401
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000402 def change_precision(self, prec):
403 self.context.prec = prec
404 def change_rounding_method(self, rounding):
405 self.context.rounding = rounding
406 def change_min_exponent(self, exp):
407 self.context.Emin = exp
408 def change_max_exponent(self, exp):
409 self.context.Emax = exp
410 def change_clamp(self, clamp):
411 self.context._clamp = clamp
412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413
414
415# The following classes test the behaviour of Decimal according to PEP 327
416
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000417class DecimalExplicitConstructionTest(unittest.TestCase):
418 '''Unit tests for Explicit Construction cases of Decimal.'''
419
420 def test_explicit_empty(self):
421 self.assertEqual(Decimal(), Decimal("0"))
422
423 def test_explicit_from_None(self):
424 self.assertRaises(TypeError, Decimal, None)
425
426 def test_explicit_from_int(self):
427
428 #positive
429 d = Decimal(45)
430 self.assertEqual(str(d), '45')
431
432 #very large positive
433 d = Decimal(500000123)
434 self.assertEqual(str(d), '500000123')
435
436 #negative
437 d = Decimal(-45)
438 self.assertEqual(str(d), '-45')
439
440 #zero
441 d = Decimal(0)
442 self.assertEqual(str(d), '0')
443
444 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000445
446 #empty
447 self.assertEqual(str(Decimal('')), 'NaN')
448
449 #int
450 self.assertEqual(str(Decimal('45')), '45')
451
452 #float
453 self.assertEqual(str(Decimal('45.34')), '45.34')
454
455 #engineer notation
456 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
457
458 #just not a number
459 self.assertEqual(str(Decimal('ugly')), 'NaN')
460
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000461 #leading and trailing whitespace permitted
462 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
463 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
464
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000465 #unicode strings should be permitted
466 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
467 self.assertEqual(str(Decimal(u'45')), '45')
468 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
469 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000471 def test_explicit_from_tuples(self):
472
473 #zero
474 d = Decimal( (0, (0,), 0) )
475 self.assertEqual(str(d), '0')
476
477 #int
478 d = Decimal( (1, (4, 5), 0) )
479 self.assertEqual(str(d), '-45')
480
481 #float
482 d = Decimal( (0, (4, 5, 3, 4), -2) )
483 self.assertEqual(str(d), '45.34')
484
485 #weird
486 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
487 self.assertEqual(str(d), '-4.34913534E-17')
488
489 #wrong number of items
490 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
491
492 #bad sign
493 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000494 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
495 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496
497 #bad exp
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
502 #bad coefficients
503 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
504 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000505 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000506 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000507
508 def test_explicit_from_Decimal(self):
509
510 #positive
511 d = Decimal(45)
512 e = Decimal(d)
513 self.assertEqual(str(e), '45')
514 self.assertNotEqual(id(d), id(e))
515
516 #very large positive
517 d = Decimal(500000123)
518 e = Decimal(d)
519 self.assertEqual(str(e), '500000123')
520 self.assertNotEqual(id(d), id(e))
521
522 #negative
523 d = Decimal(-45)
524 e = Decimal(d)
525 self.assertEqual(str(e), '-45')
526 self.assertNotEqual(id(d), id(e))
527
528 #zero
529 d = Decimal(0)
530 e = Decimal(d)
531 self.assertEqual(str(e), '0')
532 self.assertNotEqual(id(d), id(e))
533
534 def test_explicit_context_create_decimal(self):
535
536 nc = copy.copy(getcontext())
537 nc.prec = 3
538
539 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000540 d = Decimal()
541 self.assertEqual(str(d), '0')
542 d = nc.create_decimal()
543 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000544
545 # from None
546 self.assertRaises(TypeError, nc.create_decimal, None)
547
548 # from int
549 d = nc.create_decimal(456)
550 self.failUnless(isinstance(d, Decimal))
551 self.assertEqual(nc.create_decimal(45678),
552 nc.create_decimal('457E+2'))
553
554 # from string
555 d = Decimal('456789')
556 self.assertEqual(str(d), '456789')
557 d = nc.create_decimal('456789')
558 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000559 # leading and trailing whitespace should result in a NaN;
560 # spaces are already checked in Cowlishaw's test-suite, so
561 # here we just check that a trailing newline results in a NaN
562 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000563
564 # from tuples
565 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
566 self.assertEqual(str(d), '-4.34913534E-17')
567 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
568 self.assertEqual(str(d), '-4.35E-17')
569
570 # from Decimal
571 prevdec = Decimal(500000123)
572 d = Decimal(prevdec)
573 self.assertEqual(str(d), '500000123')
574 d = nc.create_decimal(prevdec)
575 self.assertEqual(str(d), '5.00E+8')
576
Mark Dickinson9a6e6452009-08-02 11:01:01 +0000577 def test_unicode_digits(self):
578 test_values = {
579 u'\uff11': '1',
580 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
581 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
582 }
583 for input, expected in test_values.items():
584 self.assertEqual(str(Decimal(input)), expected)
585
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000586
587class DecimalImplicitConstructionTest(unittest.TestCase):
588 '''Unit tests for Implicit Construction cases of Decimal.'''
589
590 def test_implicit_from_None(self):
591 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
592
593 def test_implicit_from_int(self):
594 #normal
595 self.assertEqual(str(Decimal(5) + 45), '50')
596 #exceeding precision
597 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
598
599 def test_implicit_from_string(self):
600 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
601
602 def test_implicit_from_float(self):
603 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
604
605 def test_implicit_from_Decimal(self):
606 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
607
Raymond Hettinger267b8682005-03-27 10:47:39 +0000608 def test_rop(self):
609 # Allow other classes to be trained to interact with Decimals
610 class E:
611 def __divmod__(self, other):
612 return 'divmod ' + str(other)
613 def __rdivmod__(self, other):
614 return str(other) + ' rdivmod'
615 def __lt__(self, other):
616 return 'lt ' + str(other)
617 def __gt__(self, other):
618 return 'gt ' + str(other)
619 def __le__(self, other):
620 return 'le ' + str(other)
621 def __ge__(self, other):
622 return 'ge ' + str(other)
623 def __eq__(self, other):
624 return 'eq ' + str(other)
625 def __ne__(self, other):
626 return 'ne ' + str(other)
627
628 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
629 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
630 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
631 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
632 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
633 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
634 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
635 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
636
637 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000638 oplist = [
639 ('+', '__add__', '__radd__'),
640 ('-', '__sub__', '__rsub__'),
641 ('*', '__mul__', '__rmul__'),
642 ('%', '__mod__', '__rmod__'),
643 ('//', '__floordiv__', '__rfloordiv__'),
644 ('**', '__pow__', '__rpow__')
645 ]
646 if 1/2 == 0:
647 # testing with classic division, so add __div__
648 oplist.append(('/', '__div__', '__rdiv__'))
649 else:
650 # testing with -Qnew, so add __truediv__
651 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000652
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000653 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000654 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
655 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
656 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
657 'str' + lop + '10')
658 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
659 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000661class DecimalFormatTest(unittest.TestCase):
662 '''Unit tests for the format function.'''
663 def test_formatting(self):
664 # triples giving a format, a Decimal, and the expected result
665 test_values = [
666 ('e', '0E-15', '0e-15'),
667 ('e', '2.3E-15', '2.3e-15'),
668 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
669 ('e', '2.30000E-15', '2.30000e-15'),
670 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
671 ('e', '1.5', '1.5e+0'),
672 ('e', '0.15', '1.5e-1'),
673 ('e', '0.015', '1.5e-2'),
674 ('e', '0.0000000000015', '1.5e-12'),
675 ('e', '15.0', '1.50e+1'),
676 ('e', '-15', '-1.5e+1'),
677 ('e', '0', '0e+0'),
678 ('e', '0E1', '0e+1'),
679 ('e', '0.0', '0e-1'),
680 ('e', '0.00', '0e-2'),
681 ('.6e', '0E-15', '0.000000e-9'),
682 ('.6e', '0', '0.000000e+6'),
683 ('.6e', '9.999999', '9.999999e+0'),
684 ('.6e', '9.9999999', '1.000000e+1'),
685 ('.6e', '-1.23e5', '-1.230000e+5'),
686 ('.6e', '1.23456789e-3', '1.234568e-3'),
687 ('f', '0', '0'),
688 ('f', '0.0', '0.0'),
689 ('f', '0E-2', '0.00'),
690 ('f', '0.00E-8', '0.0000000000'),
691 ('f', '0E1', '0'), # loses exponent information
692 ('f', '3.2E1', '32'),
693 ('f', '3.2E2', '320'),
694 ('f', '3.20E2', '320'),
695 ('f', '3.200E2', '320.0'),
696 ('f', '3.2E-6', '0.0000032'),
697 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
698 ('.6f', '0E1', '0.000000'),
699 ('.6f', '0', '0.000000'),
700 ('.0f', '0', '0'), # no decimal point
701 ('.0f', '0e-2', '0'),
702 ('.0f', '3.14159265', '3'),
703 ('.1f', '3.14159265', '3.1'),
704 ('.4f', '3.14159265', '3.1416'),
705 ('.6f', '3.14159265', '3.141593'),
706 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
707 ('.8f', '3.14159265', '3.14159265'),
708 ('.9f', '3.14159265', '3.141592650'),
709
710 ('g', '0', '0'),
711 ('g', '0.0', '0.0'),
712 ('g', '0E1', '0e+1'),
713 ('G', '0E1', '0E+1'),
714 ('g', '0E-5', '0.00000'),
715 ('g', '0E-6', '0.000000'),
716 ('g', '0E-7', '0e-7'),
717 ('g', '-0E2', '-0e+2'),
718 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
719 ('.1g', '3.14159265', '3'),
720 ('.2g', '3.14159265', '3.1'),
721 ('.5g', '3.14159265', '3.1416'),
722 ('.7g', '3.14159265', '3.141593'),
723 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
724 ('.9g', '3.14159265', '3.14159265'),
725 ('.10g', '3.14159265', '3.14159265'), # don't pad
726
727 ('%', '0E1', '0%'),
728 ('%', '0E0', '0%'),
729 ('%', '0E-1', '0%'),
730 ('%', '0E-2', '0%'),
731 ('%', '0E-3', '0.0%'),
732 ('%', '0E-4', '0.00%'),
733
734 ('.3%', '0', '0.000%'), # all zeros treated equally
735 ('.3%', '0E10', '0.000%'),
736 ('.3%', '0E-10', '0.000%'),
737 ('.3%', '2.34', '234.000%'),
738 ('.3%', '1.234567', '123.457%'),
739 ('.0%', '1.23', '123%'),
740
741 ('e', 'NaN', 'NaN'),
742 ('f', '-NaN123', '-NaN123'),
743 ('+g', 'NaN456', '+NaN456'),
744 ('.3e', 'Inf', 'Infinity'),
745 ('.16f', '-Inf', '-Infinity'),
746 ('.0g', '-sNaN', '-sNaN'),
747
748 ('', '1.00', '1.00'),
Mark Dickinson71416822009-03-17 18:07:41 +0000749
750 # check alignment
751 ('<6', '123', '123 '),
752 ('>6', '123', ' 123'),
753 ('^6', '123', ' 123 '),
754 ('=+6', '123', '+ 123'),
Mark Dickinsonc3c112d2009-09-07 16:19:35 +0000755
756 # issue 6850
757 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000758 ]
759 for fmt, d, result in test_values:
760 self.assertEqual(format(Decimal(d), fmt), result)
761
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000762class DecimalArithmeticOperatorsTest(unittest.TestCase):
763 '''Unit tests for all arithmetic operators, binary and unary.'''
764
765 def test_addition(self):
766
767 d1 = Decimal('-11.1')
768 d2 = Decimal('22.2')
769
770 #two Decimals
771 self.assertEqual(d1+d2, Decimal('11.1'))
772 self.assertEqual(d2+d1, Decimal('11.1'))
773
774 #with other type, left
775 c = d1 + 5
776 self.assertEqual(c, Decimal('-6.1'))
777 self.assertEqual(type(c), type(d1))
778
779 #with other type, right
780 c = 5 + d1
781 self.assertEqual(c, Decimal('-6.1'))
782 self.assertEqual(type(c), type(d1))
783
784 #inline with decimal
785 d1 += d2
786 self.assertEqual(d1, Decimal('11.1'))
787
788 #inline with other type
789 d1 += 5
790 self.assertEqual(d1, Decimal('16.1'))
791
792 def test_subtraction(self):
793
794 d1 = Decimal('-11.1')
795 d2 = Decimal('22.2')
796
797 #two Decimals
798 self.assertEqual(d1-d2, Decimal('-33.3'))
799 self.assertEqual(d2-d1, Decimal('33.3'))
800
801 #with other type, left
802 c = d1 - 5
803 self.assertEqual(c, Decimal('-16.1'))
804 self.assertEqual(type(c), type(d1))
805
806 #with other type, right
807 c = 5 - d1
808 self.assertEqual(c, Decimal('16.1'))
809 self.assertEqual(type(c), type(d1))
810
811 #inline with decimal
812 d1 -= d2
813 self.assertEqual(d1, Decimal('-33.3'))
814
815 #inline with other type
816 d1 -= 5
817 self.assertEqual(d1, Decimal('-38.3'))
818
819 def test_multiplication(self):
820
821 d1 = Decimal('-5')
822 d2 = Decimal('3')
823
824 #two Decimals
825 self.assertEqual(d1*d2, Decimal('-15'))
826 self.assertEqual(d2*d1, Decimal('-15'))
827
828 #with other type, left
829 c = d1 * 5
830 self.assertEqual(c, Decimal('-25'))
831 self.assertEqual(type(c), type(d1))
832
833 #with other type, right
834 c = 5 * d1
835 self.assertEqual(c, Decimal('-25'))
836 self.assertEqual(type(c), type(d1))
837
838 #inline with decimal
839 d1 *= d2
840 self.assertEqual(d1, Decimal('-15'))
841
842 #inline with other type
843 d1 *= 5
844 self.assertEqual(d1, Decimal('-75'))
845
846 def test_division(self):
847
848 d1 = Decimal('-5')
849 d2 = Decimal('2')
850
851 #two Decimals
852 self.assertEqual(d1/d2, Decimal('-2.5'))
853 self.assertEqual(d2/d1, Decimal('-0.4'))
854
855 #with other type, left
856 c = d1 / 4
857 self.assertEqual(c, Decimal('-1.25'))
858 self.assertEqual(type(c), type(d1))
859
860 #with other type, right
861 c = 4 / d1
862 self.assertEqual(c, Decimal('-0.8'))
863 self.assertEqual(type(c), type(d1))
864
865 #inline with decimal
866 d1 /= d2
867 self.assertEqual(d1, Decimal('-2.5'))
868
869 #inline with other type
870 d1 /= 4
871 self.assertEqual(d1, Decimal('-0.625'))
872
873 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000874
875 d1 = Decimal('5')
876 d2 = Decimal('2')
877
878 #two Decimals
879 self.assertEqual(d1//d2, Decimal('2'))
880 self.assertEqual(d2//d1, Decimal('0'))
881
882 #with other type, left
883 c = d1 // 4
884 self.assertEqual(c, Decimal('1'))
885 self.assertEqual(type(c), type(d1))
886
887 #with other type, right
888 c = 7 // d1
889 self.assertEqual(c, Decimal('1'))
890 self.assertEqual(type(c), type(d1))
891
892 #inline with decimal
893 d1 //= d2
894 self.assertEqual(d1, Decimal('2'))
895
896 #inline with other type
897 d1 //= 2
898 self.assertEqual(d1, Decimal('1'))
899
900 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000901
902 d1 = Decimal('5')
903 d2 = Decimal('2')
904
905 #two Decimals
906 self.assertEqual(d1**d2, Decimal('25'))
907 self.assertEqual(d2**d1, Decimal('32'))
908
909 #with other type, left
910 c = d1 ** 4
911 self.assertEqual(c, Decimal('625'))
912 self.assertEqual(type(c), type(d1))
913
914 #with other type, right
915 c = 7 ** d1
916 self.assertEqual(c, Decimal('16807'))
917 self.assertEqual(type(c), type(d1))
918
919 #inline with decimal
920 d1 **= d2
921 self.assertEqual(d1, Decimal('25'))
922
923 #inline with other type
924 d1 **= 4
925 self.assertEqual(d1, Decimal('390625'))
926
927 def test_module(self):
928
929 d1 = Decimal('5')
930 d2 = Decimal('2')
931
932 #two Decimals
933 self.assertEqual(d1%d2, Decimal('1'))
934 self.assertEqual(d2%d1, Decimal('2'))
935
936 #with other type, left
937 c = d1 % 4
938 self.assertEqual(c, Decimal('1'))
939 self.assertEqual(type(c), type(d1))
940
941 #with other type, right
942 c = 7 % d1
943 self.assertEqual(c, Decimal('2'))
944 self.assertEqual(type(c), type(d1))
945
946 #inline with decimal
947 d1 %= d2
948 self.assertEqual(d1, Decimal('1'))
949
950 #inline with other type
951 d1 %= 4
952 self.assertEqual(d1, Decimal('1'))
953
954 def test_floor_div_module(self):
955
956 d1 = Decimal('5')
957 d2 = Decimal('2')
958
959 #two Decimals
960 (p, q) = divmod(d1, d2)
961 self.assertEqual(p, Decimal('2'))
962 self.assertEqual(q, Decimal('1'))
963 self.assertEqual(type(p), type(d1))
964 self.assertEqual(type(q), type(d1))
965
966 #with other type, left
967 (p, q) = divmod(d1, 4)
968 self.assertEqual(p, Decimal('1'))
969 self.assertEqual(q, Decimal('1'))
970 self.assertEqual(type(p), type(d1))
971 self.assertEqual(type(q), type(d1))
972
973 #with other type, right
974 (p, q) = divmod(7, d1)
975 self.assertEqual(p, Decimal('1'))
976 self.assertEqual(q, Decimal('2'))
977 self.assertEqual(type(p), type(d1))
978 self.assertEqual(type(q), type(d1))
979
980 def test_unary_operators(self):
981 self.assertEqual(+Decimal(45), Decimal(+45)) # +
982 self.assertEqual(-Decimal(45), Decimal(-45)) # -
983 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
984
Mark Dickinson2fc92632008-02-06 22:10:50 +0000985 def test_nan_comparisons(self):
986 n = Decimal('NaN')
987 s = Decimal('sNaN')
988 i = Decimal('Inf')
989 f = Decimal('2')
990 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
991 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
992 self.assert_(x != y)
993 self.assert_(not (x == y))
994 self.assert_(not (x < y))
995 self.assert_(not (x <= y))
996 self.assert_(not (x > y))
997 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000998
999# The following are two functions used to test threading in the next class
1000
1001def thfunc1(cls):
1002 d1 = Decimal(1)
1003 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001004 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001005 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001006 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001007 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001008
Facundo Batistaee340e52008-05-02 17:39:00 +00001009 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1010 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001011 return
1012
1013def thfunc2(cls):
1014 d1 = Decimal(1)
1015 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001016 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001017 thiscontext = getcontext()
1018 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001019 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001020 cls.synchro.set()
1021 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001022
Facundo Batistaee340e52008-05-02 17:39:00 +00001023 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001024 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001025 return
1026
1027
1028class DecimalUseOfContextTest(unittest.TestCase):
1029 '''Unit tests for Use of Context cases in Decimal.'''
1030
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001031 try:
1032 import threading
1033 except ImportError:
1034 threading = None
1035
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001036 # Take care executing this test from IDLE, there's an issue in threading
1037 # that hangs IDLE and I couldn't find it
1038
1039 def test_threading(self):
1040 #Test the "threading isolation" of a Context.
1041
1042 self.synchro = threading.Event()
1043 self.finish1 = threading.Event()
1044 self.finish2 = threading.Event()
1045
1046 th1 = threading.Thread(target=thfunc1, args=(self,))
1047 th2 = threading.Thread(target=thfunc2, args=(self,))
1048
1049 th1.start()
1050 th2.start()
1051
1052 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001053 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001054 return
1055
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001056 if threading is None:
1057 del test_threading
1058
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001059
1060class DecimalUsabilityTest(unittest.TestCase):
1061 '''Unit tests for Usability cases of Decimal.'''
1062
1063 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001064
1065 da = Decimal('23.42')
1066 db = Decimal('23.42')
1067 dc = Decimal('45')
1068
1069 #two Decimals
1070 self.failUnless(dc > da)
1071 self.failUnless(dc >= da)
1072 self.failUnless(da < dc)
1073 self.failUnless(da <= dc)
1074 self.failUnless(da == db)
1075 self.failUnless(da != dc)
1076 self.failUnless(da <= db)
1077 self.failUnless(da >= db)
1078 self.assertEqual(cmp(dc,da), 1)
1079 self.assertEqual(cmp(da,dc), -1)
1080 self.assertEqual(cmp(da,db), 0)
1081
1082 #a Decimal and an int
1083 self.failUnless(dc > 23)
1084 self.failUnless(23 < dc)
1085 self.failUnless(dc == 45)
1086 self.assertEqual(cmp(dc,23), 1)
1087 self.assertEqual(cmp(23,dc), -1)
1088 self.assertEqual(cmp(dc,45), 0)
1089
1090 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001091 self.assertNotEqual(da, 'ugly')
1092 self.assertNotEqual(da, 32.7)
1093 self.assertNotEqual(da, object())
1094 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001095
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001096 # sortable
1097 a = map(Decimal, xrange(100))
1098 b = a[:]
1099 random.shuffle(a)
1100 a.sort()
1101 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001102
Facundo Batista353750c2007-09-13 18:13:15 +00001103 # with None
1104 self.assertFalse(Decimal(1) < None)
1105 self.assertTrue(Decimal(1) > None)
1106
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001107 def test_copy_and_deepcopy_methods(self):
1108 d = Decimal('43.24')
1109 c = copy.copy(d)
1110 self.assertEqual(id(c), id(d))
1111 dc = copy.deepcopy(d)
1112 self.assertEqual(id(dc), id(d))
1113
1114 def test_hash_method(self):
1115 #just that it's hashable
1116 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001117
1118 test_values = [Decimal(sign*(2**m + n))
1119 for m in [0, 14, 15, 16, 17, 30, 31,
1120 32, 33, 62, 63, 64, 65, 66]
1121 for n in range(-10, 10)
1122 for sign in [-1, 1]]
1123 test_values.extend([
1124 Decimal("-0"), # zeros
1125 Decimal("0.00"),
1126 Decimal("-0.000"),
1127 Decimal("0E10"),
1128 Decimal("-0E12"),
1129 Decimal("10.0"), # negative exponent
1130 Decimal("-23.00000"),
1131 Decimal("1230E100"), # positive exponent
1132 Decimal("-4.5678E50"),
1133 # a value for which hash(n) != hash(n % (2**64-1))
1134 # in Python pre-2.6
1135 Decimal(2**64 + 2**32 - 1),
1136 # selection of values which fail with the old (before
1137 # version 2.6) long.__hash__
1138 Decimal("1.634E100"),
1139 Decimal("90.697E100"),
1140 Decimal("188.83E100"),
1141 Decimal("1652.9E100"),
1142 Decimal("56531E100"),
1143 ])
1144
1145 # check that hash(d) == hash(int(d)) for integral values
1146 for value in test_values:
1147 self.assertEqual(hash(value), hash(int(value)))
1148
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001149 #the same hash that to an int
1150 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001151 self.assertRaises(TypeError, hash, Decimal('NaN'))
1152 self.assert_(hash(Decimal('Inf')))
1153 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001154
Facundo Batista52b25792008-01-08 12:25:20 +00001155 # check that the value of the hash doesn't depend on the
1156 # current context (issue #1757)
1157 c = getcontext()
1158 old_precision = c.prec
1159 x = Decimal("123456789.1")
1160
1161 c.prec = 6
1162 h1 = hash(x)
1163 c.prec = 10
1164 h2 = hash(x)
1165 c.prec = 16
1166 h3 = hash(x)
1167
1168 self.assertEqual(h1, h2)
1169 self.assertEqual(h1, h3)
1170 c.prec = old_precision
1171
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001172 def test_min_and_max_methods(self):
1173
1174 d1 = Decimal('15.32')
1175 d2 = Decimal('28.5')
1176 l1 = 15
1177 l2 = 28
1178
1179 #between Decimals
1180 self.failUnless(min(d1,d2) is d1)
1181 self.failUnless(min(d2,d1) is d1)
1182 self.failUnless(max(d1,d2) is d2)
1183 self.failUnless(max(d2,d1) is d2)
1184
1185 #between Decimal and long
1186 self.failUnless(min(d1,l2) is d1)
1187 self.failUnless(min(l2,d1) is d1)
1188 self.failUnless(max(l1,d2) is d2)
1189 self.failUnless(max(d2,l1) is d2)
1190
1191 def test_as_nonzero(self):
1192 #as false
1193 self.failIf(Decimal(0))
1194 #as true
1195 self.failUnless(Decimal('0.372'))
1196
1197 def test_tostring_methods(self):
1198 #Test str and repr methods.
1199
1200 d = Decimal('15.32')
1201 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001202 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001203
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001204 # result type of string methods should be str, not unicode
1205 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1206 u'-0.0E100', u'-NaN001', u'-Inf']
1207
1208 for u in unicode_inputs:
1209 d = Decimal(u)
1210 self.assertEqual(type(str(d)), str)
1211 self.assertEqual(type(repr(d)), str)
1212 self.assertEqual(type(d.to_eng_string()), str)
1213
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001214 def test_tonum_methods(self):
1215 #Test float, int and long methods.
1216
1217 d1 = Decimal('66')
1218 d2 = Decimal('15.32')
1219
1220 #int
1221 self.assertEqual(int(d1), 66)
1222 self.assertEqual(int(d2), 15)
1223
1224 #long
1225 self.assertEqual(long(d1), 66)
1226 self.assertEqual(long(d2), 15)
1227
1228 #float
1229 self.assertEqual(float(d1), 66)
1230 self.assertEqual(float(d2), 15.32)
1231
1232 def test_eval_round_trip(self):
1233
1234 #with zero
1235 d = Decimal( (0, (0,), 0) )
1236 self.assertEqual(d, eval(repr(d)))
1237
1238 #int
1239 d = Decimal( (1, (4, 5), 0) )
1240 self.assertEqual(d, eval(repr(d)))
1241
1242 #float
1243 d = Decimal( (0, (4, 5, 3, 4), -2) )
1244 self.assertEqual(d, eval(repr(d)))
1245
1246 #weird
1247 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1248 self.assertEqual(d, eval(repr(d)))
1249
1250 def test_as_tuple(self):
1251
1252 #with zero
1253 d = Decimal(0)
1254 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1255
1256 #int
1257 d = Decimal(-45)
1258 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1259
1260 #complicated string
1261 d = Decimal("-4.34913534E-17")
1262 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1263
1264 #inf
1265 d = Decimal("Infinity")
1266 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1267
Facundo Batista9b5e2312007-10-19 19:25:57 +00001268 #leading zeros in coefficient should be stripped
1269 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1270 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1271 d = Decimal( (1, (0, 0, 0), 37) )
1272 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1273 d = Decimal( (1, (), 37) )
1274 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1275
1276 #leading zeros in NaN diagnostic info should be stripped
1277 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1278 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1279 d = Decimal( (1, (0, 0, 0), 'N') )
1280 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1281 d = Decimal( (1, (), 'n') )
1282 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1283
1284 #coefficient in infinity should be ignored
1285 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1286 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1287 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1288 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1289
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001290 def test_immutability_operations(self):
1291 # Do operations and check that it didn't change change internal objects.
1292
1293 d1 = Decimal('-25e55')
1294 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001295 d2 = Decimal('33e+33')
1296 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001297
1298 def checkSameDec(operation, useOther=False):
1299 if useOther:
1300 eval("d1." + operation + "(d2)")
1301 self.assertEqual(d1._sign, b1._sign)
1302 self.assertEqual(d1._int, b1._int)
1303 self.assertEqual(d1._exp, b1._exp)
1304 self.assertEqual(d2._sign, b2._sign)
1305 self.assertEqual(d2._int, b2._int)
1306 self.assertEqual(d2._exp, b2._exp)
1307 else:
1308 eval("d1." + operation + "()")
1309 self.assertEqual(d1._sign, b1._sign)
1310 self.assertEqual(d1._int, b1._int)
1311 self.assertEqual(d1._exp, b1._exp)
1312 return
1313
1314 Decimal(d1)
1315 self.assertEqual(d1._sign, b1._sign)
1316 self.assertEqual(d1._int, b1._int)
1317 self.assertEqual(d1._exp, b1._exp)
1318
1319 checkSameDec("__abs__")
1320 checkSameDec("__add__", True)
1321 checkSameDec("__div__", True)
1322 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001323 checkSameDec("__eq__", True)
1324 checkSameDec("__ne__", True)
1325 checkSameDec("__le__", True)
1326 checkSameDec("__lt__", True)
1327 checkSameDec("__ge__", True)
1328 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001329 checkSameDec("__float__")
1330 checkSameDec("__floordiv__", True)
1331 checkSameDec("__hash__")
1332 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001333 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001334 checkSameDec("__long__")
1335 checkSameDec("__mod__", True)
1336 checkSameDec("__mul__", True)
1337 checkSameDec("__neg__")
1338 checkSameDec("__nonzero__")
1339 checkSameDec("__pos__")
1340 checkSameDec("__pow__", True)
1341 checkSameDec("__radd__", True)
1342 checkSameDec("__rdiv__", True)
1343 checkSameDec("__rdivmod__", True)
1344 checkSameDec("__repr__")
1345 checkSameDec("__rfloordiv__", True)
1346 checkSameDec("__rmod__", True)
1347 checkSameDec("__rmul__", True)
1348 checkSameDec("__rpow__", True)
1349 checkSameDec("__rsub__", True)
1350 checkSameDec("__str__")
1351 checkSameDec("__sub__", True)
1352 checkSameDec("__truediv__", True)
1353 checkSameDec("adjusted")
1354 checkSameDec("as_tuple")
1355 checkSameDec("compare", True)
1356 checkSameDec("max", True)
1357 checkSameDec("min", True)
1358 checkSameDec("normalize")
1359 checkSameDec("quantize", True)
1360 checkSameDec("remainder_near", True)
1361 checkSameDec("same_quantum", True)
1362 checkSameDec("sqrt")
1363 checkSameDec("to_eng_string")
1364 checkSameDec("to_integral")
1365
Facundo Batista6c398da2007-09-17 17:30:13 +00001366 def test_subclassing(self):
1367 # Different behaviours when subclassing Decimal
1368
1369 class MyDecimal(Decimal):
1370 pass
1371
1372 d1 = MyDecimal(1)
1373 d2 = MyDecimal(2)
1374 d = d1 + d2
1375 self.assertTrue(type(d) is Decimal)
1376
1377 d = d1.max(d2)
1378 self.assertTrue(type(d) is Decimal)
1379
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001380 def test_implicit_context(self):
1381 # Check results when context given implicitly. (Issue 2478)
1382 c = getcontext()
1383 self.assertEqual(str(Decimal(0).sqrt()),
1384 str(c.sqrt(Decimal(0))))
1385
Mark Dickinsond8a2e2b2009-10-29 12:16:15 +00001386 def test_conversions_from_int(self):
1387 # Check that methods taking a second Decimal argument will
1388 # always accept an integer in place of a Decimal.
1389 self.assertEqual(Decimal(4).compare(3),
1390 Decimal(4).compare(Decimal(3)))
1391 self.assertEqual(Decimal(4).compare_signal(3),
1392 Decimal(4).compare_signal(Decimal(3)))
1393 self.assertEqual(Decimal(4).compare_total(3),
1394 Decimal(4).compare_total(Decimal(3)))
1395 self.assertEqual(Decimal(4).compare_total_mag(3),
1396 Decimal(4).compare_total_mag(Decimal(3)))
1397 self.assertEqual(Decimal(10101).logical_and(1001),
1398 Decimal(10101).logical_and(Decimal(1001)))
1399 self.assertEqual(Decimal(10101).logical_or(1001),
1400 Decimal(10101).logical_or(Decimal(1001)))
1401 self.assertEqual(Decimal(10101).logical_xor(1001),
1402 Decimal(10101).logical_xor(Decimal(1001)))
1403 self.assertEqual(Decimal(567).max(123),
1404 Decimal(567).max(Decimal(123)))
1405 self.assertEqual(Decimal(567).max_mag(123),
1406 Decimal(567).max_mag(Decimal(123)))
1407 self.assertEqual(Decimal(567).min(123),
1408 Decimal(567).min(Decimal(123)))
1409 self.assertEqual(Decimal(567).min_mag(123),
1410 Decimal(567).min_mag(Decimal(123)))
1411 self.assertEqual(Decimal(567).next_toward(123),
1412 Decimal(567).next_toward(Decimal(123)))
1413 self.assertEqual(Decimal(1234).quantize(100),
1414 Decimal(1234).quantize(Decimal(100)))
1415 self.assertEqual(Decimal(768).remainder_near(1234),
1416 Decimal(768).remainder_near(Decimal(1234)))
1417 self.assertEqual(Decimal(123).rotate(1),
1418 Decimal(123).rotate(Decimal(1)))
1419 self.assertEqual(Decimal(1234).same_quantum(1000),
1420 Decimal(1234).same_quantum(Decimal(1000)))
1421 self.assertEqual(Decimal('9.123').scaleb(-100),
1422 Decimal('9.123').scaleb(Decimal(-100)))
1423 self.assertEqual(Decimal(456).shift(-1),
1424 Decimal(456).shift(Decimal(-1)))
1425
1426 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1427 Decimal(-12).fma(Decimal(45), Decimal(67)))
1428 self.assertEqual(Decimal(-12).fma(45, 67),
1429 Decimal(-12).fma(Decimal(45), Decimal(67)))
1430 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1431 Decimal(-12).fma(Decimal(45), Decimal(67)))
1432
Facundo Batista6c398da2007-09-17 17:30:13 +00001433
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001434class DecimalPythonAPItests(unittest.TestCase):
1435
Raymond Hettinger45fd4762009-02-03 03:42:07 +00001436 def test_abc(self):
1437 self.assert_(issubclass(Decimal, numbers.Number))
1438 self.assert_(not issubclass(Decimal, numbers.Real))
1439 self.assert_(isinstance(Decimal(0), numbers.Number))
1440 self.assert_(not isinstance(Decimal(0), numbers.Real))
1441
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001442 def test_pickle(self):
1443 d = Decimal('-3.141590000')
1444 p = pickle.dumps(d)
1445 e = pickle.loads(p)
1446 self.assertEqual(d, e)
1447
Raymond Hettinger5548be22004-07-05 18:49:38 +00001448 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001449 for x in range(-250, 250):
1450 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001451 # should work the same as for floats
1452 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001453 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001454 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001455 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001456 self.assertEqual(Decimal(int(d)), r)
1457
Mark Dickinsonc05b7892009-09-08 19:22:18 +00001458 self.assertRaises(ValueError, int, Decimal('-nan'))
1459 self.assertRaises(ValueError, int, Decimal('snan'))
1460 self.assertRaises(OverflowError, int, Decimal('inf'))
1461 self.assertRaises(OverflowError, int, Decimal('-inf'))
1462
1463 self.assertRaises(ValueError, long, Decimal('-nan'))
1464 self.assertRaises(ValueError, long, Decimal('snan'))
1465 self.assertRaises(OverflowError, long, Decimal('inf'))
1466 self.assertRaises(OverflowError, long, Decimal('-inf'))
1467
Raymond Hettinger5a053642008-01-24 19:05:29 +00001468 def test_trunc(self):
1469 for x in range(-250, 250):
1470 s = '%0.2f' % (x / 100.0)
1471 # should work the same as for floats
1472 self.assertEqual(int(Decimal(s)), int(float(s)))
1473 # should work the same as to_integral in the ROUND_DOWN mode
1474 d = Decimal(s)
1475 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001476 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001477
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001478class ContextAPItests(unittest.TestCase):
1479
1480 def test_pickle(self):
1481 c = Context()
1482 e = pickle.loads(pickle.dumps(c))
1483 for k in vars(c):
1484 v1 = vars(c)[k]
1485 v2 = vars(e)[k]
1486 self.assertEqual(v1, v2)
1487
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001488 def test_equality_with_other_types(self):
1489 self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1490 self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1491
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001492 def test_copy(self):
1493 # All copies should be deep
1494 c = Context()
1495 d = c.copy()
1496 self.assertNotEqual(id(c), id(d))
1497 self.assertNotEqual(id(c.flags), id(d.flags))
1498 self.assertNotEqual(id(c.traps), id(d.traps))
1499
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001500class WithStatementTest(unittest.TestCase):
1501 # Can't do these as docstrings until Python 2.6
1502 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001503
1504 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001505 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001506 orig_ctx = getcontext()
1507 with localcontext() as enter_ctx:
1508 set_ctx = getcontext()
1509 final_ctx = getcontext()
1510 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1511 self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
1512 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1513
1514 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001515 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001516 orig_ctx = getcontext()
1517 new_ctx = Context(prec=42)
1518 with localcontext(new_ctx) as enter_ctx:
1519 set_ctx = getcontext()
1520 final_ctx = getcontext()
1521 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1522 self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1523 self.assert_(new_ctx is not set_ctx, 'did not copy the context')
1524 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1525
Facundo Batista353750c2007-09-13 18:13:15 +00001526class ContextFlags(unittest.TestCase):
1527 def test_flags_irrelevant(self):
1528 # check that the result (numeric result + flags raised) of an
1529 # arithmetic operation doesn't depend on the current flags
1530
1531 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1532 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1533
1534 # operations that raise various flags, in the form (function, arglist)
1535 operations = [
1536 (context._apply, [Decimal("100E-1000000009")]),
1537 (context.sqrt, [Decimal(2)]),
1538 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1539 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1540 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1541 ]
1542
1543 # try various flags individually, then a whole lot at once
1544 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1545 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1546
1547 for fn, args in operations:
1548 # find answer and flags raised using a clean context
1549 context.clear_flags()
1550 ans = fn(*args)
1551 flags = [k for k, v in context.flags.items() if v]
1552
1553 for extra_flags in flagsets:
1554 # set flags, before calling operation
1555 context.clear_flags()
1556 for flag in extra_flags:
1557 context._raise_error(flag)
1558 new_ans = fn(*args)
1559
1560 # flags that we expect to be set after the operation
1561 expected_flags = list(flags)
1562 for flag in extra_flags:
1563 if flag not in expected_flags:
1564 expected_flags.append(flag)
1565 expected_flags.sort()
1566
1567 # flags we actually got
1568 new_flags = [k for k,v in context.flags.items() if v]
1569 new_flags.sort()
1570
1571 self.assertEqual(ans, new_ans,
1572 "operation produces different answers depending on flags set: " +
1573 "expected %s, got %s." % (ans, new_ans))
1574 self.assertEqual(new_flags, expected_flags,
1575 "operation raises different flags depending on flags set: " +
1576 "expected %s, got %s" % (expected_flags, new_flags))
1577
1578def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001579 """ Execute the tests.
1580
Raymond Hettingered20ad82004-09-04 20:09:13 +00001581 Runs all arithmetic tests if arith is True or if the "decimal" resource
1582 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001583 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001584
Neal Norwitzce4a9c92006-04-09 08:36:46 +00001585 init()
Facundo Batista353750c2007-09-13 18:13:15 +00001586 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001587 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00001588 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001589
Facundo Batista353750c2007-09-13 18:13:15 +00001590 if todo_tests is None:
1591 test_classes = [
1592 DecimalExplicitConstructionTest,
1593 DecimalImplicitConstructionTest,
1594 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00001595 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00001596 DecimalUseOfContextTest,
1597 DecimalUsabilityTest,
1598 DecimalPythonAPItests,
1599 ContextAPItests,
1600 DecimalTest,
1601 WithStatementTest,
1602 ContextFlags
1603 ]
1604 else:
1605 test_classes = [DecimalTest]
1606
1607 # Dynamically build custom test definition for each file in the test
1608 # directory and add the definitions to the DecimalTest class. This
1609 # procedure insures that new files do not get skipped.
1610 for filename in os.listdir(directory):
1611 if '.decTest' not in filename or filename.startswith("."):
1612 continue
1613 head, tail = filename.split('.')
1614 if todo_tests is not None and head not in todo_tests:
1615 continue
1616 tester = lambda self, f=filename: self.eval_file(directory + f)
1617 setattr(DecimalTest, 'test_' + head, tester)
1618 del filename, head, tail, tester
1619
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001620
Tim Peters46cc7022006-03-31 04:11:16 +00001621 try:
1622 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00001623 if todo_tests is None:
1624 import decimal as DecimalModule
1625 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00001626 finally:
1627 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001628
1629if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00001630 import optparse
1631 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1632 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1633 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1634 (opt, args) = p.parse_args()
1635
1636 if opt.skip:
1637 test_main(arith=False, verbose=True)
1638 elif args:
1639 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001640 else:
Facundo Batista353750c2007-09-13 18:13:15 +00001641 test_main(arith=True, verbose=True)