123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #!/usr/bin/env python3
- """
- test.modtest_d.ut_obj: data object unit tests for the MMGen suite
- """
- from decimal import Decimal, getcontext
- from ..include.common import vmsg, cfg, parity_dev_amt
- from mmgen.protocol import init_proto
- def test_equal(res, chk):
- vmsg(f' checking {res}')
- if type(res) is type:
- assert res is chk, f'{res} != {chk}'
- else:
- assert res == chk, f'{res} != {chk}'
- def coinamt_test(cls, aa, bb, ut):
- def do(desc, res, chk):
- vmsg(f'{desc:10} = {res:<{cls.max_prec+10}} [{type(res).__name__}]')
- if chk is not None:
- assert res == chk, f'{res} != {chk}'
- assert type(res) is cls, f'{type(res).__name__} != {cls.__name__}'
- vmsg(f'\nTesting {cls.__name__} arithmetic operations...')
- A, B = (Decimal(aa), Decimal(bb))
- a, b = (cls(aa), cls(bb))
- do('A', A, None)
- do('B', B, None)
- do('a', a, A)
- do('b', b, B)
- do('b + a', b + a, B + A)
- do('sum([b,a])', sum([b, a]), B + A)
- do('b - a', b - a, B - A)
- do('b * a', b * a, B * A)
- do('b * A', b * A, B * A)
- do('B * a', B * a, B * A)
- do('b / a', b / a, cls(B / A, from_decimal=True))
- do('b / A', b / A, cls(B / A, from_decimal=True))
- do('a / b', a / b, cls(A / B, from_decimal=True))
- do('a * a / a', a * a / a, A * A / A)
- do('a * b / a', a * b / a, A * B / A)
- do('a * b / b', a * b / b, A * B / B)
- vmsg(f'\nChecking {cls.__name__} error handling...')
- bad_data = (
- ('negation', 'NotImplementedError', 'not implemented', lambda: -a),
- ('modulus', 'NotImplementedError', 'not implemented', lambda: b % a),
- ('floor division', 'NotImplementedError', 'not implemented', lambda: b // a),
- ('negative result', 'ObjectInitError', 'cannot be negative', lambda: a - b),
- ('operand type', 'TypeError', 'incorrect type', lambda: a + B),
- ('operand type', 'TypeError', 'incorrect type', lambda: b - A),
- )
- if cls.max_amt is not None:
- bad_data += (
- ('result', 'ObjectInitError', 'too large', lambda: b + b),
- ('result', 'ObjectInitError', 'too large', lambda: b * b),
- )
- ut.process_bad_data(bad_data)
- vmsg('OK')
- class unit_tests:
- altcoin_deps = ('coinamt_alt', 'coinamt_alt2')
- def coinamt(self, name, ut, desc='BTCAmt class'):
- from mmgen.amt import BTCAmt
- for cls, aa, bb in (
- (BTCAmt, '1.2345', '11234567.897'),
- ):
- coinamt_test(cls, aa, bb, ut)
- return True
- def coinamt_alt(self, name, ut, desc='LTCAmt, XMRAmt and ETHAmt classes'):
- from mmgen.amt import LTCAmt, XMRAmt, ETHAmt
- for cls, aa, bb in (
- (LTCAmt, '1.2345', '44938271.588'),
- (XMRAmt, '1.2345', '11234567.98765432'),
- (ETHAmt, '1.2345', '11234567.98765432123456'),
- ):
- coinamt_test(cls, aa, bb, ut)
- return True
- def coinamt2(self, name, ut, desc='CoinAmt class'):
- from decimal import Decimal
- proto = init_proto(cfg, 'btc', network='testnet', need_amt=True)
- test_equal(getcontext().prec, proto.decimal_prec)
- coin_amt = proto.coin_amt
- test_equal(coin_amt.__name__, 'BTCAmt')
- a = coin_amt('1.234')
- a2 = coin_amt('2.468')
- # addition with integer zero:
- b = a + 0 # __add__
- b = 0 + a # __radd__
- test_equal(sum([a, a]), a2) # __radd__ (sum() starts with integer 0)
- # __add__
- b = coin_amt('333.2456')
- test_equal(a + b, coin_amt('334.4796'))
- # __sub__
- test_equal(a - coin_amt('1'), coin_amt('0.234'))
- test_equal(coin_amt('2') - a, coin_amt('0.766'))
- # __mul__
- b = a * 2
- test_equal(type(b), coin_amt)
- test_equal(b, a2)
- # __rmul__
- b = 2 * a
- test_equal(type(b), coin_amt)
- test_equal(b, a2)
- # __truediv__
- b = a / 2
- test_equal(type(b), coin_amt)
- test_equal(b, coin_amt('0.617'))
- # __rtruediv__
- b = 2 / a
- test_equal(type(b), coin_amt)
- test_equal(b, coin_amt('1.62074554'))
- def bad1(): b = a + 1
- def bad2(): b = a - 1
- def bad3(): a + Decimal(1)
- def bad4(): b = a + 0.0
- def bad5(): b = a - 0.0
- def bad1r(): b = 1 + a
- def bad2r(): b = 3 - a
- def bad3r(): Decimal(1) + a
- def bad4r(): b = 0.0 + a
- def bad5r(): b = 0.0 - a
- def bad10(): b = coin_amt('1') - a
- def bad11(): b = a * -2
- def bad12(): b = a / -2
- def bad13(): b = a - coin_amt('2')
- def bad14(): b = -2 * a
- def bad15(): b = -2 / a
- def bad16(): b = coin_amt(a)
- vmsg('Testing error handling:')
- ut.process_bad_data(
- (
- ('addition with int', 'TypeError', 'incorrect type', bad1),
- ('subtraction with int', 'TypeError', 'incorrect type', bad2),
- ('addition with Decimal', 'TypeError', 'incorrect type', bad3),
- ('addition with float', 'TypeError', 'incorrect type', bad4),
- ('subtraction with float', 'TypeError', 'incorrect type', bad5),
- ('addition with int', 'TypeError', 'incorrect type', bad1r),
- ('subtraction with int', 'TypeError', 'incorrect type', bad2r),
- ('addition with Decimal', 'TypeError', 'incorrect type', bad3r),
- ('addition with float', 'TypeError', 'incorrect type', bad4r),
- ('subtraction with float', 'TypeError', 'incorrect type', bad5r),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad10),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad11),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad12),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad13),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad14),
- ('negative result', 'ObjectInitError', 'cannot be negative', bad15),
- ('double initialization', 'TypeError', 'is instance', bad16),
- ),
- pfx = '')
- return True
- def coinamt_alt2(self, name, ut, desc='CoinAmt class (altcoins)'):
- proto = init_proto(cfg, 'etc', network='regtest', need_amt=True)
- test_equal(getcontext().prec, proto.decimal_prec)
- coin_amt = proto.coin_amt
- dev_amt = coin_amt(parity_dev_amt, from_unit='wei')
- dev_amt_s = '1606938044258990275541962092341162602522202.993782792835301376'
- dev_amt_a1 = '1606938044258990275541962092341162602522203.993782792835301377'
- dev_amt_s1 = '1606938044258990275541962092341162602522201.993782792835301375'
- dev_amt_d2 = '803469022129495137770981046170581301261101.496891396417650688'
- dev_amt_d10 = '160693804425899027554196209234116260252220.299378279283530138'
- test_equal(str(dev_amt), dev_amt_s)
- addend = coin_amt('1.000000000000000001')
- test_equal(dev_amt + addend, coin_amt(dev_amt_a1))
- test_equal(dev_amt - addend, coin_amt(dev_amt_s1))
- test_equal(dev_amt / coin_amt('2'), coin_amt(dev_amt_d2))
- test_equal(dev_amt / coin_amt('10'), coin_amt(dev_amt_d10))
- test_equal(2 / coin_amt('0.3456'), coin_amt('5.787037037037037037'))
- test_equal(2.345 * coin_amt('2.3456'), coin_amt('5.500432000000000458'))
- return True
|