From 1484ccc4049dc42a5a8a71713253894ade401573 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Thu, 7 Jun 2012 09:25:19 +0200 Subject: Decimal parameter conversion and normalization Parameter Decimal does not have a sufficient value checks. Some values cause Decimal parameter with a custom precision to crash with an unhandled exception. Improve parameter conversion and normalization operations to handle decimal exceptions more gracefully. Decimal parameter now also has new attributes enabling 2 new validation/normalization methods: * exponential: when False, decimal number is normalized to its non-exponential form * numberclass: a set of allowed decimal number classes (e.g. +Infinity, -Normal, ...) that are enforced for every Decimal parameter value https://fedorahosted.org/freeipa/ticket/2705 --- tests/test_ipalib/test_parameters.py | 93 +++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) (limited to 'tests/test_ipalib') diff --git a/tests/test_ipalib/test_parameters.py b/tests/test_ipalib/test_parameters.py index fc9569e73..0b6fae375 100644 --- a/tests/test_ipalib/test_parameters.py +++ b/tests/test_ipalib/test_parameters.py @@ -32,7 +32,7 @@ from tests.util import dummy_ugettext, assert_equal from tests.data import binary_bytes, utf8_bytes, unicode_str from ipalib import parameters, text, errors, config from ipalib.constants import TYPE_ERROR, CALLABLE_ERROR, NULLS -from ipalib.errors import ValidationError +from ipalib.errors import ValidationError, ConversionError from ipalib import _ from xmlrpclib import MAXINT, MININT @@ -1358,6 +1358,97 @@ class test_Decimal(ClassChecker): assert dummy.called() is True dummy.reset() + def test_precision(self): + """ + Test the `ipalib.parameters.Decimal` precision attribute + """ + # precission is None + param = self.cls('my_number') + + for value in (Decimal('0'), Decimal('4.4'), Decimal('4.67')): + assert_equal( + param(value), + value) + + # precision is 0 + param = self.cls('my_number', precision=0) + for original,expected in ((Decimal('0'), '0'), + (Decimal('1.1'), '1'), + (Decimal('4.67'), '5')): + assert_equal( + str(param(original)), + expected) + + # precision is 1 + param = self.cls('my_number', precision=1) + for original,expected in ((Decimal('0'), '0.0'), + (Decimal('1.1'), '1.1'), + (Decimal('4.67'), '4.7')): + assert_equal( + str(param(original)), + expected) + + # value has too many digits + param = self.cls('my_number', precision=1) + e = raises(ConversionError, param, '123456789012345678901234567890') + + assert str(e) == \ + "invalid 'my_number': quantize result has too many digits for current context" + + def test_exponential(self): + """ + Test the `ipalib.parameters.Decimal` exponential attribute + """ + param = self.cls('my_number', exponential=True) + for original,expected in ((Decimal('0'), '0'), + (Decimal('1E3'), '1E+3'), + (Decimal('3.4E2'), '3.4E+2')): + assert_equal( + str(param(original)), + expected) + + + param = self.cls('my_number', exponential=False) + for original,expected in ((Decimal('0'), '0'), + (Decimal('1E3'), '1000'), + (Decimal('3.4E2'), '340')): + assert_equal( + str(param(original)), + expected) + + def test_numberclass(self): + """ + Test the `ipalib.parameters.Decimal` numberclass attribute + """ + # test default value: '-Normal', '+Zero', '+Normal' + param = self.cls('my_number') + for value,raises_verror in ((Decimal('0'), False), + (Decimal('-0'), True), + (Decimal('1E8'), False), + (Decimal('-1.1'), False), + (Decimal('-Infinity'), True), + (Decimal('+Infinity'), True), + (Decimal('NaN'), True)): + if raises_verror: + raises(ValidationError, param, value) + else: + param(value) + + + param = self.cls('my_number', exponential=True, + numberclass=('-Normal', '+Zero', '+Infinity')) + for value,raises_verror in ((Decimal('0'), False), + (Decimal('-0'), True), + (Decimal('1E8'), True), + (Decimal('-1.1'), False), + (Decimal('-Infinity'), True), + (Decimal('+Infinity'), False), + (Decimal('NaN'), True)): + if raises_verror: + raises(ValidationError, param, value) + else: + param(value) + class test_AccessTime(ClassChecker): """ Test the `ipalib.parameters.AccessTime` class. -- cgit