blob: b78041b3fb782e21fe9cdc2b15c522278b68776b [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
43Signals = getcontext().flags.keys()
44
Tim Peters46cc7022006-03-31 04:11:16 +000045# Tests are built around these assumed context defaults.
46# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000047def init():
48 global ORIGINAL_CONTEXT
49 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000050 DefaultTestContext = Context(
51 prec = 9,
52 rounding = ROUND_HALF_EVEN,
53 traps = dict.fromkeys(Signals, 0)
54 )
55 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000056
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000057TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000058if __name__ == '__main__':
59 file = sys.argv[0]
60else:
61 file = __file__
62testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000063directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000064
Raymond Hettinger267b8682005-03-27 10:47:39 +000065skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000066
Mark Dickinson25567ef2009-10-27 17:02:46 +000067# list of individual .decTest test ids that correspond to tests that
68# we're skipping for one reason or another.
69skipped_test_ids = [
70 'scbx164', # skipping apparently implementation-specific scaleb
71 'scbx165', # tests, pending clarification of scaleb rules.
72]
73
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000074# Make sure it actually raises errors when not expected and caught in flags
75# Slower, since it runs some things several times.
76EXTENDEDERRORTEST = False
77
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000079ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000080 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000081 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000082 'division_impossible' : InvalidOperation,
83 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000085 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000086 'invalid_operation' : InvalidOperation,
87 'overflow' : Overflow,
88 'rounded' : Rounded,
89 'subnormal' : Subnormal,
90 'underflow' : Underflow}
91
92
93def Nonfunction(*args):
94 """Doesn't do anything."""
95 return None
96
97RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
98 'down' : ROUND_DOWN,
99 'floor' : ROUND_FLOOR,
100 'half_down' : ROUND_HALF_DOWN,
101 'half_even' : ROUND_HALF_EVEN,
102 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000103 'up' : ROUND_UP,
104 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000105
106# Name adapter to be able to change the Decimal and Context
107# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000108nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000110 'class':'number_class',
111 'comparesig':'compare_signal',
112 'comparetotal':'compare_total',
113 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000114 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000115 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000116 'copynegate':'copy_negate',
117 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000118 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000119 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000120 'iscanonical':'is_canonical',
121 'isfinite':'is_finite',
122 'isinfinite':'is_infinite',
123 'isnan':'is_nan',
124 'isnormal':'is_normal',
125 'isqnan':'is_qnan',
126 'issigned':'is_signed',
127 'issnan':'is_snan',
128 'issubnormal':'is_subnormal',
129 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000130 'maxmag':'max_mag',
131 'minmag':'min_mag',
132 'nextminus':'next_minus',
133 'nextplus':'next_plus',
134 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000135 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000136 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000137 'remaindernear':'remainder_near',
138 'samequantum':'same_quantum',
139 'squareroot':'sqrt',
140 'toeng':'to_eng_string',
141 'tointegral':'to_integral_value',
142 'tointegralx':'to_integral_exact',
143 'tosci':'to_sci_string',
144 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000145 }
146
Facundo Batista1a191df2007-10-02 17:01:24 +0000147# The following functions return True/False rather than a Decimal instance
148
149LOGICAL_FUNCTIONS = (
150 'is_canonical',
151 'is_finite',
152 'is_infinite',
153 'is_nan',
154 'is_normal',
155 'is_qnan',
156 'is_signed',
157 'is_snan',
158 'is_subnormal',
159 'is_zero',
160 'same_quantum',
161 )
162
Facundo Batista353750c2007-09-13 18:13:15 +0000163# For some operations (currently exp, ln, log10, power), the decNumber
164# reference implementation imposes additional restrictions on the
165# context and operands. These restrictions are not part of the
166# specification; however, the effect of these restrictions does show
167# up in some of the testcases. We skip testcases that violate these
168# restrictions, since Decimal behaves differently from decNumber for
169# these testcases so these testcases would otherwise fail.
170
171decNumberRestricted = ('power', 'ln', 'log10', 'exp')
172DEC_MAX_MATH = 999999
173def outside_decNumber_bounds(v, context):
174 if (context.prec > DEC_MAX_MATH or
175 context.Emax > DEC_MAX_MATH or
176 -context.Emin > DEC_MAX_MATH):
177 return True
178 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000179 v.adjusted() > DEC_MAX_MATH or
180 v.adjusted() < 1-2*DEC_MAX_MATH):
181 return True
182 return False
183
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184class DecimalTest(unittest.TestCase):
185 """Class which tests the Decimal class against the test cases.
186
187 Changed for unittest.
188 """
189 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000191 self.ignore_list = ['#']
192 # Basically, a # means return NaN InvalidOperation.
193 # Different from a sNaN in trim
194
195 self.ChangeDict = {'precision' : self.change_precision,
196 'rounding' : self.change_rounding_method,
197 'maxexponent' : self.change_max_exponent,
198 'minexponent' : self.change_min_exponent,
199 'clamp' : self.change_clamp}
200
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000201 def eval_file(self, file):
202 global skip_expected
203 if skip_expected:
204 raise TestSkipped
205 return
206 for line in open(file).xreadlines():
207 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000208 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000209 try:
210 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 except DecimalException, exception:
212 #Exception raised where there shoudn't have been one.
213 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
214
215 return
216
217 def eval_line(self, s):
218 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
219 s = (s.split('->')[0] + '->' +
220 s.split('->')[1].split('--')[0]).strip()
221 else:
222 s = s.split('--')[0].strip()
223
224 for ignore in self.ignore_list:
225 if s.find(ignore) >= 0:
226 #print s.split()[0], 'NotImplemented--', ignore
227 return
228 if not s:
229 return
230 elif ':' in s:
231 return self.eval_directive(s)
232 else:
233 return self.eval_equation(s)
234
235 def eval_directive(self, s):
236 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
237 if funct == 'rounding':
238 value = RoundingDict[value]
239 else:
240 try:
241 value = int(value)
242 except ValueError:
243 pass
244
245 funct = self.ChangeDict.get(funct, Nonfunction)
246 funct(value)
247
248 def eval_equation(self, s):
249 #global DEFAULT_PRECISION
250 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000251
252 if not TEST_ALL and random.random() < 0.90:
253 return
254
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000255 try:
256 Sides = s.split('->')
257 L = Sides[0].strip().split()
258 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000259 if DEBUG:
260 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000261 funct = L[1].lower()
262 valstemp = L[2:]
263 L = Sides[1].strip().split()
264 ans = L[0]
265 exceptions = L[1:]
266 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000267 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000268 def FixQuotes(val):
269 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
270 val = val.replace("'", '').replace('"', '')
271 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
272 return val
Mark Dickinson25567ef2009-10-27 17:02:46 +0000273
274 if id in skipped_test_ids:
275 return
276
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 fname = nameAdapter.get(funct, funct)
278 if fname == 'rescale':
279 return
280 funct = getattr(self.context, fname)
281 vals = []
282 conglomerate = ''
283 quote = 0
284 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
285
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000286 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000287 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000289 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000290 for i, val in enumerate(valstemp):
291 if val.count("'") % 2 == 1:
292 quote = 1 - quote
293 if quote:
294 conglomerate = conglomerate + ' ' + val
295 continue
296 else:
297 val = conglomerate + val
298 conglomerate = ''
299 v = FixQuotes(val)
300 if fname in ('to_sci_string', 'to_eng_string'):
301 if EXTENDEDERRORTEST:
302 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000303 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304 try:
305 funct(self.context.create_decimal(v))
306 except error:
307 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000308 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 self.fail("Raised %s in %s when %s disabled" % \
310 (e, s, error))
311 else:
312 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000313 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000314 v = self.context.create_decimal(v)
315 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000316 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000317 vals.append(v)
318
319 ans = FixQuotes(ans)
320
Facundo Batista353750c2007-09-13 18:13:15 +0000321 # skip tests that are related to bounds imposed in the decNumber
322 # reference implementation
323 if fname in decNumberRestricted:
324 if fname == 'power':
325 if not (vals[1]._isinteger() and
326 -1999999997 <= vals[1] <= 999999999):
327 if outside_decNumber_bounds(vals[0], self.context) or \
328 outside_decNumber_bounds(vals[1], self.context):
329 #print "Skipping test %s" % s
330 return
331 else:
332 if outside_decNumber_bounds(vals[0], self.context):
333 #print "Skipping test %s" % s
334 return
335
336
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 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
Facundo Batista353750c2007-09-13 18:13:15 +0000350 if DEBUG:
351 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000352 try:
353 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000354 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000356 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 self.fail("Raised %s in %s" % (error, s))
358 except: #Catch any error long enough to state the test case.
359 print "ERROR:", s
360 raise
361
362 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000363 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364
365 myexceptions.sort()
366 theirexceptions.sort()
367
368 self.assertEqual(result, ans,
369 'Incorrect answer for ' + s + ' -- got ' + result)
370 self.assertEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000371 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372 return
373
374 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000375 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 def change_precision(self, prec):
378 self.context.prec = prec
379 def change_rounding_method(self, rounding):
380 self.context.rounding = rounding
381 def change_min_exponent(self, exp):
382 self.context.Emin = exp
383 def change_max_exponent(self, exp):
384 self.context.Emax = exp
385 def change_clamp(self, clamp):
386 self.context._clamp = clamp
387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388
389
390# The following classes test the behaviour of Decimal according to PEP 327
391
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392class DecimalExplicitConstructionTest(unittest.TestCase):
393 '''Unit tests for Explicit Construction cases of Decimal.'''
394
395 def test_explicit_empty(self):
396 self.assertEqual(Decimal(), Decimal("0"))
397
398 def test_explicit_from_None(self):
399 self.assertRaises(TypeError, Decimal, None)
400
401 def test_explicit_from_int(self):
402
403 #positive
404 d = Decimal(45)
405 self.assertEqual(str(d), '45')
406
407 #very large positive
408 d = Decimal(500000123)
409 self.assertEqual(str(d), '500000123')
410
411 #negative
412 d = Decimal(-45)
413 self.assertEqual(str(d), '-45')
414
415 #zero
416 d = Decimal(0)
417 self.assertEqual(str(d), '0')
418
419 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000420
421 #empty
422 self.assertEqual(str(Decimal('')), 'NaN')
423
424 #int
425 self.assertEqual(str(Decimal('45')), '45')
426
427 #float
428 self.assertEqual(str(Decimal('45.34')), '45.34')
429
430 #engineer notation
431 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
432
433 #just not a number
434 self.assertEqual(str(Decimal('ugly')), 'NaN')
435
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000436 #leading and trailing whitespace permitted
437 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
438 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
439
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000440 #unicode strings should be permitted
441 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
442 self.assertEqual(str(Decimal(u'45')), '45')
443 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
444 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
445
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446 def test_explicit_from_tuples(self):
447
448 #zero
449 d = Decimal( (0, (0,), 0) )
450 self.assertEqual(str(d), '0')
451
452 #int
453 d = Decimal( (1, (4, 5), 0) )
454 self.assertEqual(str(d), '-45')
455
456 #float
457 d = Decimal( (0, (4, 5, 3, 4), -2) )
458 self.assertEqual(str(d), '45.34')
459
460 #weird
461 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
462 self.assertEqual(str(d), '-4.34913534E-17')
463
464 #wrong number of items
465 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
466
467 #bad sign
468 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000469 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
470 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000471
472 #bad exp
473 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000474 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
475 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000476
477 #bad coefficients
478 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
479 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000480 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000481 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000482
483 def test_explicit_from_Decimal(self):
484
485 #positive
486 d = Decimal(45)
487 e = Decimal(d)
488 self.assertEqual(str(e), '45')
489 self.assertNotEqual(id(d), id(e))
490
491 #very large positive
492 d = Decimal(500000123)
493 e = Decimal(d)
494 self.assertEqual(str(e), '500000123')
495 self.assertNotEqual(id(d), id(e))
496
497 #negative
498 d = Decimal(-45)
499 e = Decimal(d)
500 self.assertEqual(str(e), '-45')
501 self.assertNotEqual(id(d), id(e))
502
503 #zero
504 d = Decimal(0)
505 e = Decimal(d)
506 self.assertEqual(str(e), '0')
507 self.assertNotEqual(id(d), id(e))
508
509 def test_explicit_context_create_decimal(self):
510
511 nc = copy.copy(getcontext())
512 nc.prec = 3
513
514 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000515 d = Decimal()
516 self.assertEqual(str(d), '0')
517 d = nc.create_decimal()
518 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000519
520 # from None
521 self.assertRaises(TypeError, nc.create_decimal, None)
522
523 # from int
524 d = nc.create_decimal(456)
525 self.failUnless(isinstance(d, Decimal))
526 self.assertEqual(nc.create_decimal(45678),
527 nc.create_decimal('457E+2'))
528
529 # from string
530 d = Decimal('456789')
531 self.assertEqual(str(d), '456789')
532 d = nc.create_decimal('456789')
533 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000534 # leading and trailing whitespace should result in a NaN;
535 # spaces are already checked in Cowlishaw's test-suite, so
536 # here we just check that a trailing newline results in a NaN
537 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538
539 # from tuples
540 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
541 self.assertEqual(str(d), '-4.34913534E-17')
542 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
543 self.assertEqual(str(d), '-4.35E-17')
544
545 # from Decimal
546 prevdec = Decimal(500000123)
547 d = Decimal(prevdec)
548 self.assertEqual(str(d), '500000123')
549 d = nc.create_decimal(prevdec)
550 self.assertEqual(str(d), '5.00E+8')
551
Mark Dickinson9a6e6452009-08-02 11:01:01 +0000552 def test_unicode_digits(self):
553 test_values = {
554 u'\uff11': '1',
555 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
556 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
557 }
558 for input, expected in test_values.items():
559 self.assertEqual(str(Decimal(input)), expected)
560
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000561
562class DecimalImplicitConstructionTest(unittest.TestCase):
563 '''Unit tests for Implicit Construction cases of Decimal.'''
564
565 def test_implicit_from_None(self):
566 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
567
568 def test_implicit_from_int(self):
569 #normal
570 self.assertEqual(str(Decimal(5) + 45), '50')
571 #exceeding precision
572 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
573
574 def test_implicit_from_string(self):
575 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
576
577 def test_implicit_from_float(self):
578 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
579
580 def test_implicit_from_Decimal(self):
581 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
582
Raymond Hettinger267b8682005-03-27 10:47:39 +0000583 def test_rop(self):
584 # Allow other classes to be trained to interact with Decimals
585 class E:
586 def __divmod__(self, other):
587 return 'divmod ' + str(other)
588 def __rdivmod__(self, other):
589 return str(other) + ' rdivmod'
590 def __lt__(self, other):
591 return 'lt ' + str(other)
592 def __gt__(self, other):
593 return 'gt ' + str(other)
594 def __le__(self, other):
595 return 'le ' + str(other)
596 def __ge__(self, other):
597 return 'ge ' + str(other)
598 def __eq__(self, other):
599 return 'eq ' + str(other)
600 def __ne__(self, other):
601 return 'ne ' + str(other)
602
603 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
604 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
605 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
606 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
607 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
608 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
609 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
610 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
611
612 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000613 oplist = [
614 ('+', '__add__', '__radd__'),
615 ('-', '__sub__', '__rsub__'),
616 ('*', '__mul__', '__rmul__'),
617 ('%', '__mod__', '__rmod__'),
618 ('//', '__floordiv__', '__rfloordiv__'),
619 ('**', '__pow__', '__rpow__')
620 ]
621 if 1/2 == 0:
622 # testing with classic division, so add __div__
623 oplist.append(('/', '__div__', '__rdiv__'))
624 else:
625 # testing with -Qnew, so add __truediv__
626 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000627
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000628 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000629 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
630 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
631 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
632 'str' + lop + '10')
633 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
634 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000635
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000636class DecimalFormatTest(unittest.TestCase):
637 '''Unit tests for the format function.'''
638 def test_formatting(self):
639 # triples giving a format, a Decimal, and the expected result
640 test_values = [
641 ('e', '0E-15', '0e-15'),
642 ('e', '2.3E-15', '2.3e-15'),
643 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
644 ('e', '2.30000E-15', '2.30000e-15'),
645 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
646 ('e', '1.5', '1.5e+0'),
647 ('e', '0.15', '1.5e-1'),
648 ('e', '0.015', '1.5e-2'),
649 ('e', '0.0000000000015', '1.5e-12'),
650 ('e', '15.0', '1.50e+1'),
651 ('e', '-15', '-1.5e+1'),
652 ('e', '0', '0e+0'),
653 ('e', '0E1', '0e+1'),
654 ('e', '0.0', '0e-1'),
655 ('e', '0.00', '0e-2'),
656 ('.6e', '0E-15', '0.000000e-9'),
657 ('.6e', '0', '0.000000e+6'),
658 ('.6e', '9.999999', '9.999999e+0'),
659 ('.6e', '9.9999999', '1.000000e+1'),
660 ('.6e', '-1.23e5', '-1.230000e+5'),
661 ('.6e', '1.23456789e-3', '1.234568e-3'),
662 ('f', '0', '0'),
663 ('f', '0.0', '0.0'),
664 ('f', '0E-2', '0.00'),
665 ('f', '0.00E-8', '0.0000000000'),
666 ('f', '0E1', '0'), # loses exponent information
667 ('f', '3.2E1', '32'),
668 ('f', '3.2E2', '320'),
669 ('f', '3.20E2', '320'),
670 ('f', '3.200E2', '320.0'),
671 ('f', '3.2E-6', '0.0000032'),
672 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
673 ('.6f', '0E1', '0.000000'),
674 ('.6f', '0', '0.000000'),
675 ('.0f', '0', '0'), # no decimal point
676 ('.0f', '0e-2', '0'),
677 ('.0f', '3.14159265', '3'),
678 ('.1f', '3.14159265', '3.1'),
679 ('.4f', '3.14159265', '3.1416'),
680 ('.6f', '3.14159265', '3.141593'),
681 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
682 ('.8f', '3.14159265', '3.14159265'),
683 ('.9f', '3.14159265', '3.141592650'),
684
685 ('g', '0', '0'),
686 ('g', '0.0', '0.0'),
687 ('g', '0E1', '0e+1'),
688 ('G', '0E1', '0E+1'),
689 ('g', '0E-5', '0.00000'),
690 ('g', '0E-6', '0.000000'),
691 ('g', '0E-7', '0e-7'),
692 ('g', '-0E2', '-0e+2'),
693 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
694 ('.1g', '3.14159265', '3'),
695 ('.2g', '3.14159265', '3.1'),
696 ('.5g', '3.14159265', '3.1416'),
697 ('.7g', '3.14159265', '3.141593'),
698 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
699 ('.9g', '3.14159265', '3.14159265'),
700 ('.10g', '3.14159265', '3.14159265'), # don't pad
701
702 ('%', '0E1', '0%'),
703 ('%', '0E0', '0%'),
704 ('%', '0E-1', '0%'),
705 ('%', '0E-2', '0%'),
706 ('%', '0E-3', '0.0%'),
707 ('%', '0E-4', '0.00%'),
708
709 ('.3%', '0', '0.000%'), # all zeros treated equally
710 ('.3%', '0E10', '0.000%'),
711 ('.3%', '0E-10', '0.000%'),
712 ('.3%', '2.34', '234.000%'),
713 ('.3%', '1.234567', '123.457%'),
714 ('.0%', '1.23', '123%'),
715
716 ('e', 'NaN', 'NaN'),
717 ('f', '-NaN123', '-NaN123'),
718 ('+g', 'NaN456', '+NaN456'),
719 ('.3e', 'Inf', 'Infinity'),
720 ('.16f', '-Inf', '-Infinity'),
721 ('.0g', '-sNaN', '-sNaN'),
722
723 ('', '1.00', '1.00'),
Mark Dickinson71416822009-03-17 18:07:41 +0000724
725 # check alignment
726 ('<6', '123', '123 '),
727 ('>6', '123', ' 123'),
728 ('^6', '123', ' 123 '),
729 ('=+6', '123', '+ 123'),
Mark Dickinsonc3c112d2009-09-07 16:19:35 +0000730
731 # issue 6850
732 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000733 ]
734 for fmt, d, result in test_values:
735 self.assertEqual(format(Decimal(d), fmt), result)
736
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000737class DecimalArithmeticOperatorsTest(unittest.TestCase):
738 '''Unit tests for all arithmetic operators, binary and unary.'''
739
740 def test_addition(self):
741
742 d1 = Decimal('-11.1')
743 d2 = Decimal('22.2')
744
745 #two Decimals
746 self.assertEqual(d1+d2, Decimal('11.1'))
747 self.assertEqual(d2+d1, Decimal('11.1'))
748
749 #with other type, left
750 c = d1 + 5
751 self.assertEqual(c, Decimal('-6.1'))
752 self.assertEqual(type(c), type(d1))
753
754 #with other type, right
755 c = 5 + d1
756 self.assertEqual(c, Decimal('-6.1'))
757 self.assertEqual(type(c), type(d1))
758
759 #inline with decimal
760 d1 += d2
761 self.assertEqual(d1, Decimal('11.1'))
762
763 #inline with other type
764 d1 += 5
765 self.assertEqual(d1, Decimal('16.1'))
766
767 def test_subtraction(self):
768
769 d1 = Decimal('-11.1')
770 d2 = Decimal('22.2')
771
772 #two Decimals
773 self.assertEqual(d1-d2, Decimal('-33.3'))
774 self.assertEqual(d2-d1, Decimal('33.3'))
775
776 #with other type, left
777 c = d1 - 5
778 self.assertEqual(c, Decimal('-16.1'))
779 self.assertEqual(type(c), type(d1))
780
781 #with other type, right
782 c = 5 - d1
783 self.assertEqual(c, Decimal('16.1'))
784 self.assertEqual(type(c), type(d1))
785
786 #inline with decimal
787 d1 -= d2
788 self.assertEqual(d1, Decimal('-33.3'))
789
790 #inline with other type
791 d1 -= 5
792 self.assertEqual(d1, Decimal('-38.3'))
793
794 def test_multiplication(self):
795
796 d1 = Decimal('-5')
797 d2 = Decimal('3')
798
799 #two Decimals
800 self.assertEqual(d1*d2, Decimal('-15'))
801 self.assertEqual(d2*d1, Decimal('-15'))
802
803 #with other type, left
804 c = d1 * 5
805 self.assertEqual(c, Decimal('-25'))
806 self.assertEqual(type(c), type(d1))
807
808 #with other type, right
809 c = 5 * d1
810 self.assertEqual(c, Decimal('-25'))
811 self.assertEqual(type(c), type(d1))
812
813 #inline with decimal
814 d1 *= d2
815 self.assertEqual(d1, Decimal('-15'))
816
817 #inline with other type
818 d1 *= 5
819 self.assertEqual(d1, Decimal('-75'))
820
821 def test_division(self):
822
823 d1 = Decimal('-5')
824 d2 = Decimal('2')
825
826 #two Decimals
827 self.assertEqual(d1/d2, Decimal('-2.5'))
828 self.assertEqual(d2/d1, Decimal('-0.4'))
829
830 #with other type, left
831 c = d1 / 4
832 self.assertEqual(c, Decimal('-1.25'))
833 self.assertEqual(type(c), type(d1))
834
835 #with other type, right
836 c = 4 / d1
837 self.assertEqual(c, Decimal('-0.8'))
838 self.assertEqual(type(c), type(d1))
839
840 #inline with decimal
841 d1 /= d2
842 self.assertEqual(d1, Decimal('-2.5'))
843
844 #inline with other type
845 d1 /= 4
846 self.assertEqual(d1, Decimal('-0.625'))
847
848 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000849
850 d1 = Decimal('5')
851 d2 = Decimal('2')
852
853 #two Decimals
854 self.assertEqual(d1//d2, Decimal('2'))
855 self.assertEqual(d2//d1, Decimal('0'))
856
857 #with other type, left
858 c = d1 // 4
859 self.assertEqual(c, Decimal('1'))
860 self.assertEqual(type(c), type(d1))
861
862 #with other type, right
863 c = 7 // d1
864 self.assertEqual(c, Decimal('1'))
865 self.assertEqual(type(c), type(d1))
866
867 #inline with decimal
868 d1 //= d2
869 self.assertEqual(d1, Decimal('2'))
870
871 #inline with other type
872 d1 //= 2
873 self.assertEqual(d1, Decimal('1'))
874
875 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000876
877 d1 = Decimal('5')
878 d2 = Decimal('2')
879
880 #two Decimals
881 self.assertEqual(d1**d2, Decimal('25'))
882 self.assertEqual(d2**d1, Decimal('32'))
883
884 #with other type, left
885 c = d1 ** 4
886 self.assertEqual(c, Decimal('625'))
887 self.assertEqual(type(c), type(d1))
888
889 #with other type, right
890 c = 7 ** d1
891 self.assertEqual(c, Decimal('16807'))
892 self.assertEqual(type(c), type(d1))
893
894 #inline with decimal
895 d1 **= d2
896 self.assertEqual(d1, Decimal('25'))
897
898 #inline with other type
899 d1 **= 4
900 self.assertEqual(d1, Decimal('390625'))
901
902 def test_module(self):
903
904 d1 = Decimal('5')
905 d2 = Decimal('2')
906
907 #two Decimals
908 self.assertEqual(d1%d2, Decimal('1'))
909 self.assertEqual(d2%d1, Decimal('2'))
910
911 #with other type, left
912 c = d1 % 4
913 self.assertEqual(c, Decimal('1'))
914 self.assertEqual(type(c), type(d1))
915
916 #with other type, right
917 c = 7 % d1
918 self.assertEqual(c, Decimal('2'))
919 self.assertEqual(type(c), type(d1))
920
921 #inline with decimal
922 d1 %= d2
923 self.assertEqual(d1, Decimal('1'))
924
925 #inline with other type
926 d1 %= 4
927 self.assertEqual(d1, Decimal('1'))
928
929 def test_floor_div_module(self):
930
931 d1 = Decimal('5')
932 d2 = Decimal('2')
933
934 #two Decimals
935 (p, q) = divmod(d1, d2)
936 self.assertEqual(p, Decimal('2'))
937 self.assertEqual(q, Decimal('1'))
938 self.assertEqual(type(p), type(d1))
939 self.assertEqual(type(q), type(d1))
940
941 #with other type, left
942 (p, q) = divmod(d1, 4)
943 self.assertEqual(p, Decimal('1'))
944 self.assertEqual(q, Decimal('1'))
945 self.assertEqual(type(p), type(d1))
946 self.assertEqual(type(q), type(d1))
947
948 #with other type, right
949 (p, q) = divmod(7, d1)
950 self.assertEqual(p, Decimal('1'))
951 self.assertEqual(q, Decimal('2'))
952 self.assertEqual(type(p), type(d1))
953 self.assertEqual(type(q), type(d1))
954
955 def test_unary_operators(self):
956 self.assertEqual(+Decimal(45), Decimal(+45)) # +
957 self.assertEqual(-Decimal(45), Decimal(-45)) # -
958 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
959
Mark Dickinson2fc92632008-02-06 22:10:50 +0000960 def test_nan_comparisons(self):
961 n = Decimal('NaN')
962 s = Decimal('sNaN')
963 i = Decimal('Inf')
964 f = Decimal('2')
965 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
966 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
967 self.assert_(x != y)
968 self.assert_(not (x == y))
969 self.assert_(not (x < y))
970 self.assert_(not (x <= y))
971 self.assert_(not (x > y))
972 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000973
974# The following are two functions used to test threading in the next class
975
976def thfunc1(cls):
977 d1 = Decimal(1)
978 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +0000979 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000980 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +0000981 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000982 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +0000983
Facundo Batistaee340e52008-05-02 17:39:00 +0000984 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
985 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000986 return
987
988def thfunc2(cls):
989 d1 = Decimal(1)
990 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +0000991 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000992 thiscontext = getcontext()
993 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +0000994 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000995 cls.synchro.set()
996 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +0000997
Facundo Batistaee340e52008-05-02 17:39:00 +0000998 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +0000999 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001000 return
1001
1002
1003class DecimalUseOfContextTest(unittest.TestCase):
1004 '''Unit tests for Use of Context cases in Decimal.'''
1005
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001006 try:
1007 import threading
1008 except ImportError:
1009 threading = None
1010
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001011 # Take care executing this test from IDLE, there's an issue in threading
1012 # that hangs IDLE and I couldn't find it
1013
1014 def test_threading(self):
1015 #Test the "threading isolation" of a Context.
1016
1017 self.synchro = threading.Event()
1018 self.finish1 = threading.Event()
1019 self.finish2 = threading.Event()
1020
1021 th1 = threading.Thread(target=thfunc1, args=(self,))
1022 th2 = threading.Thread(target=thfunc2, args=(self,))
1023
1024 th1.start()
1025 th2.start()
1026
1027 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001028 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001029 return
1030
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001031 if threading is None:
1032 del test_threading
1033
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001034
1035class DecimalUsabilityTest(unittest.TestCase):
1036 '''Unit tests for Usability cases of Decimal.'''
1037
1038 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001039
1040 da = Decimal('23.42')
1041 db = Decimal('23.42')
1042 dc = Decimal('45')
1043
1044 #two Decimals
1045 self.failUnless(dc > da)
1046 self.failUnless(dc >= da)
1047 self.failUnless(da < dc)
1048 self.failUnless(da <= dc)
1049 self.failUnless(da == db)
1050 self.failUnless(da != dc)
1051 self.failUnless(da <= db)
1052 self.failUnless(da >= db)
1053 self.assertEqual(cmp(dc,da), 1)
1054 self.assertEqual(cmp(da,dc), -1)
1055 self.assertEqual(cmp(da,db), 0)
1056
1057 #a Decimal and an int
1058 self.failUnless(dc > 23)
1059 self.failUnless(23 < dc)
1060 self.failUnless(dc == 45)
1061 self.assertEqual(cmp(dc,23), 1)
1062 self.assertEqual(cmp(23,dc), -1)
1063 self.assertEqual(cmp(dc,45), 0)
1064
1065 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001066 self.assertNotEqual(da, 'ugly')
1067 self.assertNotEqual(da, 32.7)
1068 self.assertNotEqual(da, object())
1069 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001070
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001071 # sortable
1072 a = map(Decimal, xrange(100))
1073 b = a[:]
1074 random.shuffle(a)
1075 a.sort()
1076 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001077
Facundo Batista353750c2007-09-13 18:13:15 +00001078 # with None
1079 self.assertFalse(Decimal(1) < None)
1080 self.assertTrue(Decimal(1) > None)
1081
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001082 def test_copy_and_deepcopy_methods(self):
1083 d = Decimal('43.24')
1084 c = copy.copy(d)
1085 self.assertEqual(id(c), id(d))
1086 dc = copy.deepcopy(d)
1087 self.assertEqual(id(dc), id(d))
1088
1089 def test_hash_method(self):
1090 #just that it's hashable
1091 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001092
1093 test_values = [Decimal(sign*(2**m + n))
1094 for m in [0, 14, 15, 16, 17, 30, 31,
1095 32, 33, 62, 63, 64, 65, 66]
1096 for n in range(-10, 10)
1097 for sign in [-1, 1]]
1098 test_values.extend([
1099 Decimal("-0"), # zeros
1100 Decimal("0.00"),
1101 Decimal("-0.000"),
1102 Decimal("0E10"),
1103 Decimal("-0E12"),
1104 Decimal("10.0"), # negative exponent
1105 Decimal("-23.00000"),
1106 Decimal("1230E100"), # positive exponent
1107 Decimal("-4.5678E50"),
1108 # a value for which hash(n) != hash(n % (2**64-1))
1109 # in Python pre-2.6
1110 Decimal(2**64 + 2**32 - 1),
1111 # selection of values which fail with the old (before
1112 # version 2.6) long.__hash__
1113 Decimal("1.634E100"),
1114 Decimal("90.697E100"),
1115 Decimal("188.83E100"),
1116 Decimal("1652.9E100"),
1117 Decimal("56531E100"),
1118 ])
1119
1120 # check that hash(d) == hash(int(d)) for integral values
1121 for value in test_values:
1122 self.assertEqual(hash(value), hash(int(value)))
1123
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001124 #the same hash that to an int
1125 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001126 self.assertRaises(TypeError, hash, Decimal('NaN'))
1127 self.assert_(hash(Decimal('Inf')))
1128 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001129
Facundo Batista52b25792008-01-08 12:25:20 +00001130 # check that the value of the hash doesn't depend on the
1131 # current context (issue #1757)
1132 c = getcontext()
1133 old_precision = c.prec
1134 x = Decimal("123456789.1")
1135
1136 c.prec = 6
1137 h1 = hash(x)
1138 c.prec = 10
1139 h2 = hash(x)
1140 c.prec = 16
1141 h3 = hash(x)
1142
1143 self.assertEqual(h1, h2)
1144 self.assertEqual(h1, h3)
1145 c.prec = old_precision
1146
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001147 def test_min_and_max_methods(self):
1148
1149 d1 = Decimal('15.32')
1150 d2 = Decimal('28.5')
1151 l1 = 15
1152 l2 = 28
1153
1154 #between Decimals
1155 self.failUnless(min(d1,d2) is d1)
1156 self.failUnless(min(d2,d1) is d1)
1157 self.failUnless(max(d1,d2) is d2)
1158 self.failUnless(max(d2,d1) is d2)
1159
1160 #between Decimal and long
1161 self.failUnless(min(d1,l2) is d1)
1162 self.failUnless(min(l2,d1) is d1)
1163 self.failUnless(max(l1,d2) is d2)
1164 self.failUnless(max(d2,l1) is d2)
1165
1166 def test_as_nonzero(self):
1167 #as false
1168 self.failIf(Decimal(0))
1169 #as true
1170 self.failUnless(Decimal('0.372'))
1171
1172 def test_tostring_methods(self):
1173 #Test str and repr methods.
1174
1175 d = Decimal('15.32')
1176 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001177 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001179 # result type of string methods should be str, not unicode
1180 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1181 u'-0.0E100', u'-NaN001', u'-Inf']
1182
1183 for u in unicode_inputs:
1184 d = Decimal(u)
1185 self.assertEqual(type(str(d)), str)
1186 self.assertEqual(type(repr(d)), str)
1187 self.assertEqual(type(d.to_eng_string()), str)
1188
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189 def test_tonum_methods(self):
1190 #Test float, int and long methods.
1191
1192 d1 = Decimal('66')
1193 d2 = Decimal('15.32')
1194
1195 #int
1196 self.assertEqual(int(d1), 66)
1197 self.assertEqual(int(d2), 15)
1198
1199 #long
1200 self.assertEqual(long(d1), 66)
1201 self.assertEqual(long(d2), 15)
1202
1203 #float
1204 self.assertEqual(float(d1), 66)
1205 self.assertEqual(float(d2), 15.32)
1206
1207 def test_eval_round_trip(self):
1208
1209 #with zero
1210 d = Decimal( (0, (0,), 0) )
1211 self.assertEqual(d, eval(repr(d)))
1212
1213 #int
1214 d = Decimal( (1, (4, 5), 0) )
1215 self.assertEqual(d, eval(repr(d)))
1216
1217 #float
1218 d = Decimal( (0, (4, 5, 3, 4), -2) )
1219 self.assertEqual(d, eval(repr(d)))
1220
1221 #weird
1222 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1223 self.assertEqual(d, eval(repr(d)))
1224
1225 def test_as_tuple(self):
1226
1227 #with zero
1228 d = Decimal(0)
1229 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1230
1231 #int
1232 d = Decimal(-45)
1233 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1234
1235 #complicated string
1236 d = Decimal("-4.34913534E-17")
1237 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1238
1239 #inf
1240 d = Decimal("Infinity")
1241 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1242
Facundo Batista9b5e2312007-10-19 19:25:57 +00001243 #leading zeros in coefficient should be stripped
1244 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1245 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1246 d = Decimal( (1, (0, 0, 0), 37) )
1247 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1248 d = Decimal( (1, (), 37) )
1249 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1250
1251 #leading zeros in NaN diagnostic info should be stripped
1252 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1253 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1254 d = Decimal( (1, (0, 0, 0), 'N') )
1255 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1256 d = Decimal( (1, (), 'n') )
1257 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1258
1259 #coefficient in infinity should be ignored
1260 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1261 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1262 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1263 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1264
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001265 def test_immutability_operations(self):
1266 # Do operations and check that it didn't change change internal objects.
1267
1268 d1 = Decimal('-25e55')
1269 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001270 d2 = Decimal('33e+33')
1271 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001272
1273 def checkSameDec(operation, useOther=False):
1274 if useOther:
1275 eval("d1." + operation + "(d2)")
1276 self.assertEqual(d1._sign, b1._sign)
1277 self.assertEqual(d1._int, b1._int)
1278 self.assertEqual(d1._exp, b1._exp)
1279 self.assertEqual(d2._sign, b2._sign)
1280 self.assertEqual(d2._int, b2._int)
1281 self.assertEqual(d2._exp, b2._exp)
1282 else:
1283 eval("d1." + operation + "()")
1284 self.assertEqual(d1._sign, b1._sign)
1285 self.assertEqual(d1._int, b1._int)
1286 self.assertEqual(d1._exp, b1._exp)
1287 return
1288
1289 Decimal(d1)
1290 self.assertEqual(d1._sign, b1._sign)
1291 self.assertEqual(d1._int, b1._int)
1292 self.assertEqual(d1._exp, b1._exp)
1293
1294 checkSameDec("__abs__")
1295 checkSameDec("__add__", True)
1296 checkSameDec("__div__", True)
1297 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001298 checkSameDec("__eq__", True)
1299 checkSameDec("__ne__", True)
1300 checkSameDec("__le__", True)
1301 checkSameDec("__lt__", True)
1302 checkSameDec("__ge__", True)
1303 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001304 checkSameDec("__float__")
1305 checkSameDec("__floordiv__", True)
1306 checkSameDec("__hash__")
1307 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001308 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001309 checkSameDec("__long__")
1310 checkSameDec("__mod__", True)
1311 checkSameDec("__mul__", True)
1312 checkSameDec("__neg__")
1313 checkSameDec("__nonzero__")
1314 checkSameDec("__pos__")
1315 checkSameDec("__pow__", True)
1316 checkSameDec("__radd__", True)
1317 checkSameDec("__rdiv__", True)
1318 checkSameDec("__rdivmod__", True)
1319 checkSameDec("__repr__")
1320 checkSameDec("__rfloordiv__", True)
1321 checkSameDec("__rmod__", True)
1322 checkSameDec("__rmul__", True)
1323 checkSameDec("__rpow__", True)
1324 checkSameDec("__rsub__", True)
1325 checkSameDec("__str__")
1326 checkSameDec("__sub__", True)
1327 checkSameDec("__truediv__", True)
1328 checkSameDec("adjusted")
1329 checkSameDec("as_tuple")
1330 checkSameDec("compare", True)
1331 checkSameDec("max", True)
1332 checkSameDec("min", True)
1333 checkSameDec("normalize")
1334 checkSameDec("quantize", True)
1335 checkSameDec("remainder_near", True)
1336 checkSameDec("same_quantum", True)
1337 checkSameDec("sqrt")
1338 checkSameDec("to_eng_string")
1339 checkSameDec("to_integral")
1340
Facundo Batista6c398da2007-09-17 17:30:13 +00001341 def test_subclassing(self):
1342 # Different behaviours when subclassing Decimal
1343
1344 class MyDecimal(Decimal):
1345 pass
1346
1347 d1 = MyDecimal(1)
1348 d2 = MyDecimal(2)
1349 d = d1 + d2
1350 self.assertTrue(type(d) is Decimal)
1351
1352 d = d1.max(d2)
1353 self.assertTrue(type(d) is Decimal)
1354
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001355 def test_implicit_context(self):
1356 # Check results when context given implicitly. (Issue 2478)
1357 c = getcontext()
1358 self.assertEqual(str(Decimal(0).sqrt()),
1359 str(c.sqrt(Decimal(0))))
1360
Mark Dickinsond8a2e2b2009-10-29 12:16:15 +00001361 def test_conversions_from_int(self):
1362 # Check that methods taking a second Decimal argument will
1363 # always accept an integer in place of a Decimal.
1364 self.assertEqual(Decimal(4).compare(3),
1365 Decimal(4).compare(Decimal(3)))
1366 self.assertEqual(Decimal(4).compare_signal(3),
1367 Decimal(4).compare_signal(Decimal(3)))
1368 self.assertEqual(Decimal(4).compare_total(3),
1369 Decimal(4).compare_total(Decimal(3)))
1370 self.assertEqual(Decimal(4).compare_total_mag(3),
1371 Decimal(4).compare_total_mag(Decimal(3)))
1372 self.assertEqual(Decimal(10101).logical_and(1001),
1373 Decimal(10101).logical_and(Decimal(1001)))
1374 self.assertEqual(Decimal(10101).logical_or(1001),
1375 Decimal(10101).logical_or(Decimal(1001)))
1376 self.assertEqual(Decimal(10101).logical_xor(1001),
1377 Decimal(10101).logical_xor(Decimal(1001)))
1378 self.assertEqual(Decimal(567).max(123),
1379 Decimal(567).max(Decimal(123)))
1380 self.assertEqual(Decimal(567).max_mag(123),
1381 Decimal(567).max_mag(Decimal(123)))
1382 self.assertEqual(Decimal(567).min(123),
1383 Decimal(567).min(Decimal(123)))
1384 self.assertEqual(Decimal(567).min_mag(123),
1385 Decimal(567).min_mag(Decimal(123)))
1386 self.assertEqual(Decimal(567).next_toward(123),
1387 Decimal(567).next_toward(Decimal(123)))
1388 self.assertEqual(Decimal(1234).quantize(100),
1389 Decimal(1234).quantize(Decimal(100)))
1390 self.assertEqual(Decimal(768).remainder_near(1234),
1391 Decimal(768).remainder_near(Decimal(1234)))
1392 self.assertEqual(Decimal(123).rotate(1),
1393 Decimal(123).rotate(Decimal(1)))
1394 self.assertEqual(Decimal(1234).same_quantum(1000),
1395 Decimal(1234).same_quantum(Decimal(1000)))
1396 self.assertEqual(Decimal('9.123').scaleb(-100),
1397 Decimal('9.123').scaleb(Decimal(-100)))
1398 self.assertEqual(Decimal(456).shift(-1),
1399 Decimal(456).shift(Decimal(-1)))
1400
1401 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1402 Decimal(-12).fma(Decimal(45), Decimal(67)))
1403 self.assertEqual(Decimal(-12).fma(45, 67),
1404 Decimal(-12).fma(Decimal(45), Decimal(67)))
1405 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1406 Decimal(-12).fma(Decimal(45), Decimal(67)))
1407
Facundo Batista6c398da2007-09-17 17:30:13 +00001408
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409class DecimalPythonAPItests(unittest.TestCase):
1410
Raymond Hettinger45fd4762009-02-03 03:42:07 +00001411 def test_abc(self):
1412 self.assert_(issubclass(Decimal, numbers.Number))
1413 self.assert_(not issubclass(Decimal, numbers.Real))
1414 self.assert_(isinstance(Decimal(0), numbers.Number))
1415 self.assert_(not isinstance(Decimal(0), numbers.Real))
1416
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001417 def test_pickle(self):
1418 d = Decimal('-3.141590000')
1419 p = pickle.dumps(d)
1420 e = pickle.loads(p)
1421 self.assertEqual(d, e)
1422
Raymond Hettinger5548be22004-07-05 18:49:38 +00001423 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001424 for x in range(-250, 250):
1425 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001426 # should work the same as for floats
1427 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001428 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001429 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001430 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001431 self.assertEqual(Decimal(int(d)), r)
1432
Mark Dickinsonc05b7892009-09-08 19:22:18 +00001433 self.assertRaises(ValueError, int, Decimal('-nan'))
1434 self.assertRaises(ValueError, int, Decimal('snan'))
1435 self.assertRaises(OverflowError, int, Decimal('inf'))
1436 self.assertRaises(OverflowError, int, Decimal('-inf'))
1437
1438 self.assertRaises(ValueError, long, Decimal('-nan'))
1439 self.assertRaises(ValueError, long, Decimal('snan'))
1440 self.assertRaises(OverflowError, long, Decimal('inf'))
1441 self.assertRaises(OverflowError, long, Decimal('-inf'))
1442
Raymond Hettinger5a053642008-01-24 19:05:29 +00001443 def test_trunc(self):
1444 for x in range(-250, 250):
1445 s = '%0.2f' % (x / 100.0)
1446 # should work the same as for floats
1447 self.assertEqual(int(Decimal(s)), int(float(s)))
1448 # should work the same as to_integral in the ROUND_DOWN mode
1449 d = Decimal(s)
1450 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001451 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001452
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001453class ContextAPItests(unittest.TestCase):
1454
1455 def test_pickle(self):
1456 c = Context()
1457 e = pickle.loads(pickle.dumps(c))
1458 for k in vars(c):
1459 v1 = vars(c)[k]
1460 v2 = vars(e)[k]
1461 self.assertEqual(v1, v2)
1462
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001463 def test_equality_with_other_types(self):
1464 self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1465 self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1466
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001467 def test_copy(self):
1468 # All copies should be deep
1469 c = Context()
1470 d = c.copy()
1471 self.assertNotEqual(id(c), id(d))
1472 self.assertNotEqual(id(c.flags), id(d.flags))
1473 self.assertNotEqual(id(c.traps), id(d.traps))
1474
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001475class WithStatementTest(unittest.TestCase):
1476 # Can't do these as docstrings until Python 2.6
1477 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001478
1479 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001480 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001481 orig_ctx = getcontext()
1482 with localcontext() as enter_ctx:
1483 set_ctx = getcontext()
1484 final_ctx = getcontext()
1485 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1486 self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
1487 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1488
1489 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001490 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001491 orig_ctx = getcontext()
1492 new_ctx = Context(prec=42)
1493 with localcontext(new_ctx) as enter_ctx:
1494 set_ctx = getcontext()
1495 final_ctx = getcontext()
1496 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1497 self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1498 self.assert_(new_ctx is not set_ctx, 'did not copy the context')
1499 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1500
Facundo Batista353750c2007-09-13 18:13:15 +00001501class ContextFlags(unittest.TestCase):
1502 def test_flags_irrelevant(self):
1503 # check that the result (numeric result + flags raised) of an
1504 # arithmetic operation doesn't depend on the current flags
1505
1506 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1507 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1508
1509 # operations that raise various flags, in the form (function, arglist)
1510 operations = [
1511 (context._apply, [Decimal("100E-1000000009")]),
1512 (context.sqrt, [Decimal(2)]),
1513 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1514 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1515 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1516 ]
1517
1518 # try various flags individually, then a whole lot at once
1519 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1520 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1521
1522 for fn, args in operations:
1523 # find answer and flags raised using a clean context
1524 context.clear_flags()
1525 ans = fn(*args)
1526 flags = [k for k, v in context.flags.items() if v]
1527
1528 for extra_flags in flagsets:
1529 # set flags, before calling operation
1530 context.clear_flags()
1531 for flag in extra_flags:
1532 context._raise_error(flag)
1533 new_ans = fn(*args)
1534
1535 # flags that we expect to be set after the operation
1536 expected_flags = list(flags)
1537 for flag in extra_flags:
1538 if flag not in expected_flags:
1539 expected_flags.append(flag)
1540 expected_flags.sort()
1541
1542 # flags we actually got
1543 new_flags = [k for k,v in context.flags.items() if v]
1544 new_flags.sort()
1545
1546 self.assertEqual(ans, new_ans,
1547 "operation produces different answers depending on flags set: " +
1548 "expected %s, got %s." % (ans, new_ans))
1549 self.assertEqual(new_flags, expected_flags,
1550 "operation raises different flags depending on flags set: " +
1551 "expected %s, got %s" % (expected_flags, new_flags))
1552
1553def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001554 """ Execute the tests.
1555
Raymond Hettingered20ad82004-09-04 20:09:13 +00001556 Runs all arithmetic tests if arith is True or if the "decimal" resource
1557 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001559
Neal Norwitzce4a9c92006-04-09 08:36:46 +00001560 init()
Facundo Batista353750c2007-09-13 18:13:15 +00001561 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001562 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00001563 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001564
Facundo Batista353750c2007-09-13 18:13:15 +00001565 if todo_tests is None:
1566 test_classes = [
1567 DecimalExplicitConstructionTest,
1568 DecimalImplicitConstructionTest,
1569 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00001570 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00001571 DecimalUseOfContextTest,
1572 DecimalUsabilityTest,
1573 DecimalPythonAPItests,
1574 ContextAPItests,
1575 DecimalTest,
1576 WithStatementTest,
1577 ContextFlags
1578 ]
1579 else:
1580 test_classes = [DecimalTest]
1581
1582 # Dynamically build custom test definition for each file in the test
1583 # directory and add the definitions to the DecimalTest class. This
1584 # procedure insures that new files do not get skipped.
1585 for filename in os.listdir(directory):
1586 if '.decTest' not in filename or filename.startswith("."):
1587 continue
1588 head, tail = filename.split('.')
1589 if todo_tests is not None and head not in todo_tests:
1590 continue
1591 tester = lambda self, f=filename: self.eval_file(directory + f)
1592 setattr(DecimalTest, 'test_' + head, tester)
1593 del filename, head, tail, tester
1594
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001595
Tim Peters46cc7022006-03-31 04:11:16 +00001596 try:
1597 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00001598 if todo_tests is None:
1599 import decimal as DecimalModule
1600 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00001601 finally:
1602 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001603
1604if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00001605 import optparse
1606 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1607 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1608 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1609 (opt, args) = p.parse_args()
1610
1611 if opt.skip:
1612 test_main(arith=False, verbose=True)
1613 elif args:
1614 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001615 else:
Facundo Batista353750c2007-09-13 18:13:15 +00001616 test_main(arith=True, verbose=True)