blob: 41767c3b48febc9706fd22023d6412a0614bd870 [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,
Ezio Melottid24b5d82010-08-03 04:08:59 +000035 is_resource_enabled, _check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000036import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000037try:
38 import threading
39except ImportError:
40 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000041
Raymond Hettingerfed52962004-07-14 15:41:57 +000042# Useful Test Constant
Mark Dickinson813f1182010-05-01 11:56:48 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Mark Dickinson1cdfa5f2010-05-04 14:30:32 +000045# Signals ordered with respect to precedence: when an operation
46# produces multiple signals, signals occurring later in the list
47# should be handled before those occurring earlier in the list.
48OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
49 Underflow, Overflow, DivisionByZero, InvalidOperation)
50
Tim Peters46cc7022006-03-31 04:11:16 +000051# Tests are built around these assumed context defaults.
52# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000053def init():
54 global ORIGINAL_CONTEXT
55 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000056 DefaultTestContext = Context(
57 prec = 9,
58 rounding = ROUND_HALF_EVEN,
59 traps = dict.fromkeys(Signals, 0)
60 )
61 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000062
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000063TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000064if __name__ == '__main__':
65 file = sys.argv[0]
66else:
67 file = __file__
68testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000069directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000070
Raymond Hettinger267b8682005-03-27 10:47:39 +000071skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000072
Mark Dickinson25567ef2009-10-27 17:02:46 +000073# list of individual .decTest test ids that correspond to tests that
74# we're skipping for one reason or another.
Mark Dickinson060d6552010-07-08 19:27:24 +000075skipped_test_ids = set([
76 # Skip implementation-specific scaleb tests.
77 'scbx164',
78 'scbx165',
79
80 # For some operations (currently exp, ln, log10, power), the decNumber
81 # reference implementation imposes additional restrictions on the context
82 # and operands. These restrictions are not part of the specification;
83 # however, the effect of these restrictions does show up in some of the
84 # testcases. We skip testcases that violate these restrictions, since
85 # Decimal behaves differently from decNumber for these testcases so these
86 # testcases would otherwise fail.
87 'expx901',
88 'expx902',
89 'expx903',
90 'expx905',
91 'lnx901',
92 'lnx902',
93 'lnx903',
94 'lnx905',
95 'logx901',
96 'logx902',
97 'logx903',
98 'logx905',
99 'powx1183',
100 'powx1184',
101 'powx4001',
102 'powx4002',
103 'powx4003',
104 'powx4005',
105 'powx4008',
106 'powx4010',
107 'powx4012',
108 'powx4014',
109 ])
Mark Dickinson25567ef2009-10-27 17:02:46 +0000110
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000111# Make sure it actually raises errors when not expected and caught in flags
112# Slower, since it runs some things several times.
113EXTENDEDERRORTEST = False
114
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000117 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000119 'division_impossible' : InvalidOperation,
120 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000122 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123 'invalid_operation' : InvalidOperation,
124 'overflow' : Overflow,
125 'rounded' : Rounded,
126 'subnormal' : Subnormal,
127 'underflow' : Underflow}
128
129
130def Nonfunction(*args):
131 """Doesn't do anything."""
132 return None
133
134RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
135 'down' : ROUND_DOWN,
136 'floor' : ROUND_FLOOR,
137 'half_down' : ROUND_HALF_DOWN,
138 'half_even' : ROUND_HALF_EVEN,
139 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000140 'up' : ROUND_UP,
141 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000142
143# Name adapter to be able to change the Decimal and Context
144# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000145nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000146 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000147 'class':'number_class',
148 'comparesig':'compare_signal',
149 'comparetotal':'compare_total',
150 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000151 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000152 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000153 'copynegate':'copy_negate',
154 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000155 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000156 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000157 'iscanonical':'is_canonical',
158 'isfinite':'is_finite',
159 'isinfinite':'is_infinite',
160 'isnan':'is_nan',
161 'isnormal':'is_normal',
162 'isqnan':'is_qnan',
163 'issigned':'is_signed',
164 'issnan':'is_snan',
165 'issubnormal':'is_subnormal',
166 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000167 'maxmag':'max_mag',
168 'minmag':'min_mag',
169 'nextminus':'next_minus',
170 'nextplus':'next_plus',
171 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000172 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000173 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000174 'remaindernear':'remainder_near',
175 'samequantum':'same_quantum',
176 'squareroot':'sqrt',
177 'toeng':'to_eng_string',
178 'tointegral':'to_integral_value',
179 'tointegralx':'to_integral_exact',
180 'tosci':'to_sci_string',
181 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000182 }
183
Facundo Batista1a191df2007-10-02 17:01:24 +0000184# The following functions return True/False rather than a Decimal instance
185
186LOGICAL_FUNCTIONS = (
187 'is_canonical',
188 'is_finite',
189 'is_infinite',
190 'is_nan',
191 'is_normal',
192 'is_qnan',
193 'is_signed',
194 'is_snan',
195 'is_subnormal',
196 'is_zero',
197 'same_quantum',
198 )
199
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200class DecimalTest(unittest.TestCase):
201 """Class which tests the Decimal class against the test cases.
202
203 Changed for unittest.
204 """
205 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000207 self.ignore_list = ['#']
208 # Basically, a # means return NaN InvalidOperation.
209 # Different from a sNaN in trim
210
211 self.ChangeDict = {'precision' : self.change_precision,
212 'rounding' : self.change_rounding_method,
213 'maxexponent' : self.change_max_exponent,
214 'minexponent' : self.change_min_exponent,
215 'clamp' : self.change_clamp}
216
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000217 def eval_file(self, file):
218 global skip_expected
219 if skip_expected:
220 raise TestSkipped
221 return
Ezio Melottid24b5d82010-08-03 04:08:59 +0000222 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000223 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000224 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000225 try:
226 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000227 except DecimalException, exception:
228 #Exception raised where there shoudn't have been one.
229 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
230
231 return
232
233 def eval_line(self, s):
234 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
235 s = (s.split('->')[0] + '->' +
236 s.split('->')[1].split('--')[0]).strip()
237 else:
238 s = s.split('--')[0].strip()
239
240 for ignore in self.ignore_list:
241 if s.find(ignore) >= 0:
242 #print s.split()[0], 'NotImplemented--', ignore
243 return
244 if not s:
245 return
246 elif ':' in s:
247 return self.eval_directive(s)
248 else:
249 return self.eval_equation(s)
250
251 def eval_directive(self, s):
252 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
253 if funct == 'rounding':
254 value = RoundingDict[value]
255 else:
256 try:
257 value = int(value)
258 except ValueError:
259 pass
260
261 funct = self.ChangeDict.get(funct, Nonfunction)
262 funct(value)
263
264 def eval_equation(self, s):
265 #global DEFAULT_PRECISION
266 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000267
268 if not TEST_ALL and random.random() < 0.90:
269 return
270
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000271 try:
272 Sides = s.split('->')
273 L = Sides[0].strip().split()
274 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000275 if DEBUG:
276 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 funct = L[1].lower()
278 valstemp = L[2:]
279 L = Sides[1].strip().split()
280 ans = L[0]
281 exceptions = L[1:]
282 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000283 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000284 def FixQuotes(val):
285 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
286 val = val.replace("'", '').replace('"', '')
287 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
288 return val
Mark Dickinson25567ef2009-10-27 17:02:46 +0000289
290 if id in skipped_test_ids:
291 return
292
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 fname = nameAdapter.get(funct, funct)
294 if fname == 'rescale':
295 return
296 funct = getattr(self.context, fname)
297 vals = []
298 conglomerate = ''
299 quote = 0
300 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
301
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000302 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000303 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000305 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000306 for i, val in enumerate(valstemp):
307 if val.count("'") % 2 == 1:
308 quote = 1 - quote
309 if quote:
310 conglomerate = conglomerate + ' ' + val
311 continue
312 else:
313 val = conglomerate + val
314 conglomerate = ''
315 v = FixQuotes(val)
316 if fname in ('to_sci_string', 'to_eng_string'):
317 if EXTENDEDERRORTEST:
318 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000319 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 try:
321 funct(self.context.create_decimal(v))
322 except error:
323 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000324 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 self.fail("Raised %s in %s when %s disabled" % \
326 (e, s, error))
327 else:
328 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000329 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 v = self.context.create_decimal(v)
331 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000332 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000333 vals.append(v)
334
335 ans = FixQuotes(ans)
336
337 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
338 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000339 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 try:
341 funct(*vals)
342 except error:
343 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000344 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 self.fail("Raised %s in %s when %s disabled" % \
346 (e, s, error))
347 else:
348 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000349 self.context.traps[error] = 0
Mark Dickinson1cdfa5f2010-05-04 14:30:32 +0000350
351 # as above, but add traps cumulatively, to check precedence
352 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
353 for error in ordered_errors:
354 self.context.traps[error] = 1
355 try:
356 funct(*vals)
357 except error:
358 pass
359 except Signals, e:
360 self.fail("Raised %s in %s; expected %s" %
361 (type(e), s, error))
362 else:
363 self.fail("Did not raise %s in %s" % (error, s))
364 # reset traps
365 for error in ordered_errors:
366 self.context.traps[error] = 0
367
368
Facundo Batista353750c2007-09-13 18:13:15 +0000369 if DEBUG:
370 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371 try:
372 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000373 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000375 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 self.fail("Raised %s in %s" % (error, s))
377 except: #Catch any error long enough to state the test case.
378 print "ERROR:", s
379 raise
380
381 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000382 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000383
Ezio Melottid24b5d82010-08-03 04:08:59 +0000384 with _check_py3k_warnings(quiet=True):
385 myexceptions.sort()
386 theirexceptions.sort()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387
388 self.assertEqual(result, ans,
389 'Incorrect answer for ' + s + ' -- got ' + result)
390 self.assertEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000391 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392 return
393
394 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000395 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 def change_precision(self, prec):
398 self.context.prec = prec
399 def change_rounding_method(self, rounding):
400 self.context.rounding = rounding
401 def change_min_exponent(self, exp):
402 self.context.Emin = exp
403 def change_max_exponent(self, exp):
404 self.context.Emax = exp
405 def change_clamp(self, clamp):
406 self.context._clamp = clamp
407
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000408
409
410# The following classes test the behaviour of Decimal according to PEP 327
411
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412class DecimalExplicitConstructionTest(unittest.TestCase):
413 '''Unit tests for Explicit Construction cases of Decimal.'''
414
415 def test_explicit_empty(self):
416 self.assertEqual(Decimal(), Decimal("0"))
417
418 def test_explicit_from_None(self):
419 self.assertRaises(TypeError, Decimal, None)
420
421 def test_explicit_from_int(self):
422
423 #positive
424 d = Decimal(45)
425 self.assertEqual(str(d), '45')
426
427 #very large positive
428 d = Decimal(500000123)
429 self.assertEqual(str(d), '500000123')
430
431 #negative
432 d = Decimal(-45)
433 self.assertEqual(str(d), '-45')
434
435 #zero
436 d = Decimal(0)
437 self.assertEqual(str(d), '0')
438
439 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000440
441 #empty
442 self.assertEqual(str(Decimal('')), 'NaN')
443
444 #int
445 self.assertEqual(str(Decimal('45')), '45')
446
447 #float
448 self.assertEqual(str(Decimal('45.34')), '45.34')
449
450 #engineer notation
451 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
452
453 #just not a number
454 self.assertEqual(str(Decimal('ugly')), 'NaN')
455
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000456 #leading and trailing whitespace permitted
457 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
458 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
459
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000460 #unicode strings should be permitted
461 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
462 self.assertEqual(str(Decimal(u'45')), '45')
463 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
464 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
465
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466 def test_explicit_from_tuples(self):
467
468 #zero
469 d = Decimal( (0, (0,), 0) )
470 self.assertEqual(str(d), '0')
471
472 #int
473 d = Decimal( (1, (4, 5), 0) )
474 self.assertEqual(str(d), '-45')
475
476 #float
477 d = Decimal( (0, (4, 5, 3, 4), -2) )
478 self.assertEqual(str(d), '45.34')
479
480 #weird
481 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
482 self.assertEqual(str(d), '-4.34913534E-17')
483
484 #wrong number of items
485 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
486
487 #bad sign
488 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000489 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
490 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491
492 #bad exp
493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
495 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496
497 #bad coefficients
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
499 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000501 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
503 def test_explicit_from_Decimal(self):
504
505 #positive
506 d = Decimal(45)
507 e = Decimal(d)
508 self.assertEqual(str(e), '45')
509 self.assertNotEqual(id(d), id(e))
510
511 #very large positive
512 d = Decimal(500000123)
513 e = Decimal(d)
514 self.assertEqual(str(e), '500000123')
515 self.assertNotEqual(id(d), id(e))
516
517 #negative
518 d = Decimal(-45)
519 e = Decimal(d)
520 self.assertEqual(str(e), '-45')
521 self.assertNotEqual(id(d), id(e))
522
523 #zero
524 d = Decimal(0)
525 e = Decimal(d)
526 self.assertEqual(str(e), '0')
527 self.assertNotEqual(id(d), id(e))
528
529 def test_explicit_context_create_decimal(self):
530
531 nc = copy.copy(getcontext())
532 nc.prec = 3
533
534 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000535 d = Decimal()
536 self.assertEqual(str(d), '0')
537 d = nc.create_decimal()
538 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000539
540 # from None
541 self.assertRaises(TypeError, nc.create_decimal, None)
542
543 # from int
544 d = nc.create_decimal(456)
545 self.failUnless(isinstance(d, Decimal))
546 self.assertEqual(nc.create_decimal(45678),
547 nc.create_decimal('457E+2'))
548
549 # from string
550 d = Decimal('456789')
551 self.assertEqual(str(d), '456789')
552 d = nc.create_decimal('456789')
553 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000554 # leading and trailing whitespace should result in a NaN;
555 # spaces are already checked in Cowlishaw's test-suite, so
556 # here we just check that a trailing newline results in a NaN
557 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000558
559 # from tuples
560 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
561 self.assertEqual(str(d), '-4.34913534E-17')
562 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
563 self.assertEqual(str(d), '-4.35E-17')
564
565 # from Decimal
566 prevdec = Decimal(500000123)
567 d = Decimal(prevdec)
568 self.assertEqual(str(d), '500000123')
569 d = nc.create_decimal(prevdec)
570 self.assertEqual(str(d), '5.00E+8')
571
Mark Dickinson9a6e6452009-08-02 11:01:01 +0000572 def test_unicode_digits(self):
573 test_values = {
574 u'\uff11': '1',
575 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
576 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
577 }
578 for input, expected in test_values.items():
579 self.assertEqual(str(Decimal(input)), expected)
580
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000581
582class DecimalImplicitConstructionTest(unittest.TestCase):
583 '''Unit tests for Implicit Construction cases of Decimal.'''
584
585 def test_implicit_from_None(self):
586 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
587
588 def test_implicit_from_int(self):
589 #normal
590 self.assertEqual(str(Decimal(5) + 45), '50')
591 #exceeding precision
592 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
593
594 def test_implicit_from_string(self):
595 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
596
597 def test_implicit_from_float(self):
598 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
599
600 def test_implicit_from_Decimal(self):
601 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
602
Raymond Hettinger267b8682005-03-27 10:47:39 +0000603 def test_rop(self):
604 # Allow other classes to be trained to interact with Decimals
605 class E:
606 def __divmod__(self, other):
607 return 'divmod ' + str(other)
608 def __rdivmod__(self, other):
609 return str(other) + ' rdivmod'
610 def __lt__(self, other):
611 return 'lt ' + str(other)
612 def __gt__(self, other):
613 return 'gt ' + str(other)
614 def __le__(self, other):
615 return 'le ' + str(other)
616 def __ge__(self, other):
617 return 'ge ' + str(other)
618 def __eq__(self, other):
619 return 'eq ' + str(other)
620 def __ne__(self, other):
621 return 'ne ' + str(other)
622
623 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
624 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
625 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
626 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
627 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
628 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
629 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
630 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
631
632 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000633 oplist = [
634 ('+', '__add__', '__radd__'),
635 ('-', '__sub__', '__rsub__'),
636 ('*', '__mul__', '__rmul__'),
637 ('%', '__mod__', '__rmod__'),
638 ('//', '__floordiv__', '__rfloordiv__'),
639 ('**', '__pow__', '__rpow__')
640 ]
Ezio Melottid24b5d82010-08-03 04:08:59 +0000641 with _check_py3k_warnings():
642 if 1 / 2 == 0:
643 # testing with classic division, so add __div__
644 oplist.append(('/', '__div__', '__rdiv__'))
645 else:
646 # testing with -Qnew, so add __truediv__
647 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000648
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000649 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000650 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
651 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
652 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
653 'str' + lop + '10')
654 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
655 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000656
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000657class DecimalFormatTest(unittest.TestCase):
658 '''Unit tests for the format function.'''
659 def test_formatting(self):
660 # triples giving a format, a Decimal, and the expected result
661 test_values = [
662 ('e', '0E-15', '0e-15'),
663 ('e', '2.3E-15', '2.3e-15'),
664 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
665 ('e', '2.30000E-15', '2.30000e-15'),
666 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
667 ('e', '1.5', '1.5e+0'),
668 ('e', '0.15', '1.5e-1'),
669 ('e', '0.015', '1.5e-2'),
670 ('e', '0.0000000000015', '1.5e-12'),
671 ('e', '15.0', '1.50e+1'),
672 ('e', '-15', '-1.5e+1'),
673 ('e', '0', '0e+0'),
674 ('e', '0E1', '0e+1'),
675 ('e', '0.0', '0e-1'),
676 ('e', '0.00', '0e-2'),
677 ('.6e', '0E-15', '0.000000e-9'),
678 ('.6e', '0', '0.000000e+6'),
679 ('.6e', '9.999999', '9.999999e+0'),
680 ('.6e', '9.9999999', '1.000000e+1'),
681 ('.6e', '-1.23e5', '-1.230000e+5'),
682 ('.6e', '1.23456789e-3', '1.234568e-3'),
683 ('f', '0', '0'),
684 ('f', '0.0', '0.0'),
685 ('f', '0E-2', '0.00'),
686 ('f', '0.00E-8', '0.0000000000'),
687 ('f', '0E1', '0'), # loses exponent information
688 ('f', '3.2E1', '32'),
689 ('f', '3.2E2', '320'),
690 ('f', '3.20E2', '320'),
691 ('f', '3.200E2', '320.0'),
692 ('f', '3.2E-6', '0.0000032'),
693 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
694 ('.6f', '0E1', '0.000000'),
695 ('.6f', '0', '0.000000'),
696 ('.0f', '0', '0'), # no decimal point
697 ('.0f', '0e-2', '0'),
698 ('.0f', '3.14159265', '3'),
699 ('.1f', '3.14159265', '3.1'),
700 ('.4f', '3.14159265', '3.1416'),
701 ('.6f', '3.14159265', '3.141593'),
702 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
703 ('.8f', '3.14159265', '3.14159265'),
704 ('.9f', '3.14159265', '3.141592650'),
705
706 ('g', '0', '0'),
707 ('g', '0.0', '0.0'),
708 ('g', '0E1', '0e+1'),
709 ('G', '0E1', '0E+1'),
710 ('g', '0E-5', '0.00000'),
711 ('g', '0E-6', '0.000000'),
712 ('g', '0E-7', '0e-7'),
713 ('g', '-0E2', '-0e+2'),
714 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
715 ('.1g', '3.14159265', '3'),
716 ('.2g', '3.14159265', '3.1'),
717 ('.5g', '3.14159265', '3.1416'),
718 ('.7g', '3.14159265', '3.141593'),
719 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
720 ('.9g', '3.14159265', '3.14159265'),
721 ('.10g', '3.14159265', '3.14159265'), # don't pad
722
723 ('%', '0E1', '0%'),
724 ('%', '0E0', '0%'),
725 ('%', '0E-1', '0%'),
726 ('%', '0E-2', '0%'),
727 ('%', '0E-3', '0.0%'),
728 ('%', '0E-4', '0.00%'),
729
730 ('.3%', '0', '0.000%'), # all zeros treated equally
731 ('.3%', '0E10', '0.000%'),
732 ('.3%', '0E-10', '0.000%'),
733 ('.3%', '2.34', '234.000%'),
734 ('.3%', '1.234567', '123.457%'),
735 ('.0%', '1.23', '123%'),
736
737 ('e', 'NaN', 'NaN'),
738 ('f', '-NaN123', '-NaN123'),
739 ('+g', 'NaN456', '+NaN456'),
740 ('.3e', 'Inf', 'Infinity'),
741 ('.16f', '-Inf', '-Infinity'),
742 ('.0g', '-sNaN', '-sNaN'),
743
744 ('', '1.00', '1.00'),
Mark Dickinson71416822009-03-17 18:07:41 +0000745
746 # check alignment
747 ('<6', '123', '123 '),
748 ('>6', '123', ' 123'),
749 ('^6', '123', ' 123 '),
750 ('=+6', '123', '+ 123'),
Mark Dickinsonc3c112d2009-09-07 16:19:35 +0000751
752 # issue 6850
753 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000754 ]
755 for fmt, d, result in test_values:
756 self.assertEqual(format(Decimal(d), fmt), result)
757
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000758class DecimalArithmeticOperatorsTest(unittest.TestCase):
759 '''Unit tests for all arithmetic operators, binary and unary.'''
760
761 def test_addition(self):
762
763 d1 = Decimal('-11.1')
764 d2 = Decimal('22.2')
765
766 #two Decimals
767 self.assertEqual(d1+d2, Decimal('11.1'))
768 self.assertEqual(d2+d1, Decimal('11.1'))
769
770 #with other type, left
771 c = d1 + 5
772 self.assertEqual(c, Decimal('-6.1'))
773 self.assertEqual(type(c), type(d1))
774
775 #with other type, right
776 c = 5 + d1
777 self.assertEqual(c, Decimal('-6.1'))
778 self.assertEqual(type(c), type(d1))
779
780 #inline with decimal
781 d1 += d2
782 self.assertEqual(d1, Decimal('11.1'))
783
784 #inline with other type
785 d1 += 5
786 self.assertEqual(d1, Decimal('16.1'))
787
788 def test_subtraction(self):
789
790 d1 = Decimal('-11.1')
791 d2 = Decimal('22.2')
792
793 #two Decimals
794 self.assertEqual(d1-d2, Decimal('-33.3'))
795 self.assertEqual(d2-d1, Decimal('33.3'))
796
797 #with other type, left
798 c = d1 - 5
799 self.assertEqual(c, Decimal('-16.1'))
800 self.assertEqual(type(c), type(d1))
801
802 #with other type, right
803 c = 5 - d1
804 self.assertEqual(c, Decimal('16.1'))
805 self.assertEqual(type(c), type(d1))
806
807 #inline with decimal
808 d1 -= d2
809 self.assertEqual(d1, Decimal('-33.3'))
810
811 #inline with other type
812 d1 -= 5
813 self.assertEqual(d1, Decimal('-38.3'))
814
815 def test_multiplication(self):
816
817 d1 = Decimal('-5')
818 d2 = Decimal('3')
819
820 #two Decimals
821 self.assertEqual(d1*d2, Decimal('-15'))
822 self.assertEqual(d2*d1, Decimal('-15'))
823
824 #with other type, left
825 c = d1 * 5
826 self.assertEqual(c, Decimal('-25'))
827 self.assertEqual(type(c), type(d1))
828
829 #with other type, right
830 c = 5 * d1
831 self.assertEqual(c, Decimal('-25'))
832 self.assertEqual(type(c), type(d1))
833
834 #inline with decimal
835 d1 *= d2
836 self.assertEqual(d1, Decimal('-15'))
837
838 #inline with other type
839 d1 *= 5
840 self.assertEqual(d1, Decimal('-75'))
841
842 def test_division(self):
843
844 d1 = Decimal('-5')
845 d2 = Decimal('2')
846
847 #two Decimals
848 self.assertEqual(d1/d2, Decimal('-2.5'))
849 self.assertEqual(d2/d1, Decimal('-0.4'))
850
851 #with other type, left
852 c = d1 / 4
853 self.assertEqual(c, Decimal('-1.25'))
854 self.assertEqual(type(c), type(d1))
855
856 #with other type, right
857 c = 4 / d1
858 self.assertEqual(c, Decimal('-0.8'))
859 self.assertEqual(type(c), type(d1))
860
861 #inline with decimal
862 d1 /= d2
863 self.assertEqual(d1, Decimal('-2.5'))
864
865 #inline with other type
866 d1 /= 4
867 self.assertEqual(d1, Decimal('-0.625'))
868
869 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000870
871 d1 = Decimal('5')
872 d2 = Decimal('2')
873
874 #two Decimals
875 self.assertEqual(d1//d2, Decimal('2'))
876 self.assertEqual(d2//d1, Decimal('0'))
877
878 #with other type, left
879 c = d1 // 4
880 self.assertEqual(c, Decimal('1'))
881 self.assertEqual(type(c), type(d1))
882
883 #with other type, right
884 c = 7 // d1
885 self.assertEqual(c, Decimal('1'))
886 self.assertEqual(type(c), type(d1))
887
888 #inline with decimal
889 d1 //= d2
890 self.assertEqual(d1, Decimal('2'))
891
892 #inline with other type
893 d1 //= 2
894 self.assertEqual(d1, Decimal('1'))
895
896 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000897
898 d1 = Decimal('5')
899 d2 = Decimal('2')
900
901 #two Decimals
902 self.assertEqual(d1**d2, Decimal('25'))
903 self.assertEqual(d2**d1, Decimal('32'))
904
905 #with other type, left
906 c = d1 ** 4
907 self.assertEqual(c, Decimal('625'))
908 self.assertEqual(type(c), type(d1))
909
910 #with other type, right
911 c = 7 ** d1
912 self.assertEqual(c, Decimal('16807'))
913 self.assertEqual(type(c), type(d1))
914
915 #inline with decimal
916 d1 **= d2
917 self.assertEqual(d1, Decimal('25'))
918
919 #inline with other type
920 d1 **= 4
921 self.assertEqual(d1, Decimal('390625'))
922
923 def test_module(self):
924
925 d1 = Decimal('5')
926 d2 = Decimal('2')
927
928 #two Decimals
929 self.assertEqual(d1%d2, Decimal('1'))
930 self.assertEqual(d2%d1, Decimal('2'))
931
932 #with other type, left
933 c = d1 % 4
934 self.assertEqual(c, Decimal('1'))
935 self.assertEqual(type(c), type(d1))
936
937 #with other type, right
938 c = 7 % d1
939 self.assertEqual(c, Decimal('2'))
940 self.assertEqual(type(c), type(d1))
941
942 #inline with decimal
943 d1 %= d2
944 self.assertEqual(d1, Decimal('1'))
945
946 #inline with other type
947 d1 %= 4
948 self.assertEqual(d1, Decimal('1'))
949
950 def test_floor_div_module(self):
951
952 d1 = Decimal('5')
953 d2 = Decimal('2')
954
955 #two Decimals
956 (p, q) = divmod(d1, d2)
957 self.assertEqual(p, Decimal('2'))
958 self.assertEqual(q, Decimal('1'))
959 self.assertEqual(type(p), type(d1))
960 self.assertEqual(type(q), type(d1))
961
962 #with other type, left
963 (p, q) = divmod(d1, 4)
964 self.assertEqual(p, Decimal('1'))
965 self.assertEqual(q, Decimal('1'))
966 self.assertEqual(type(p), type(d1))
967 self.assertEqual(type(q), type(d1))
968
969 #with other type, right
970 (p, q) = divmod(7, d1)
971 self.assertEqual(p, Decimal('1'))
972 self.assertEqual(q, Decimal('2'))
973 self.assertEqual(type(p), type(d1))
974 self.assertEqual(type(q), type(d1))
975
976 def test_unary_operators(self):
977 self.assertEqual(+Decimal(45), Decimal(+45)) # +
978 self.assertEqual(-Decimal(45), Decimal(-45)) # -
979 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
980
Mark Dickinson2fc92632008-02-06 22:10:50 +0000981 def test_nan_comparisons(self):
982 n = Decimal('NaN')
983 s = Decimal('sNaN')
984 i = Decimal('Inf')
985 f = Decimal('2')
986 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
987 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
988 self.assert_(x != y)
989 self.assert_(not (x == y))
990 self.assert_(not (x < y))
991 self.assert_(not (x <= y))
992 self.assert_(not (x > y))
993 self.assert_(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000994
995# The following are two functions used to test threading in the next class
996
997def thfunc1(cls):
998 d1 = Decimal(1)
999 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001000 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001001 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001002 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001003 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001004
Facundo Batistaee340e52008-05-02 17:39:00 +00001005 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1006 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001007 return
1008
1009def thfunc2(cls):
1010 d1 = Decimal(1)
1011 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001012 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001013 thiscontext = getcontext()
1014 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001015 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001016 cls.synchro.set()
1017 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001018
Facundo Batistaee340e52008-05-02 17:39:00 +00001019 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001020 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001021 return
1022
1023
1024class DecimalUseOfContextTest(unittest.TestCase):
1025 '''Unit tests for Use of Context cases in Decimal.'''
1026
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001027 try:
1028 import threading
1029 except ImportError:
1030 threading = None
1031
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001032 # Take care executing this test from IDLE, there's an issue in threading
1033 # that hangs IDLE and I couldn't find it
1034
1035 def test_threading(self):
1036 #Test the "threading isolation" of a Context.
1037
1038 self.synchro = threading.Event()
1039 self.finish1 = threading.Event()
1040 self.finish2 = threading.Event()
1041
1042 th1 = threading.Thread(target=thfunc1, args=(self,))
1043 th2 = threading.Thread(target=thfunc2, args=(self,))
1044
1045 th1.start()
1046 th2.start()
1047
1048 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001049 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001050 return
1051
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001052 if threading is None:
1053 del test_threading
1054
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001055
1056class DecimalUsabilityTest(unittest.TestCase):
1057 '''Unit tests for Usability cases of Decimal.'''
1058
1059 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001060
1061 da = Decimal('23.42')
1062 db = Decimal('23.42')
1063 dc = Decimal('45')
1064
1065 #two Decimals
1066 self.failUnless(dc > da)
1067 self.failUnless(dc >= da)
1068 self.failUnless(da < dc)
1069 self.failUnless(da <= dc)
1070 self.failUnless(da == db)
1071 self.failUnless(da != dc)
1072 self.failUnless(da <= db)
1073 self.failUnless(da >= db)
1074 self.assertEqual(cmp(dc,da), 1)
1075 self.assertEqual(cmp(da,dc), -1)
1076 self.assertEqual(cmp(da,db), 0)
1077
1078 #a Decimal and an int
1079 self.failUnless(dc > 23)
1080 self.failUnless(23 < dc)
1081 self.failUnless(dc == 45)
1082 self.assertEqual(cmp(dc,23), 1)
1083 self.assertEqual(cmp(23,dc), -1)
1084 self.assertEqual(cmp(dc,45), 0)
1085
1086 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001087 self.assertNotEqual(da, 'ugly')
1088 self.assertNotEqual(da, 32.7)
1089 self.assertNotEqual(da, object())
1090 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001091
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001092 # sortable
1093 a = map(Decimal, xrange(100))
1094 b = a[:]
1095 random.shuffle(a)
1096 a.sort()
1097 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001098
Facundo Batista353750c2007-09-13 18:13:15 +00001099 # with None
Ezio Melottid24b5d82010-08-03 04:08:59 +00001100 with _check_py3k_warnings():
1101 self.assertFalse(Decimal(1) < None)
1102 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001103
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001104 def test_copy_and_deepcopy_methods(self):
1105 d = Decimal('43.24')
1106 c = copy.copy(d)
1107 self.assertEqual(id(c), id(d))
1108 dc = copy.deepcopy(d)
1109 self.assertEqual(id(dc), id(d))
1110
1111 def test_hash_method(self):
1112 #just that it's hashable
1113 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001114
1115 test_values = [Decimal(sign*(2**m + n))
1116 for m in [0, 14, 15, 16, 17, 30, 31,
1117 32, 33, 62, 63, 64, 65, 66]
1118 for n in range(-10, 10)
1119 for sign in [-1, 1]]
1120 test_values.extend([
1121 Decimal("-0"), # zeros
1122 Decimal("0.00"),
1123 Decimal("-0.000"),
1124 Decimal("0E10"),
1125 Decimal("-0E12"),
1126 Decimal("10.0"), # negative exponent
1127 Decimal("-23.00000"),
1128 Decimal("1230E100"), # positive exponent
1129 Decimal("-4.5678E50"),
1130 # a value for which hash(n) != hash(n % (2**64-1))
1131 # in Python pre-2.6
1132 Decimal(2**64 + 2**32 - 1),
1133 # selection of values which fail with the old (before
1134 # version 2.6) long.__hash__
1135 Decimal("1.634E100"),
1136 Decimal("90.697E100"),
1137 Decimal("188.83E100"),
1138 Decimal("1652.9E100"),
1139 Decimal("56531E100"),
1140 ])
1141
1142 # check that hash(d) == hash(int(d)) for integral values
1143 for value in test_values:
1144 self.assertEqual(hash(value), hash(int(value)))
1145
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001146 #the same hash that to an int
1147 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001148 self.assertRaises(TypeError, hash, Decimal('NaN'))
1149 self.assert_(hash(Decimal('Inf')))
1150 self.assert_(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001151
Facundo Batista52b25792008-01-08 12:25:20 +00001152 # check that the value of the hash doesn't depend on the
1153 # current context (issue #1757)
1154 c = getcontext()
1155 old_precision = c.prec
1156 x = Decimal("123456789.1")
1157
1158 c.prec = 6
1159 h1 = hash(x)
1160 c.prec = 10
1161 h2 = hash(x)
1162 c.prec = 16
1163 h3 = hash(x)
1164
1165 self.assertEqual(h1, h2)
1166 self.assertEqual(h1, h3)
1167 c.prec = old_precision
1168
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001169 def test_min_and_max_methods(self):
1170
1171 d1 = Decimal('15.32')
1172 d2 = Decimal('28.5')
1173 l1 = 15
1174 l2 = 28
1175
1176 #between Decimals
1177 self.failUnless(min(d1,d2) is d1)
1178 self.failUnless(min(d2,d1) is d1)
1179 self.failUnless(max(d1,d2) is d2)
1180 self.failUnless(max(d2,d1) is d2)
1181
1182 #between Decimal and long
1183 self.failUnless(min(d1,l2) is d1)
1184 self.failUnless(min(l2,d1) is d1)
1185 self.failUnless(max(l1,d2) is d2)
1186 self.failUnless(max(d2,l1) is d2)
1187
1188 def test_as_nonzero(self):
1189 #as false
1190 self.failIf(Decimal(0))
1191 #as true
1192 self.failUnless(Decimal('0.372'))
1193
1194 def test_tostring_methods(self):
1195 #Test str and repr methods.
1196
1197 d = Decimal('15.32')
1198 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001199 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001201 # result type of string methods should be str, not unicode
1202 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1203 u'-0.0E100', u'-NaN001', u'-Inf']
1204
1205 for u in unicode_inputs:
1206 d = Decimal(u)
1207 self.assertEqual(type(str(d)), str)
1208 self.assertEqual(type(repr(d)), str)
1209 self.assertEqual(type(d.to_eng_string()), str)
1210
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001211 def test_tonum_methods(self):
1212 #Test float, int and long methods.
1213
1214 d1 = Decimal('66')
1215 d2 = Decimal('15.32')
1216
1217 #int
1218 self.assertEqual(int(d1), 66)
1219 self.assertEqual(int(d2), 15)
1220
1221 #long
1222 self.assertEqual(long(d1), 66)
1223 self.assertEqual(long(d2), 15)
1224
1225 #float
1226 self.assertEqual(float(d1), 66)
1227 self.assertEqual(float(d2), 15.32)
1228
1229 def test_eval_round_trip(self):
1230
1231 #with zero
1232 d = Decimal( (0, (0,), 0) )
1233 self.assertEqual(d, eval(repr(d)))
1234
1235 #int
1236 d = Decimal( (1, (4, 5), 0) )
1237 self.assertEqual(d, eval(repr(d)))
1238
1239 #float
1240 d = Decimal( (0, (4, 5, 3, 4), -2) )
1241 self.assertEqual(d, eval(repr(d)))
1242
1243 #weird
1244 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1245 self.assertEqual(d, eval(repr(d)))
1246
1247 def test_as_tuple(self):
1248
1249 #with zero
1250 d = Decimal(0)
1251 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1252
1253 #int
1254 d = Decimal(-45)
1255 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1256
1257 #complicated string
1258 d = Decimal("-4.34913534E-17")
1259 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1260
1261 #inf
1262 d = Decimal("Infinity")
1263 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1264
Facundo Batista9b5e2312007-10-19 19:25:57 +00001265 #leading zeros in coefficient should be stripped
1266 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1267 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1268 d = Decimal( (1, (0, 0, 0), 37) )
1269 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1270 d = Decimal( (1, (), 37) )
1271 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1272
1273 #leading zeros in NaN diagnostic info should be stripped
1274 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1275 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1276 d = Decimal( (1, (0, 0, 0), 'N') )
1277 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1278 d = Decimal( (1, (), 'n') )
1279 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1280
1281 #coefficient in infinity should be ignored
1282 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1283 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1284 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1285 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1286
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001287 def test_immutability_operations(self):
1288 # Do operations and check that it didn't change change internal objects.
1289
1290 d1 = Decimal('-25e55')
1291 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001292 d2 = Decimal('33e+33')
1293 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
1295 def checkSameDec(operation, useOther=False):
1296 if useOther:
1297 eval("d1." + operation + "(d2)")
1298 self.assertEqual(d1._sign, b1._sign)
1299 self.assertEqual(d1._int, b1._int)
1300 self.assertEqual(d1._exp, b1._exp)
1301 self.assertEqual(d2._sign, b2._sign)
1302 self.assertEqual(d2._int, b2._int)
1303 self.assertEqual(d2._exp, b2._exp)
1304 else:
1305 eval("d1." + operation + "()")
1306 self.assertEqual(d1._sign, b1._sign)
1307 self.assertEqual(d1._int, b1._int)
1308 self.assertEqual(d1._exp, b1._exp)
1309 return
1310
1311 Decimal(d1)
1312 self.assertEqual(d1._sign, b1._sign)
1313 self.assertEqual(d1._int, b1._int)
1314 self.assertEqual(d1._exp, b1._exp)
1315
1316 checkSameDec("__abs__")
1317 checkSameDec("__add__", True)
1318 checkSameDec("__div__", True)
1319 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001320 checkSameDec("__eq__", True)
1321 checkSameDec("__ne__", True)
1322 checkSameDec("__le__", True)
1323 checkSameDec("__lt__", True)
1324 checkSameDec("__ge__", True)
1325 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001326 checkSameDec("__float__")
1327 checkSameDec("__floordiv__", True)
1328 checkSameDec("__hash__")
1329 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001330 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001331 checkSameDec("__long__")
1332 checkSameDec("__mod__", True)
1333 checkSameDec("__mul__", True)
1334 checkSameDec("__neg__")
1335 checkSameDec("__nonzero__")
1336 checkSameDec("__pos__")
1337 checkSameDec("__pow__", True)
1338 checkSameDec("__radd__", True)
1339 checkSameDec("__rdiv__", True)
1340 checkSameDec("__rdivmod__", True)
1341 checkSameDec("__repr__")
1342 checkSameDec("__rfloordiv__", True)
1343 checkSameDec("__rmod__", True)
1344 checkSameDec("__rmul__", True)
1345 checkSameDec("__rpow__", True)
1346 checkSameDec("__rsub__", True)
1347 checkSameDec("__str__")
1348 checkSameDec("__sub__", True)
1349 checkSameDec("__truediv__", True)
1350 checkSameDec("adjusted")
1351 checkSameDec("as_tuple")
1352 checkSameDec("compare", True)
1353 checkSameDec("max", True)
1354 checkSameDec("min", True)
1355 checkSameDec("normalize")
1356 checkSameDec("quantize", True)
1357 checkSameDec("remainder_near", True)
1358 checkSameDec("same_quantum", True)
1359 checkSameDec("sqrt")
1360 checkSameDec("to_eng_string")
1361 checkSameDec("to_integral")
1362
Facundo Batista6c398da2007-09-17 17:30:13 +00001363 def test_subclassing(self):
1364 # Different behaviours when subclassing Decimal
1365
1366 class MyDecimal(Decimal):
1367 pass
1368
1369 d1 = MyDecimal(1)
1370 d2 = MyDecimal(2)
1371 d = d1 + d2
1372 self.assertTrue(type(d) is Decimal)
1373
1374 d = d1.max(d2)
1375 self.assertTrue(type(d) is Decimal)
1376
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001377 def test_implicit_context(self):
1378 # Check results when context given implicitly. (Issue 2478)
1379 c = getcontext()
1380 self.assertEqual(str(Decimal(0).sqrt()),
1381 str(c.sqrt(Decimal(0))))
1382
Mark Dickinsond8a2e2b2009-10-29 12:16:15 +00001383 def test_conversions_from_int(self):
1384 # Check that methods taking a second Decimal argument will
1385 # always accept an integer in place of a Decimal.
1386 self.assertEqual(Decimal(4).compare(3),
1387 Decimal(4).compare(Decimal(3)))
1388 self.assertEqual(Decimal(4).compare_signal(3),
1389 Decimal(4).compare_signal(Decimal(3)))
1390 self.assertEqual(Decimal(4).compare_total(3),
1391 Decimal(4).compare_total(Decimal(3)))
1392 self.assertEqual(Decimal(4).compare_total_mag(3),
1393 Decimal(4).compare_total_mag(Decimal(3)))
1394 self.assertEqual(Decimal(10101).logical_and(1001),
1395 Decimal(10101).logical_and(Decimal(1001)))
1396 self.assertEqual(Decimal(10101).logical_or(1001),
1397 Decimal(10101).logical_or(Decimal(1001)))
1398 self.assertEqual(Decimal(10101).logical_xor(1001),
1399 Decimal(10101).logical_xor(Decimal(1001)))
1400 self.assertEqual(Decimal(567).max(123),
1401 Decimal(567).max(Decimal(123)))
1402 self.assertEqual(Decimal(567).max_mag(123),
1403 Decimal(567).max_mag(Decimal(123)))
1404 self.assertEqual(Decimal(567).min(123),
1405 Decimal(567).min(Decimal(123)))
1406 self.assertEqual(Decimal(567).min_mag(123),
1407 Decimal(567).min_mag(Decimal(123)))
1408 self.assertEqual(Decimal(567).next_toward(123),
1409 Decimal(567).next_toward(Decimal(123)))
1410 self.assertEqual(Decimal(1234).quantize(100),
1411 Decimal(1234).quantize(Decimal(100)))
1412 self.assertEqual(Decimal(768).remainder_near(1234),
1413 Decimal(768).remainder_near(Decimal(1234)))
1414 self.assertEqual(Decimal(123).rotate(1),
1415 Decimal(123).rotate(Decimal(1)))
1416 self.assertEqual(Decimal(1234).same_quantum(1000),
1417 Decimal(1234).same_quantum(Decimal(1000)))
1418 self.assertEqual(Decimal('9.123').scaleb(-100),
1419 Decimal('9.123').scaleb(Decimal(-100)))
1420 self.assertEqual(Decimal(456).shift(-1),
1421 Decimal(456).shift(Decimal(-1)))
1422
1423 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1424 Decimal(-12).fma(Decimal(45), Decimal(67)))
1425 self.assertEqual(Decimal(-12).fma(45, 67),
1426 Decimal(-12).fma(Decimal(45), Decimal(67)))
1427 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1428 Decimal(-12).fma(Decimal(45), Decimal(67)))
1429
Facundo Batista6c398da2007-09-17 17:30:13 +00001430
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001431class DecimalPythonAPItests(unittest.TestCase):
1432
Raymond Hettinger45fd4762009-02-03 03:42:07 +00001433 def test_abc(self):
1434 self.assert_(issubclass(Decimal, numbers.Number))
1435 self.assert_(not issubclass(Decimal, numbers.Real))
1436 self.assert_(isinstance(Decimal(0), numbers.Number))
1437 self.assert_(not isinstance(Decimal(0), numbers.Real))
1438
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001439 def test_pickle(self):
1440 d = Decimal('-3.141590000')
1441 p = pickle.dumps(d)
1442 e = pickle.loads(p)
1443 self.assertEqual(d, e)
1444
Raymond Hettinger5548be22004-07-05 18:49:38 +00001445 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001446 for x in range(-250, 250):
1447 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001448 # should work the same as for floats
1449 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001450 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001451 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001452 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001453 self.assertEqual(Decimal(int(d)), r)
1454
Mark Dickinsonc05b7892009-09-08 19:22:18 +00001455 self.assertRaises(ValueError, int, Decimal('-nan'))
1456 self.assertRaises(ValueError, int, Decimal('snan'))
1457 self.assertRaises(OverflowError, int, Decimal('inf'))
1458 self.assertRaises(OverflowError, int, Decimal('-inf'))
1459
1460 self.assertRaises(ValueError, long, Decimal('-nan'))
1461 self.assertRaises(ValueError, long, Decimal('snan'))
1462 self.assertRaises(OverflowError, long, Decimal('inf'))
1463 self.assertRaises(OverflowError, long, Decimal('-inf'))
1464
Raymond Hettinger5a053642008-01-24 19:05:29 +00001465 def test_trunc(self):
1466 for x in range(-250, 250):
1467 s = '%0.2f' % (x / 100.0)
1468 # should work the same as for floats
1469 self.assertEqual(int(Decimal(s)), int(float(s)))
1470 # should work the same as to_integral in the ROUND_DOWN mode
1471 d = Decimal(s)
1472 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001473 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001474
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001475class ContextAPItests(unittest.TestCase):
1476
1477 def test_pickle(self):
1478 c = Context()
1479 e = pickle.loads(pickle.dumps(c))
1480 for k in vars(c):
1481 v1 = vars(c)[k]
1482 v2 = vars(e)[k]
1483 self.assertEqual(v1, v2)
1484
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001485 def test_equality_with_other_types(self):
1486 self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
1487 self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
1488
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001489 def test_copy(self):
1490 # All copies should be deep
1491 c = Context()
1492 d = c.copy()
1493 self.assertNotEqual(id(c), id(d))
1494 self.assertNotEqual(id(c.flags), id(d.flags))
1495 self.assertNotEqual(id(c.traps), id(d.traps))
1496
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001497class WithStatementTest(unittest.TestCase):
1498 # Can't do these as docstrings until Python 2.6
1499 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001500
1501 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001502 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001503 orig_ctx = getcontext()
1504 with localcontext() as enter_ctx:
1505 set_ctx = getcontext()
1506 final_ctx = getcontext()
1507 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1508 self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
1509 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1510
1511 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00001512 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00001513 orig_ctx = getcontext()
1514 new_ctx = Context(prec=42)
1515 with localcontext(new_ctx) as enter_ctx:
1516 set_ctx = getcontext()
1517 final_ctx = getcontext()
1518 self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
1519 self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
1520 self.assert_(new_ctx is not set_ctx, 'did not copy the context')
1521 self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
1522
Facundo Batista353750c2007-09-13 18:13:15 +00001523class ContextFlags(unittest.TestCase):
1524 def test_flags_irrelevant(self):
1525 # check that the result (numeric result + flags raised) of an
1526 # arithmetic operation doesn't depend on the current flags
1527
1528 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
1529 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
1530
1531 # operations that raise various flags, in the form (function, arglist)
1532 operations = [
1533 (context._apply, [Decimal("100E-1000000009")]),
1534 (context.sqrt, [Decimal(2)]),
1535 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
1536 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
1537 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
1538 ]
1539
1540 # try various flags individually, then a whole lot at once
1541 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
1542 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
1543
1544 for fn, args in operations:
1545 # find answer and flags raised using a clean context
1546 context.clear_flags()
1547 ans = fn(*args)
1548 flags = [k for k, v in context.flags.items() if v]
1549
1550 for extra_flags in flagsets:
1551 # set flags, before calling operation
1552 context.clear_flags()
1553 for flag in extra_flags:
1554 context._raise_error(flag)
1555 new_ans = fn(*args)
1556
1557 # flags that we expect to be set after the operation
1558 expected_flags = list(flags)
1559 for flag in extra_flags:
1560 if flag not in expected_flags:
1561 expected_flags.append(flag)
Ezio Melottid24b5d82010-08-03 04:08:59 +00001562 with _check_py3k_warnings(quiet=True):
1563 expected_flags.sort()
Facundo Batista353750c2007-09-13 18:13:15 +00001564
1565 # flags we actually got
1566 new_flags = [k for k,v in context.flags.items() if v]
Ezio Melottid24b5d82010-08-03 04:08:59 +00001567 with _check_py3k_warnings(quiet=True):
1568 new_flags.sort()
Facundo Batista353750c2007-09-13 18:13:15 +00001569
1570 self.assertEqual(ans, new_ans,
1571 "operation produces different answers depending on flags set: " +
1572 "expected %s, got %s." % (ans, new_ans))
1573 self.assertEqual(new_flags, expected_flags,
Ezio Melottid24b5d82010-08-03 04:08:59 +00001574 "operation raises different flags depending on flags set: " +
1575 "expected %s, got %s" % (expected_flags, new_flags))
Facundo Batista353750c2007-09-13 18:13:15 +00001576
1577def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001578 """ Execute the tests.
1579
Raymond Hettingered20ad82004-09-04 20:09:13 +00001580 Runs all arithmetic tests if arith is True or if the "decimal" resource
1581 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001582 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00001583
Neal Norwitzce4a9c92006-04-09 08:36:46 +00001584 init()
Facundo Batista353750c2007-09-13 18:13:15 +00001585 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00001586 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00001587 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00001588
Facundo Batista353750c2007-09-13 18:13:15 +00001589 if todo_tests is None:
1590 test_classes = [
1591 DecimalExplicitConstructionTest,
1592 DecimalImplicitConstructionTest,
1593 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00001594 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00001595 DecimalUseOfContextTest,
1596 DecimalUsabilityTest,
1597 DecimalPythonAPItests,
1598 ContextAPItests,
1599 DecimalTest,
1600 WithStatementTest,
1601 ContextFlags
1602 ]
1603 else:
1604 test_classes = [DecimalTest]
1605
1606 # Dynamically build custom test definition for each file in the test
1607 # directory and add the definitions to the DecimalTest class. This
1608 # procedure insures that new files do not get skipped.
1609 for filename in os.listdir(directory):
1610 if '.decTest' not in filename or filename.startswith("."):
1611 continue
1612 head, tail = filename.split('.')
1613 if todo_tests is not None and head not in todo_tests:
1614 continue
1615 tester = lambda self, f=filename: self.eval_file(directory + f)
1616 setattr(DecimalTest, 'test_' + head, tester)
1617 del filename, head, tail, tester
1618
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001619
Tim Peters46cc7022006-03-31 04:11:16 +00001620 try:
1621 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00001622 if todo_tests is None:
1623 import decimal as DecimalModule
1624 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00001625 finally:
1626 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001627
1628if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00001629 import optparse
1630 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
1631 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
1632 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
1633 (opt, args) = p.parse_args()
1634
1635 if opt.skip:
1636 test_main(arith=False, verbose=True)
1637 elif args:
1638 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001639 else:
Facundo Batista353750c2007-09-13 18:13:15 +00001640 test_main(arith=True, verbose=True)