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  }