github.com/ethereum-optimism/optimism@v1.7.2/packages/core-utils/src/common/test-utils.ts (about) 1 import { expect } from 'chai' 2 import { BigNumber } from '@ethersproject/bignumber' 3 4 import { sleep } from './misc' 5 6 interface deviationRanges { 7 percentUpperDeviation?: number 8 percentLowerDeviation?: number 9 absoluteUpperDeviation?: number 10 absoluteLowerDeviation?: number 11 } 12 13 export const awaitCondition = async ( 14 cond: () => Promise<boolean>, 15 rate = 1000, 16 attempts = 10 17 ) => { 18 for (let i = 0; i < attempts; i++) { 19 const ok = await cond() 20 if (ok) { 21 return 22 } 23 24 await sleep(rate) 25 } 26 27 throw new Error('Timed out.') 28 } 29 30 /** 31 * Assert that a number lies within a custom defined range of the target. 32 */ 33 export const expectApprox = ( 34 actual: BigNumber | number, 35 target: BigNumber | number, 36 { 37 percentUpperDeviation, 38 percentLowerDeviation, 39 absoluteUpperDeviation, 40 absoluteLowerDeviation, 41 }: deviationRanges 42 ): void => { 43 actual = BigNumber.from(actual) 44 target = BigNumber.from(target) 45 46 // Ensure at least one deviation parameter is defined 47 const nonNullDeviations = 48 percentUpperDeviation || 49 percentLowerDeviation || 50 absoluteUpperDeviation || 51 absoluteLowerDeviation 52 if (!nonNullDeviations) { 53 throw new Error( 54 'Must define at least one parameter to limit the deviation of the actual value.' 55 ) 56 } 57 58 // Upper bound calculation. 59 let upper: BigNumber 60 // Set the two possible upper bounds if and only if they are defined. 61 const upperPcnt: BigNumber = !percentUpperDeviation 62 ? null 63 : target.mul(100 + percentUpperDeviation).div(100) 64 const upperAbs: BigNumber = !absoluteUpperDeviation 65 ? null 66 : target.add(absoluteUpperDeviation) 67 68 if (upperPcnt && upperAbs) { 69 // If both are set, take the lesser of the two upper bounds. 70 upper = upperPcnt.lte(upperAbs) ? upperPcnt : upperAbs 71 } else { 72 // Else take whichever is not undefined or set to null. 73 upper = upperPcnt || upperAbs 74 } 75 76 // Lower bound calculation. 77 let lower: BigNumber 78 // Set the two possible lower bounds if and only if they are defined. 79 const lowerPcnt: BigNumber = !percentLowerDeviation 80 ? null 81 : target.mul(100 - percentLowerDeviation).div(100) 82 const lowerAbs: BigNumber = !absoluteLowerDeviation 83 ? null 84 : target.sub(absoluteLowerDeviation) 85 if (lowerPcnt && lowerAbs) { 86 // If both are set, take the greater of the two lower bounds. 87 lower = lowerPcnt.gte(lowerAbs) ? lowerPcnt : lowerAbs 88 } else { 89 // Else take whichever is not undefined or set to null. 90 lower = lowerPcnt || lowerAbs 91 } 92 93 // Apply the assertions if they are non-null. 94 if (upper) { 95 expect( 96 actual.lte(upper), 97 `Actual value (${actual}) is greater than the calculated upper bound of (${upper})` 98 ).to.be.true 99 } 100 if (lower) { 101 expect( 102 actual.gte(lower), 103 `Actual value (${actual}) is less than the calculated lower bound of (${lower})` 104 ).to.be.true 105 } 106 }