@0x:contracts-integrations Added collections of function assertions
				
					
				
			This commit is contained in:
		@@ -1,5 +1,8 @@
 | 
			
		||||
import { PromiseWithTransactionHash } from '@0x/base-contract';
 | 
			
		||||
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
			
		||||
import { BlockchainTestsEnvironment } from '@0x/contracts-test-utils';
 | 
			
		||||
import { decodeThrownErrorAsRevertError } from '@0x/utils';
 | 
			
		||||
import { BlockParam, CallData, TransactionReceiptWithDecodedLogs, TxData } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
export interface ContractGetterFunction {
 | 
			
		||||
    callAsync: (...args: any[]) => Promise<any>;
 | 
			
		||||
@@ -9,18 +12,27 @@ export interface ContractWrapperFunction extends ContractGetterFunction {
 | 
			
		||||
    awaitTransactionSuccessAsync?: (...args: any[]) => PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Condition {
 | 
			
		||||
    before: (...args: any[]) => Promise<any>;
 | 
			
		||||
    after: (beforeInfo: any, result: Result, ...args: any[]) => Promise<any>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Result {
 | 
			
		||||
    data?: any;
 | 
			
		||||
    receipt?: TransactionReceiptWithDecodedLogs;
 | 
			
		||||
    success: boolean;
 | 
			
		||||
    receipt?: TransactionReceiptWithDecodedLogs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class FunctionAssertion {
 | 
			
		||||
export interface Condition {
 | 
			
		||||
    before?: (...args: any[]) => Promise<any>;
 | 
			
		||||
    after?: (beforeInfo: any, result: Result, ...args: any[]) => Promise<any>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RunResult {
 | 
			
		||||
    beforeInfo: any;
 | 
			
		||||
    afterInfo: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Assertion {
 | 
			
		||||
    runAsync: (...args: any[]) => Promise<any>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class FunctionAssertion implements Assertion {
 | 
			
		||||
    // A before and an after assertion that will be called around the wrapper function.
 | 
			
		||||
    public condition: Condition;
 | 
			
		||||
 | 
			
		||||
@@ -36,9 +48,9 @@ export class FunctionAssertion {
 | 
			
		||||
     * Runs the wrapped function and fails if the before or after assertions fail.
 | 
			
		||||
     * @param ...args The args to the contract wrapper function.
 | 
			
		||||
     */
 | 
			
		||||
    public async runAsync(...args: any[]): Promise<{ beforeInfo: any; afterInfo: any }> {
 | 
			
		||||
    public async runAsync(...args: any[]): Promise<RunResult> {
 | 
			
		||||
        // Call the before condition.
 | 
			
		||||
        const beforeInfo = await this.condition.before(...args);
 | 
			
		||||
        const beforeInfo = this.condition.before !== undefined ? await this.condition.before(...args) : undefined;
 | 
			
		||||
 | 
			
		||||
        // Initialize the callResult so that the default success value is true.
 | 
			
		||||
        let callResult: Result = { success: true };
 | 
			
		||||
@@ -58,7 +70,10 @@ export class FunctionAssertion {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Call the after condition.
 | 
			
		||||
        const afterInfo = await this.condition.after(beforeInfo, callResult, ...args);
 | 
			
		||||
        const afterInfo =
 | 
			
		||||
            this.condition.after !== undefined
 | 
			
		||||
                ? await this.condition.after(beforeInfo, callResult, ...args)
 | 
			
		||||
                : undefined;
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            beforeInfo,
 | 
			
		||||
@@ -66,3 +81,64 @@ export class FunctionAssertion {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Note: This can be treated like a normal `FunctionAssertion`.
 | 
			
		||||
 */
 | 
			
		||||
export class FunctionAssertionSequence {
 | 
			
		||||
    public readonly assertions: Assertion[] = [];
 | 
			
		||||
    public readonly inputGenerators: Array<() => any[]> = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up a set of function assertions equipped with generator functions.
 | 
			
		||||
     * A number can be specified for each assertion that will detail the frequency
 | 
			
		||||
     * that this assertion will be called relative to the other assertions in the
 | 
			
		||||
     * set.
 | 
			
		||||
     */
 | 
			
		||||
    constructor(assertionGenerators: [Assertion, (() => any[])][]) {
 | 
			
		||||
        for (const assertionGenerator of assertionGenerators) {
 | 
			
		||||
            this.assertions.push(assertionGenerator[0]);
 | 
			
		||||
            this.inputGenerators.push(assertionGenerator[1]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the functions in this assertion set in order.
 | 
			
		||||
     */
 | 
			
		||||
    public async runAsync(environment: BlockchainTestsEnvironment): Promise<void> {
 | 
			
		||||
        for (let i = 0; i < this.assertions.length; i++) {
 | 
			
		||||
            await this.assertions[i].runAsync(...this.inputGenerators[i]());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ContinuousFunctionAssertionSet {
 | 
			
		||||
    public readonly assertions: Assertion[] = [];
 | 
			
		||||
    public readonly inputGenerators: Array<() => any[]> = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set up a set of function assertions equipped with generator functions.
 | 
			
		||||
     * A number can be specified for each assertion that will detail the frequency
 | 
			
		||||
     * that this assertion will be called relative to the other assertions in the
 | 
			
		||||
     * set.
 | 
			
		||||
     */
 | 
			
		||||
    constructor(assertionGenerators: [Assertion, (() => any[]), number?][]) {
 | 
			
		||||
        for (const assertionGenerator of assertionGenerators) {
 | 
			
		||||
            const frequency = assertionGenerator[2] || 1;
 | 
			
		||||
            for (let i = 0; i < frequency; i++) {
 | 
			
		||||
                this.assertions.push(assertionGenerator[0]);
 | 
			
		||||
                this.inputGenerators.push(assertionGenerator[1]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the functions in this assertion set continuously.
 | 
			
		||||
     */
 | 
			
		||||
    public async runAsync(environment: BlockchainTestsEnvironment): Promise<void> {
 | 
			
		||||
        for (;;) {
 | 
			
		||||
            const randomIdx = Math.round(Math.random() * (this.assertions.length - 1));
 | 
			
		||||
            await this.assertions[randomIdx].runAsync(...this.inputGenerators[randomIdx]());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user