From 7f78d7da9dd13d1f0068a292bcd1ee3c5439d5a8 Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Thu, 23 Aug 2018 15:19:29 -0700 Subject: Add tests --- .../TestExchangeInternals.sol | 19 +++++- .../contracts/src/2.0.0/test/TestLibs/TestLibs.sol | 34 ++++++++++ packages/contracts/test/exchange/internal.ts | 43 +++++++++++++ packages/contracts/test/exchange/libs.ts | 72 +++++++++++++++------- 4 files changed, 145 insertions(+), 23 deletions(-) diff --git a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol index 239dd10a8..5e2ae2f0e 100644 --- a/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol +++ b/packages/contracts/src/2.0.0/test/TestExchangeInternals/TestExchangeInternals.sol @@ -96,7 +96,7 @@ contract TestExchangeInternals is return getPartialAmountCeil(numerator, denominator, target); } - /// @dev Checks if rounding error > 0.1%. + /// @dev Checks if rounding error >= 0.1%. /// @param numerator Numerator. /// @param denominator Denominator. /// @param target Value to multiply with numerator/denominator. @@ -112,6 +112,23 @@ contract TestExchangeInternals is { return isRoundingError(numerator, denominator, target); } + + /// @dev Checks if rounding error >= 0.1%. + /// @param numerator Numerator. + /// @param denominator Denominator. + /// @param target Value to multiply with numerator/denominator. + /// @return Rounding error is present. + function publicIsRoundingErrorCeil( + uint256 numerator, + uint256 denominator, + uint256 target + ) + public + pure + returns (bool isError) + { + return isRoundingErrorCeil(numerator, denominator, target); + } /// @dev Updates state with results of a fill order. /// @param order that was filled. diff --git a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol index 4a99dd9c1..8c3d12226 100644 --- a/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/2.0.0/test/TestLibs/TestLibs.sol @@ -66,6 +66,23 @@ contract TestLibs is return partialAmount; } + function publicGetPartialAmountCeil( + uint256 numerator, + uint256 denominator, + uint256 target + ) + public + pure + returns (uint256 partialAmount) + { + partialAmount = getPartialAmountCeil( + numerator, + denominator, + target + ); + return partialAmount; + } + function publicIsRoundingError( uint256 numerator, uint256 denominator, @@ -83,6 +100,23 @@ contract TestLibs is return isError; } + function publicIsRoundingErrorCeil( + uint256 numerator, + uint256 denominator, + uint256 target + ) + public + pure + returns (bool isError) + { + isError = isRoundingErrorCeil( + numerator, + denominator, + target + ); + return isError; + } + function publicGetOrderHash(Order memory order) public view diff --git a/packages/contracts/test/exchange/internal.ts b/packages/contracts/test/exchange/internal.ts index 48e1e620c..0c6ab3707 100644 --- a/packages/contracts/test/exchange/internal.ts +++ b/packages/contracts/test/exchange/internal.ts @@ -294,6 +294,49 @@ describe('Exchange core internal functions', () => { ); }); + describe('isRoundingErrorCeil', async () => { + async function referenceIsRoundingErrorAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise { + if (denominator.eq(0)) { + throw divisionByZeroErrorForCall; + } + if (numerator.eq(0)) { + return false; + } + if (target.eq(0)) { + return false; + } + const product = numerator.mul(target); + const remainder = product.mod(denominator); + const error = denominator.sub(remainder).mod(denominator); + const errorTimes1000 = error.mul('1000'); + const isError = errorTimes1000.gt(product); + if (product.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + if (errorTimes1000.greaterThan(MAX_UINT256)) { + throw overflowErrorForCall; + } + return isError; + } + async function testIsRoundingErrorCeilAsync( + numerator: BigNumber, + denominator: BigNumber, + target: BigNumber, + ): Promise { + return testExchange.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target); + } + await testCombinatoriallyWithReferenceFuncAsync( + 'isRoundingErrorCeil', + referenceIsRoundingErrorAsync, + testIsRoundingErrorCeilAsync, + [uint256Values, uint256Values, uint256Values], + ); + }); + describe('updateFilledState', async () => { // Note(albrow): Since updateFilledState modifies the state by calling // sendTransaction, we must reset the state after each test. diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts index c08d62758..a5f31a498 100644 --- a/packages/contracts/test/exchange/libs.ts +++ b/packages/contracts/test/exchange/libs.ts @@ -71,29 +71,57 @@ describe('Exchange libs', () => { // combinatorial tests in test/exchange/internal. They test specific edge // cases that are not covered by the combinatorial tests. describe('LibMath', () => { - it('should return true if there is a rounding error of 0.1%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(999); - const target = new BigNumber(50); - // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% - const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); - expect(isRoundingError).to.be.true(); - }); - it('should return false if there is a rounding of 0.09%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(9991); - const target = new BigNumber(500); - // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09% - const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); - expect(isRoundingError).to.be.false(); + describe('isRoundingError', () => { + it('should return true if there is a rounding error of 0.1%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(999); + const target = new BigNumber(50); + // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1% + const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + it('should return false if there is a rounding of 0.09%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9991); + const target = new BigNumber(500); + // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09% + const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + it('should return true if there is a rounding error of 0.11%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(9989); + const target = new BigNumber(500); + // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011% + const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); }); - it('should return true if there is a rounding error of 0.11%', async () => { - const numerator = new BigNumber(20); - const denominator = new BigNumber(9989); - const target = new BigNumber(500); - // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011% - const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target); - expect(isRoundingError).to.be.true(); + describe('isRoundingErrorCeil', () => { + it('should return true if there is a rounding error of 0.1%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(1001); + const target = new BigNumber(50); + // rounding error = (ceil(20*50/1001) - (20*50/1001)) / (20*50/1001) = 0.1% + const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); + it('should return false if there is a rounding of 0.09%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(10009); + const target = new BigNumber(500); + // rounding error = (ceil(20*500/10009) - (20*500/10009)) / (20*500/10009) = 0.09% + const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.false(); + }); + it('should return true if there is a rounding error of 0.11%', async () => { + const numerator = new BigNumber(20); + const denominator = new BigNumber(10011); + const target = new BigNumber(500); + // rounding error = (ceil(20*500/10011) - (20*500/10011)) / (20*500/10011) = 0.11% + const isRoundingError = await libs.publicIsRoundingErrorCeil.callAsync(numerator, denominator, target); + expect(isRoundingError).to.be.true(); + }); }); }); -- cgit v1.2.3