PHP WebShell

Текущая директория: /opt/BitGoJS/modules/blockapis/dist/test

Просмотр файла: UtxoApi.js

"use strict";
/**
 * This test suite iterates over a set of backends and test methods.
 *
 * For each backend and method, we test that the backend can fetch the resource.
 *
 * We then compare the normalized results from all backends to make sure they are the same.
 */
Object.defineProperty(exports, "__esModule", { value: true });
require("mocha");
const assert = require("assert");
const src_1 = require("../src");
const fixtures_1 = require("./fixtures");
const http_util_1 = require("./http.util");
function getTestAddresses(coinName) {
    switch (coinName) {
        case 'tbtc':
            return ['2NEhVzd2Lom5g7ZF5K1qYrgZLpXecniqHcE'];
    }
    throw new Error(`unsupported coin ${coinName}`);
}
const nonexistentTx = '1111111111111111111111111111111111111111111111111111111111111111';
function getTestTransactionIds(coinName) {
    switch (coinName) {
        case 'tbtc':
            return [
                '19c6cd6b7b8a91e1a63d759eedd2818877a624771d38e00c3ffcedfdd09afc50',
                '87f4cf756eef9979f0fb6a03db2ab2e0fd46060cf97714a990623093fe227a87',
                // unconfirmed (at time of caching)
                'fe38c68afcdd60dc0af11b692f81f512b886132b26165e404c0d0a30d7d6dc54',
                // not seen at all
                nonexistentTx,
            ];
    }
    throw new Error(`unsupported coin ${coinName}`);
}
/**
 * A test case for a UtxoApi method.
 */
class TestCase {
    /**
     * @param coinName - coin to test
     * @param methodName - method to test
     * @param args - method arguments
     */
    constructor(coinName, methodName, args) {
        this.coinName = coinName;
        this.methodName = methodName;
        this.args = args;
    }
    /**
     * Call the method on the given API.
     * @param api
     */
    func(api) {
        return api[this.methodName](...this.args);
    }
    /**
     * Get the fixture for this test case.
     * @param api
     * @param defaultValue
     */
    async getFixture(api, defaultValue) {
        const filename = [
            'UtxoApi',
            api.constructor.name,
            this.coinName,
            this.methodName,
            this.args.join(','),
            'json',
        ].join('.');
        return await (0, fixtures_1.getFixture)(`${__dirname}/fixtures/${filename}`, defaultValue);
    }
    /**
     * Get the fixture, but with the API-specific fields removed.
     * @param api
     */
    async getFixtureNormal(api) {
        if (this.methodName === 'getTransactionStatus') {
            // remove api-specific fields
            const blockInfo = (await this.getFixture(api));
            return {
                found: blockInfo.found,
                confirmed: blockInfo.confirmed,
                blockHeight: blockInfo.blockHeight,
            };
        }
        return await this.getFixture(api);
    }
    /** Certain calls produce non-200 responses, and we don't cache those. */
    expectError(api) {
        if (this.args[0] === nonexistentTx) {
            if (this.methodName === 'getTransactionStatus') {
                // Blockstream returns a 404 for missing transactions
                return api.constructor.name === 'BlockstreamApi' && !(0, http_util_1.isHttpEnabled)();
            }
            return true;
        }
        return false;
    }
    /**
     * @return a human-readable title for this test case.
     */
    title() {
        function elide(s, len) {
            return s.length > len ? `${s.slice(0, len)}...` : s;
        }
        return `${this.methodName}(${this.args.map((v) => elide(String(v), 4))})`;
    }
}
/**
 * @param coinName
 * @return a list of APIs to test.
 */
function getApis(coinName) {
    if (coinName === 'tbtc') {
        return [
            // BitGoApi.forCoin(coinName),
            src_1.BlockchairApi.forCoin(coinName, { httpClient: (0, http_util_1.getHttpClient)('blockchair') }),
            src_1.BlockstreamApi.forCoin(coinName, { httpClient: (0, http_util_1.getHttpClient)('blockstream') }),
        ];
    }
    return [];
}
/**
 * @param coinName
 * @return a list of test cases for the given coin.
 */
function getTestCases(coinName) {
    function getArguments(coinName, methodName) {
        switch (methodName) {
            case 'getTransactionHex':
            case 'getTransactionInputs':
            case 'getTransactionIO':
            case 'getTransactionSpends':
            case 'getTransactionStatus':
                return getTestTransactionIds(coinName).map((v) => [v]);
            case 'getUnspentsForAddresses':
                return getTestAddresses(coinName).map((v) => [[v]]);
        }
        throw new Error(`not implemented`);
    }
    const methods = [
        'getTransactionHex',
        'getTransactionInputs',
        'getTransactionIO',
        'getTransactionStatus',
        'getTransactionSpends',
        'getUnspentsForAddresses',
    ];
    return methods.flatMap((methodName) => getArguments(coinName, methodName).map((args) => new TestCase(coinName, methodName, args)));
}
/**
 * Set up fetch tests for the given API.
 *
 * @param api
 * @param coinName
 */
function runTestFetch(api, coinName) {
    getTestCases(coinName).forEach((testCase) => {
        describe(`${api.constructor.name} ${testCase.title()}`, function () {
            it('fetches resource', async function () {
                this.timeout(10000);
                if (testCase.expectError(api)) {
                    await assert.rejects(() => testCase.func(api));
                    return;
                }
                const resource = await testCase.func(api);
                (0, fixtures_1.deepStrictEqualJSON)(resource, await testCase.getFixture(api, resource));
            });
        });
    });
}
/**
 * Set up comparison tests for the given API.
 *
 * @param api
 * @param coinName
 */
function runTestCompare(api, coinName) {
    getTestCases(coinName).forEach((testCase) => {
        describe(`method ${testCase.title()}`, function () {
            getApis(coinName)
                .filter((otherApi) => api.constructor !== otherApi.constructor)
                .forEach((otherApi) => {
                if (testCase.expectError(api) || testCase.expectError(otherApi)) {
                    return;
                }
                it(`compare ${api.constructor.name} and ${otherApi.constructor.name}`, async function () {
                    (0, fixtures_1.deepStrictEqualJSON)(await testCase.getFixtureNormal(api), await testCase.getFixtureNormal(otherApi));
                });
            });
        });
    });
}
['tbtc'].forEach((coinName) => {
    getApis(coinName).forEach((api) => {
        runTestFetch(api, coinName);
    });
    getApis(coinName).forEach((api) => {
        runTestCompare(api, coinName);
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXR4b0FwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3Rlc3QvVXR4b0FwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUVILGlCQUFlO0FBQ2YsaUNBQWlDO0FBQ2pDLGdDQUFnRTtBQUNoRSx5Q0FBNkQ7QUFDN0QsMkNBQTJEO0FBRTNELFNBQVMsZ0JBQWdCLENBQUMsUUFBZ0I7SUFDeEMsUUFBUSxRQUFRLEVBQUUsQ0FBQztRQUNqQixLQUFLLE1BQU07WUFDVCxPQUFPLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRUQsTUFBTSxhQUFhLEdBQUcsa0VBQWtFLENBQUM7QUFFekYsU0FBUyxxQkFBcUIsQ0FBQyxRQUFnQjtJQUM3QyxRQUFRLFFBQVEsRUFBRSxDQUFDO1FBQ2pCLEtBQUssTUFBTTtZQUNULE9BQU87Z0JBQ0wsa0VBQWtFO2dCQUNsRSxrRUFBa0U7Z0JBQ2xFLG1DQUFtQztnQkFDbkMsa0VBQWtFO2dCQUNsRSxrQkFBa0I7Z0JBQ2xCLGFBQWE7YUFDZCxDQUFDO0lBQ04sQ0FBQztJQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsb0JBQW9CLFFBQVEsRUFBRSxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUlEOztHQUVHO0FBQ0gsTUFBTSxRQUFRO0lBQ1o7Ozs7T0FJRztJQUNILFlBQW1CLFFBQWdCLEVBQVMsVUFBeUIsRUFBUyxJQUFlO1FBQTFFLGFBQVEsR0FBUixRQUFRLENBQVE7UUFBUyxlQUFVLEdBQVYsVUFBVSxDQUFlO1FBQVMsU0FBSSxHQUFKLElBQUksQ0FBVztJQUFHLENBQUM7SUFFakc7OztPQUdHO0lBQ0gsSUFBSSxDQUFDLEdBQVk7UUFDZixPQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsSUFB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QUFDLFdBQVcsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLFFBQVEsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxLQUFLO29CQUMxRSxJQUFBLDhCQUFtQixFQUFDLE1BQU0sUUFBUSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxFQUFFLE1BQU0sUUFBUSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZHLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7SUFDNUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1FBQ2hDLFlBQVksQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDaEMsY0FBYyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNoQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGlzIHRlc3Qgc3VpdGUgaXRlcmF0ZXMgb3ZlciBhIHNldCBvZiBiYWNrZW5kcyBhbmQgdGVzdCBtZXRob2RzLlxuICpcbiAqIEZvciBlYWNoIGJhY2tlbmQgYW5kIG1ldGhvZCwgd2UgdGVzdCB0aGF0IHRoZSBiYWNrZW5kIGNhbiBmZXRjaCB0aGUgcmVzb3VyY2UuXG4gKlxuICogV2UgdGhlbiBjb21wYXJlIHRoZSBub3JtYWxpemVkIHJlc3VsdHMgZnJvbSBhbGwgYmFja2VuZHMgdG8gbWFrZSBzdXJlIHRoZXkgYXJlIHRoZSBzYW1lLlxuICovXG5cbmltcG9ydCAnbW9jaGEnO1xuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBCbG9ja2NoYWlyQXBpLCBCbG9ja3N0cmVhbUFwaSwgVXR4b0FwaSB9IGZyb20gJy4uL3NyYyc7XG5pbXBvcnQgeyBkZWVwU3RyaWN0RXF1YWxKU09OLCBnZXRGaXh0dXJlIH0gZnJvbSAnLi9maXh0dXJlcyc7XG5pbXBvcnQgeyBnZXRIdHRwQ2xpZW50LCBpc0h0dHBFbmFibGVkIH0gZnJvbSAnLi9odHRwLnV0aWwnO1xuXG5mdW5jdGlvbiBnZXRUZXN0QWRkcmVzc2VzKGNvaW5OYW1lOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHN3aXRjaCAoY29pbk5hbWUpIHtcbiAgICBjYXNlICd0YnRjJzpcbiAgICAgIHJldHVybiBbJzJORWhWemQyTG9tNWc3WkY1SzFxWXJnWkxwWGVjbmlxSGNFJ107XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBjb2luICR7Y29pbk5hbWV9YCk7XG59XG5cbmNvbnN0IG5vbmV4aXN0ZW50VHggPSAnMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSc7XG5cbmZ1bmN0aW9uIGdldFRlc3RUcmFuc2FjdGlvbklkcyhjb2luTmFtZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICBzd2l0Y2ggKGNvaW5OYW1lKSB7XG4gICAgY2FzZSAndGJ0Yyc6XG4gICAgICByZXR1cm4gW1xuICAgICAgICAnMTljNmNkNmI3YjhhOTFlMWE2M2Q3NTllZWRkMjgxODg3N2E2MjQ3NzFkMzhlMDBjM2ZmY2VkZmRkMDlhZmM1MCcsXG4gICAgICAgICc4N2Y0Y2Y3NTZlZWY5OTc5ZjBmYjZhMDNkYjJhYjJlMGZkNDYwNjBjZjk3NzE0YTk5MDYyMzA5M2ZlMjI3YTg3JyxcbiAgICAgICAgLy8gdW5jb25maXJtZWQgKGF0IHRpbWUgb2YgY2FjaGluZylcbiAgICAgICAgJ2ZlMzhjNjhhZmNkZDYwZGMwYWYxMWI2OTJmODFmNTEyYjg4NjEzMmIyNjE2NWU0MDRjMGQwYTMwZDdkNmRjNTQnLFxuICAgICAgICAvLyBub3Qgc2VlbiBhdCBhbGxcbiAgICAgICAgbm9uZXhpc3RlbnRUeCxcbiAgICAgIF07XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBjb2luICR7Y29pbk5hbWV9YCk7XG59XG5cbnR5cGUgTWV0aG9kQXJndW1lbnRzID0gdW5rbm93bltdO1xuXG4vKipcbiAqIEEgdGVzdCBjYXNlIGZvciBhIFV0eG9BcGkgbWV0aG9kLlxuICovXG5jbGFzcyBUZXN0Q2FzZTxUPiB7XG4gIC8qKlxuICAgKiBAcGFyYW0gY29pbk5hbWUgLSBjb2luIHRvIHRlc3RcbiAgICogQHBhcmFtIG1ldGhvZE5hbWUgLSBtZXRob2QgdG8gdGVzdFxuICAgKiBAcGFyYW0gYXJncyAtIG1ldGhvZCBhcmd1bWVudHNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBjb2luTmFtZTogc3RyaW5nLCBwdWJsaWMgbWV0aG9kTmFtZToga2V5b2YgVXR4b0FwaSwgcHVibGljIGFyZ3M6IHVua25vd25bXSkge31cblxuICAvKipcbiAgICogQ2FsbCB0aGUgbWV0aG9kIG9uIHRoZSBnaXZlbiBBUEkuXG4gICAqIEBwYXJhbSBhcGlcbiAgICovXG4gIGZ1bmMoYXBpOiBVdHhvQXBpKSB7XG4gICAgcmV0dXJuIChhcGlbdGhpcy5tZXRob2ROYW1lXSBhcyBhbnkpKC4uLnRoaXMuYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBmaXh0dXJlIGZvciB0aGlzIHRlc3QgY2FzZS5cbiAgICogQHBhcmFtIGFwaVxuICAgKiBAcGFyYW0gZGVmYXVsdFZhbHVlXG4gICAqL1xuICBhc3luYyBnZXRGaXh0dXJlKGFwaTogVXR4b0FwaSwgZGVmYXVsdFZhbHVlPzogVCk6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGZpbGVuYW1lID0gW1xuICAgICAgJ1V0eG9BcGknLFxuICAgICAgYXBpLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgICB0aGlzLmNvaW5OYW1lLFxuICAgICAgdGhpcy5tZXRob2ROYW1lLFxuICAgICAgdGhpcy5hcmdzLmpvaW4oJywnKSxcbiAgICAgICdqc29uJyxcbiAgICBdLmpvaW4oJy4nKTtcbiAgICByZXR1cm4gYXdhaXQgZ2V0Rml4dHVyZShgJHtfX2Rpcm5hbWV9L2ZpeHR1cmVzLyR7ZmlsZW5hbWV9YCwgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGZpeHR1cmUsIGJ1dCB3aXRoIHRoZSBBUEktc3BlY2lmaWMgZmllbGRzIHJlbW92ZWQuXG4gICAqIEBwYXJhbSBhcGlcbiAgICovXG4gIGFzeW5jIGdldEZpeHR1cmVOb3JtYWwoYXBpOiBVdHhvQXBpKTogUHJvbWlzZTxUPiB7XG4gICAgaWYgKHRoaXMubWV0aG9kTmFtZSA9PT0gJ2dldFRyYW5zYWN0aW9uU3RhdHVzJykge1xuICAgICAgLy8gcmVtb3ZlIGFwaS1zcGVjaWZpYyBmaWVsZHNcbiAgICAgIGNvbnN0IGJsb2NrSW5mbyA9IChhd2FpdCB0aGlzLmdldEZpeHR1cmUoYXBpKSkgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGZvdW5kOiBibG9ja0luZm8uZm91bmQsXG4gICAgICAgIGNvbmZpcm1lZDogYmxvY2tJbmZvLmNvbmZpcm1lZCxcbiAgICAgICAgYmxvY2tIZWlnaHQ6IGJsb2NrSW5mby5ibG9ja0hlaWdodCxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBUO1xuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5nZXRGaXh0dXJlKGFwaSk7XG4gIH1cblxuICAvKiogQ2VydGFpbiBjYWxscyBwcm9kdWNlIG5vbi0yMDAgcmVzcG9uc2VzLCBhbmQgd2UgZG9uJ3QgY2FjaGUgdGhvc2UuICovXG4gIGV4cGVjdEVycm9yKGFwaTogVXR4b0FwaSk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmFyZ3NbMF0gPT09IG5vbmV4aXN0ZW50VHgpIHtcbiAgICAgIGlmICh0aGlzLm1ldGhvZE5hbWUgPT09ICdnZXRUcmFuc2FjdGlvblN0YXR1cycpIHtcbiAgICAgICAgLy8gQmxvY2tzdHJlYW0gcmV0dXJucyBhIDQwNCBmb3IgbWlzc2luZyB0cmFuc2FjdGlvbnNcbiAgICAgICAgcmV0dXJuIGFwaS5jb25zdHJ1Y3Rvci5uYW1lID09PSAnQmxvY2tzdHJlYW1BcGknICYmICFpc0h0dHBFbmFibGVkKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4gYSBodW1hbi1yZWFkYWJsZSB0aXRsZSBmb3IgdGhpcyB0ZXN0IGNhc2UuXG4gICAqL1xuICB0aXRsZSgpOiBzdHJpbmcge1xuICAgIGZ1bmN0aW9uIGVsaWRlKHM6IHN0cmluZywgbGVuOiBudW1iZXIpIHtcbiAgICAgIHJldHVybiBzLmxlbmd0aCA+IGxlbiA/IGAke3Muc2xpY2UoMCwgbGVuKX0uLi5gIDogcztcbiAgICB9XG4gICAgcmV0dXJuIGAke3RoaXMubWV0aG9kTmFtZX0oJHt0aGlzLmFyZ3MubWFwKCh2KSA9PiBlbGlkZShTdHJpbmcodiksIDQpKX0pYDtcbiAgfVxufVxuXG4vKipcbiAqIEBwYXJhbSBjb2luTmFtZVxuICogQHJldHVybiBhIGxpc3Qgb2YgQVBJcyB0byB0ZXN0LlxuICovXG5mdW5jdGlvbiBnZXRBcGlzKGNvaW5OYW1lOiBzdHJpbmcpOiBVdHhvQXBpW10ge1xuICBpZiAoY29pbk5hbWUgPT09ICd0YnRjJykge1xuICAgIHJldHVybiBbXG4gICAgICAvLyBCaXRHb0FwaS5mb3JDb2luKGNvaW5OYW1lKSxcbiAgICAgIEJsb2NrY2hhaXJBcGkuZm9yQ29pbihjb2luTmFtZSwgeyBodHRwQ2xpZW50OiBnZXRIdHRwQ2xpZW50KCdibG9ja2NoYWlyJykgfSksXG4gICAgICBCbG9ja3N0cmVhbUFwaS5mb3JDb2luKGNvaW5OYW1lLCB7IGh0dHBDbGllbnQ6IGdldEh0dHBDbGllbnQoJ2Jsb2Nrc3RyZWFtJykgfSksXG4gICAgXTtcbiAgfVxuICByZXR1cm4gW107XG59XG5cbi8qKlxuICogQHBhcmFtIGNvaW5OYW1lXG4gKiBAcmV0dXJuIGEgbGlzdCBvZiB0ZXN0IGNhc2VzIGZvciB0aGUgZ2l2ZW4gY29pbi5cbiAqL1xuZnVuY3Rpb24gZ2V0VGVzdENhc2VzKGNvaW5OYW1lOiBzdHJpbmcpOiBUZXN0Q2FzZTx1bmtub3duPltdIHtcbiAgZnVuY3Rpb24gZ2V0QXJndW1lbnRzKGNvaW5OYW1lOiBzdHJpbmcsIG1ldGhvZE5hbWU6IGtleW9mIFV0eG9BcGkpOiBNZXRob2RBcmd1bWVudHNbXSB7XG4gICAgc3dpdGNoIChtZXRob2ROYW1lKSB7XG4gICAgICBjYXNlICdnZXRUcmFuc2FjdGlvbkhleCc6XG4gICAgICBjYXNlICdnZXRUcmFuc2FjdGlvbklucHV0cyc6XG4gICAgICBjYXNlICdnZXRUcmFuc2FjdGlvbklPJzpcbiAgICAgIGNhc2UgJ2dldFRyYW5zYWN0aW9uU3BlbmRzJzpcbiAgICAgIGNhc2UgJ2dldFRyYW5zYWN0aW9uU3RhdHVzJzpcbiAgICAgICAgcmV0dXJuIGdldFRlc3RUcmFuc2FjdGlvbklkcyhjb2luTmFtZSkubWFwKCh2KSA9PiBbdl0pO1xuICAgICAgY2FzZSAnZ2V0VW5zcGVudHNGb3JBZGRyZXNzZXMnOlxuICAgICAgICByZXR1cm4gZ2V0VGVzdEFkZHJlc3Nlcyhjb2luTmFtZSkubWFwKCh2KSA9PiBbW3ZdXSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgbm90IGltcGxlbWVudGVkYCk7XG4gIH1cblxuICBjb25zdCBtZXRob2RzOiAoa2V5b2YgVXR4b0FwaSlbXSA9IFtcbiAgICAnZ2V0VHJhbnNhY3Rpb25IZXgnLFxuICAgICdnZXRUcmFuc2FjdGlvbklucHV0cycsXG4gICAgJ2dldFRyYW5zYWN0aW9uSU8nLFxuICAgICdnZXRUcmFuc2FjdGlvblN0YXR1cycsXG4gICAgJ2dldFRyYW5zYWN0aW9uU3BlbmRzJyxcbiAgICAnZ2V0VW5zcGVudHNGb3JBZGRyZXNzZXMnLFxuICBdO1xuXG4gIHJldHVybiBtZXRob2RzLmZsYXRNYXAoKG1ldGhvZE5hbWUpID0+XG4gICAgZ2V0QXJndW1lbnRzKGNvaW5OYW1lLCBtZXRob2ROYW1lKS5tYXAoKGFyZ3MpID0+IG5ldyBUZXN0Q2FzZShjb2luTmFtZSwgbWV0aG9kTmFtZSwgYXJncykpXG4gICk7XG59XG5cbi8qKlxuICogU2V0IHVwIGZldGNoIHRlc3RzIGZvciB0aGUgZ2l2ZW4gQVBJLlxuICpcbiAqIEBwYXJhbSBhcGlcbiAqIEBwYXJhbSBjb2luTmFtZVxuICovXG5mdW5jdGlvbiBydW5UZXN0RmV0Y2goYXBpOiBVdHhvQXBpLCBjb2luTmFtZTogc3RyaW5nKSB7XG4gIGdldFRlc3RDYXNlcyhjb2luTmFtZSkuZm9yRWFjaCgodGVzdENhc2UpID0+IHtcbiAgICBkZXNjcmliZShgJHthcGkuY29uc3RydWN0b3IubmFtZX0gJHt0ZXN0Q2FzZS50aXRsZSgpfWAsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdmZXRjaGVzIHJlc291cmNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRpbWVvdXQoMTBfMDAwKTtcbiAgICAgICAgaWYgKHRlc3RDYXNlLmV4cGVjdEVycm9yKGFwaSkpIHtcbiAgICAgICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiB0ZXN0Q2FzZS5mdW5jKGFwaSkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IHRlc3RDYXNlLmZ1bmMoYXBpKTtcbiAgICAgICAgZGVlcFN0cmljdEVxdWFsSlNPTihyZXNvdXJjZSwgYXdhaXQgdGVzdENhc2UuZ2V0Rml4dHVyZShhcGksIHJlc291cmNlKSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogU2V0IHVwIGNvbXBhcmlzb24gdGVzdHMgZm9yIHRoZSBnaXZlbiBBUEkuXG4gKlxuICogQHBhcmFtIGFwaVxuICogQHBhcmFtIGNvaW5OYW1lXG4gKi9cbmZ1bmN0aW9uIHJ1blRlc3RDb21wYXJlKGFwaTogVXR4b0FwaSwgY29pbk5hbWU6IHN0cmluZykge1xuICBnZXRUZXN0Q2FzZXMoY29pbk5hbWUpLmZvckVhY2goKHRlc3RDYXNlKSA9PiB7XG4gICAgZGVzY3JpYmUoYG1ldGhvZCAke3Rlc3RDYXNlLnRpdGxlKCl9YCwgZnVuY3Rpb24gKCkge1xuICAgICAgZ2V0QXBpcyhjb2luTmFtZSlcbiAgICAgICAgLmZpbHRlcigob3RoZXJBcGkpID0+IGFwaS5jb25zdHJ1Y3RvciAhPT0gb3RoZXJBcGkuY29uc3RydWN0b3IpXG4gICAgICAgIC5mb3JFYWNoKChvdGhlckFwaSkgPT4ge1xuICAgICAgICAgIGlmICh0ZXN0Q2FzZS5leHBlY3RFcnJvcihhcGkpIHx8IHRlc3RDYXNlLmV4cGVjdEVycm9yKG90aGVyQXBpKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpdChgY29tcGFyZSAke2FwaS5jb25zdHJ1Y3Rvci5uYW1lfSBhbmQgJHtvdGhlckFwaS5jb25zdHJ1Y3Rvci5uYW1lfWAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGRlZXBTdHJpY3RFcXVhbEpTT04oYXdhaXQgdGVzdENhc2UuZ2V0Rml4dHVyZU5vcm1hbChhcGkpLCBhd2FpdCB0ZXN0Q2FzZS5nZXRGaXh0dXJlTm9ybWFsKG90aGVyQXBpKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn1cblxuWyd0YnRjJ10uZm9yRWFjaCgoY29pbk5hbWUpID0+IHtcbiAgZ2V0QXBpcyhjb2luTmFtZSkuZm9yRWFjaCgoYXBpKSA9PiB7XG4gICAgcnVuVGVzdEZldGNoKGFwaSwgY29pbk5hbWUpO1xuICB9KTtcbiAgZ2V0QXBpcyhjb2luTmFtZSkuZm9yRWFjaCgoYXBpKSA9PiB7XG4gICAgcnVuVGVzdENvbXBhcmUoYXBpLCBjb2luTmFtZSk7XG4gIH0pO1xufSk7XG4iXX0=

Выполнить команду


Для локальной разработки. Не используйте в интернете!