testcafe
Version:
Automated browser testing for the modern web development stack.
203 lines • 37 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const async_event_emitter_1 = __importDefault(require("../utils/async-event-emitter"));
const test_run_controller_1 = __importDefault(require("./test-run-controller"));
const session_controller_1 = __importDefault(require("../test-run/session-controller"));
const browser_job_result_1 = __importDefault(require("./browser-job-result"));
const test_run_hook_controller_1 = __importDefault(require("./test-run-hook-controller"));
var BrowserJobStatus;
(function (BrowserJobStatus) {
BrowserJobStatus[BrowserJobStatus["initialized"] = 0] = "initialized";
BrowserJobStatus[BrowserJobStatus["starting"] = 1] = "starting";
BrowserJobStatus[BrowserJobStatus["started"] = 2] = "started";
})(BrowserJobStatus || (BrowserJobStatus = {}));
class BrowserJob extends async_event_emitter_1.default {
constructor({ tests, browserConnections, proxy, screenshots, warningLog, fixtureHookController, opts, messageBus, }) {
var _a;
super();
this._status = BrowserJobStatus.initialized;
this._startTime = new Date();
this._total = 0;
this._passed = 0;
this._opts = opts;
this._proxy = proxy;
this.browserConnections = browserConnections;
this._screenshots = screenshots;
this.warningLog = warningLog;
this.fixtureHookController = fixtureHookController;
this._result = null;
this._messageBus = messageBus;
this._testRunHook = new test_run_hook_controller_1.default(tests, (_a = opts.hooks) === null || _a === void 0 ? void 0 : _a.testRun);
this._testRunControllerQueue = tests.map((test, index) => this._createTestRunController(test, index));
this._disableConcurrencyQueue = {};
this._completionQueue = [];
this._reportsPending = [];
this._connectionErrorListener = (error) => this._setResult(browser_job_result_1.default.errored, error);
this._resolveWaitingLastTestInFixture = null;
this.browserConnections.map(bc => bc.once('error', this._connectionErrorListener));
}
_createTestRunController(test, index) {
const testRunController = new test_run_controller_1.default({
test,
index: index + 1,
proxy: this._proxy,
screenshots: this._screenshots,
warningLog: this.warningLog,
fixtureHookController: this.fixtureHookController,
opts: this._opts,
messageBus: this._messageBus,
testRunHook: this._testRunHook,
});
testRunController.on('test-run-create', async (testRunInfo) => {
await this.emit('test-run-create', testRunInfo);
});
testRunController.on('test-run-ready', async () => {
await this.emit('test-run-ready', testRunController);
});
testRunController.on('test-run-restart', async () => this._onTestRunRestart(testRunController));
testRunController.on('test-run-before-done', async () => {
await this.emit('test-run-before-done', testRunController);
});
testRunController.on('test-run-done', async () => this._onTestRunDone(testRunController));
testRunController.on('test-action-done', async (args) => {
await this.emit('test-action-done', args);
});
return testRunController;
}
async _setResult(status, data) {
if (this._result)
return;
this._result = { status, data };
this.browserConnections.forEach(bc => bc.removeListener('error', this._connectionErrorListener));
await Promise.all(this.browserConnections.map(bc => bc.reportJobResult(this._result.status, this._result.data)));
}
_addToCompletionQueue(testRunInfo) {
this._completionQueue.push(testRunInfo);
}
_removeFromCompletionQueue(testRunInfo) {
(0, lodash_1.pull)(this._completionQueue, testRunInfo);
}
async _onTestRunRestart(testRunController) {
const conectionId = testRunController.testRun.browserConnection.id;
this._removeFromCompletionQueue(testRunController);
this._getTestControllerQueue(conectionId).unshift(testRunController);
await this.emit('test-run-restart', testRunController);
}
async _onTestRunDone(testRunController) {
testRunController.testRun.finishTime = new Date();
this._total++;
if (!testRunController.testRun.errs.length)
this._passed++;
while (this._completionQueue.length && this._completionQueue[0].done) {
testRunController = this._completionQueue.shift();
await this.emit('test-run-done', testRunController.testRun);
(0, lodash_1.pull)(this._reportsPending, testRunController);
if (!this._reportsPending.length && this._resolveWaitingLastTestInFixture) {
this._resolveWaitingLastTestInFixture();
this._resolveWaitingLastTestInFixture = null;
}
}
if (!this._completionQueue.length && !this.hasQueuedTestRuns) {
if (!this._opts.live)
session_controller_1.default.closeSession(testRunController.testRun);
this
._setResult(browser_job_result_1.default.done, { total: this._total, passed: this._passed })
.then(() => this.emit('done'));
}
}
async _isNextTestRunAvailable(testRunController) {
// NOTE: event task start is currently executing,
// so test run is temporary blocked
if (this._status === BrowserJobStatus.starting)
return false;
// NOTE: before hook for test run fixture is currently
// executing, so test run is temporary blocked
const isBlocked = testRunController.blocked;
const isConcurrency = this._opts.concurrency > 1;
const hasIncompleteTestRuns = this._completionQueue.some(controller => !controller.done);
const needWaitLastTestInFixture = this._reportsPending.some(controller => controller.test.fixture !== testRunController.test.fixture);
if (isBlocked || (hasIncompleteTestRuns || needWaitLastTestInFixture) && !isConcurrency) {
const disablePageReloads = testRunController.test.disablePageReloads ||
this._opts.disablePageReloads && testRunController.test.disablePageReloads !== false;
if (!needWaitLastTestInFixture || !disablePageReloads)
return false;
// NOTE: if we have `disablePageReloads` enabled and the next test is from next
// fixture, then we need to wait until all reporters finished to prevent
// redirecting to the `idle` page
await new Promise(resolve => {
this._resolveWaitingLastTestInFixture = resolve;
});
}
return true;
}
_getTestControllerQueue(connectionId) {
var _a;
if ((_a = this._disableConcurrencyQueue[connectionId]) === null || _a === void 0 ? void 0 : _a.length)
return this._disableConcurrencyQueue[connectionId];
return this._testRunControllerQueue;
}
_getNextFixtureFirstTestIndex(fixtureId) {
const nextFixtureFirstTestIndex = this._testRunControllerQueue.findIndex(testRun => { var _a; return ((_a = testRun.test.fixture) === null || _a === void 0 ? void 0 : _a.id) !== fixtureId; });
return nextFixtureFirstTestIndex === -1 ? this._testRunControllerQueue.length : nextFixtureFirstTestIndex;
}
_updateTestControllerQueues({ test }, connectionId) {
var _a, _b;
if (!test.disableConcurrency || ((_a = this._disableConcurrencyQueue[connectionId]) === null || _a === void 0 ? void 0 : _a.length))
return;
this._disableConcurrencyQueue[connectionId] = this._testRunControllerQueue.splice(0, this._getNextFixtureFirstTestIndex((_b = test.fixture) === null || _b === void 0 ? void 0 : _b.id));
}
// API
get hasQueuedTestRuns() {
if (this._testRunControllerQueue.length)
return true;
for (const connectionId in this._disableConcurrencyQueue) {
if (this._disableConcurrencyQueue[connectionId].length)
return true;
}
return false;
}
get currentTestRun() {
return this._completionQueue.length ? this._completionQueue[0].testRun : null;
}
async popNextTestRunInfo(connection) {
while (this.hasQueuedTestRuns) {
const currentQueue = this._getTestControllerQueue(connection.id);
const testRunController = currentQueue[0];
if (!testRunController)
break;
const isNextTestRunAvailable = await this._isNextTestRunAvailable(testRunController);
if (!isNextTestRunAvailable)
break;
this._reportsPending.push(testRunController);
currentQueue.shift();
this._updateTestControllerQueues(testRunController, connection.id);
this._addToCompletionQueue(testRunController);
if (this._status === BrowserJobStatus.initialized) {
this._status = BrowserJobStatus.starting;
this._startTime = new Date();
await this.emit('start', this._startTime);
this._status = BrowserJobStatus.started;
}
const testRunUrl = await testRunController.start(connection, this._startTime);
if (testRunUrl) {
return {
testRunId: testRunController.testRun.id,
url: testRunUrl,
};
}
}
return null;
}
abort() {
this.clearListeners();
this._setResult(browser_job_result_1.default.aborted);
this.browserConnections.map(bc => bc.removeJob(this));
}
}
exports.default = BrowserJob;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci1qb2IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2Jyb3dzZXItam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQXdDO0FBQ3hDLHVGQUE2RDtBQUM3RCxnRkFBc0Q7QUFDdEQsd0ZBQStEO0FBUS9ELDhFQUFvRDtBQUdwRCwwRkFBK0Q7QUFXL0QsSUFBSyxnQkFBbUQ7QUFBeEQsV0FBSyxnQkFBZ0I7SUFBRyxxRUFBVyxDQUFBO0lBQUUsK0RBQVEsQ0FBQTtJQUFFLDZEQUFPLENBQUE7QUFBQyxDQUFDLEVBQW5ELGdCQUFnQixLQUFoQixnQkFBZ0IsUUFBbUM7QUFFeEQsTUFBcUIsVUFBVyxTQUFRLDZCQUFpQjtJQXFCckQsWUFBb0IsRUFDaEIsS0FBSyxFQUNMLGtCQUFrQixFQUNsQixLQUFLLEVBQ0wsV0FBVyxFQUNYLFVBQVUsRUFDVixxQkFBcUIsRUFDckIsSUFBSSxFQUNKLFVBQVUsR0FDRzs7UUFDYixLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsV0FBVyxDQUFDO1FBQzVDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUU3QixJQUFJLENBQUMsTUFBTSxHQUFrQixDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLE9BQU8sR0FBaUIsQ0FBQyxDQUFDO1FBQy9CLElBQUksQ0FBQyxLQUFLLEdBQW1CLElBQUksQ0FBQztRQUNsQyxJQUFJLENBQUMsTUFBTSxHQUFrQixLQUFLLENBQUM7UUFDbkMsSUFBSSxDQUFDLGtCQUFrQixHQUFNLGtCQUFrQixDQUFDO1FBQ2hELElBQUksQ0FBQyxZQUFZLEdBQVksV0FBVyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxVQUFVLEdBQWMsVUFBVSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxxQkFBcUIsQ0FBQztRQUNuRCxJQUFJLENBQUMsT0FBTyxHQUFpQixJQUFJLENBQUM7UUFDbEMsSUFBSSxDQUFDLFdBQVcsR0FBYSxVQUFVLENBQUM7UUFDeEMsSUFBSSxDQUFDLFlBQVksR0FBWSxJQUFJLGtDQUFxQixDQUFDLEtBQUssRUFBRSxNQUFDLElBQUksQ0FBQyxLQUFxQiwwQ0FBRSxPQUFPLENBQUMsQ0FBQztRQUVwRyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUV0RyxJQUFJLENBQUMsd0JBQXdCLEdBQUcsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxnQkFBZ0IsR0FBVyxFQUFFLENBQUM7UUFDbkMsSUFBSSxDQUFDLGVBQWUsR0FBWSxFQUFFLENBQUM7UUFFbkMsSUFBSSxDQUFDLHdCQUF3QixHQUFHLENBQUMsS0FBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLDRCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztRQUVuRyxJQUFJLENBQUMsZ0NBQWdDLEdBQUcsSUFBSSxDQUFDO1FBRTdDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDO0lBQ3ZGLENBQUM7SUFFTyx3QkFBd0IsQ0FBRSxJQUFVLEVBQUUsS0FBYTtRQUN2RCxNQUFNLGlCQUFpQixHQUFHLElBQUksNkJBQWlCLENBQUM7WUFDNUMsSUFBSTtZQUNKLEtBQUssRUFBa0IsS0FBSyxHQUFHLENBQUM7WUFDaEMsS0FBSyxFQUFrQixJQUFJLENBQUMsTUFBTTtZQUNsQyxXQUFXLEVBQVksSUFBSSxDQUFDLFlBQVk7WUFDeEMsVUFBVSxFQUFhLElBQUksQ0FBQyxVQUFVO1lBQ3RDLHFCQUFxQixFQUFFLElBQUksQ0FBQyxxQkFBcUI7WUFDakQsSUFBSSxFQUFtQixJQUFJLENBQUMsS0FBSztZQUNqQyxVQUFVLEVBQWEsSUFBSSxDQUFDLFdBQVc7WUFDdkMsV0FBVyxFQUFZLElBQUksQ0FBQyxZQUFZO1NBQzNDLENBQUMsQ0FBQztRQUVILGlCQUFpQixDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxLQUFLLEVBQUMsV0FBVyxFQUFDLEVBQUU7WUFDeEQsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3BELENBQUMsQ0FBQyxDQUFDO1FBQ0gsaUJBQWlCLENBQUMsRUFBRSxDQUFDLGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzlDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3pELENBQUMsQ0FBQyxDQUFDO1FBQ0gsaUJBQWlCLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztRQUNoRyxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDcEQsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFDL0QsQ0FBQyxDQUFDLENBQUM7UUFDSCxpQkFBaUIsQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFFMUYsaUJBQWlCLENBQUMsRUFBRSxDQUFDLGtCQUFrQixFQUFFLEtBQUssRUFBQyxJQUFJLEVBQUMsRUFBRTtZQUNsRCxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLGlCQUFpQixDQUFDO0lBQzdCLENBQUM7SUFFTyxLQUFLLENBQUMsVUFBVSxDQUFFLE1BQXdCLEVBQUUsSUFBVTtRQUMxRCxJQUFJLElBQUksQ0FBQyxPQUFPO1lBQ1osT0FBTztRQUVYLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFFaEMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUM7UUFFakcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFFLElBQUksQ0FBQyxPQUFnQyxDQUFDLE1BQU0sRUFBRyxJQUFJLENBQUMsT0FBZ0MsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekssQ0FBQztJQUVPLHFCQUFxQixDQUFFLFdBQThCO1FBQ3pELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVPLDBCQUEwQixDQUFFLFdBQThCO1FBQzlELElBQUEsYUFBTSxFQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRU8sS0FBSyxDQUFDLGlCQUFpQixDQUFFLGlCQUFvQztRQUNqRSxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1FBRW5FLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUVyRSxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWMsQ0FBRSxpQkFBb0M7UUFDOUQsaUJBQWlCLENBQUMsT0FBTyxDQUFDLFVBQVUsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBRWxELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUVkLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU07WUFDdEMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRW5CLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFO1lBQ2xFLGlCQUFpQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQXVCLENBQUM7WUFFdkUsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUU1RCxJQUFBLGFBQU0sRUFBQyxJQUFJLENBQUMsZUFBZSxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFFaEQsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxnQ0FBZ0MsRUFBRTtnQkFDdkUsSUFBSSxDQUFDLGdDQUFnQyxFQUFFLENBQUM7Z0JBRXhDLElBQUksQ0FBQyxnQ0FBZ0MsR0FBRyxJQUFJLENBQUM7YUFDaEQ7U0FDSjtRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFO1lBQzFELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUk7Z0JBQ2hCLDRCQUFpQixDQUFDLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUU5RCxJQUFJO2lCQUNDLFVBQVUsQ0FBQyw0QkFBZ0IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2lCQUMvRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ3RDO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyx1QkFBdUIsQ0FBRSxpQkFBb0M7UUFDdkUsaURBQWlEO1FBQ2pELG1DQUFtQztRQUNuQyxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssZ0JBQWdCLENBQUMsUUFBUTtZQUMxQyxPQUFPLEtBQUssQ0FBQztRQUVqQixzREFBc0Q7UUFDdEQsOENBQThDO1FBQzlDLE1BQU0sU0FBUyxHQUFtQixpQkFBaUIsQ0FBQyxPQUFPLENBQUM7UUFDNUQsTUFBTSxhQUFhLEdBQWUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFxQixHQUFHLENBQUMsQ0FBQztRQUN2RSxNQUFNLHFCQUFxQixHQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RixNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXRJLElBQUksU0FBUyxJQUFJLENBQUMscUJBQXFCLElBQUkseUJBQXlCLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNyRixNQUFNLGtCQUFrQixHQUFHLGlCQUFpQixDQUFDLElBQUksQ0FBQyxrQkFBa0I7Z0JBQ2hFLElBQUksQ0FBQyxLQUFLLENBQUMsa0JBQWtCLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLGtCQUFrQixLQUFLLEtBQUssQ0FBQztZQUV6RixJQUFJLENBQUMseUJBQXlCLElBQUksQ0FBQyxrQkFBa0I7Z0JBQ2pELE9BQU8sS0FBSyxDQUFDO1lBRWpCLCtFQUErRTtZQUMvRSx3RUFBd0U7WUFDeEUsaUNBQWlDO1lBQ2pDLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxnQ0FBZ0MsR0FBRyxPQUFPLENBQUM7WUFDcEQsQ0FBQyxDQUFDLENBQUM7U0FDTjtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFTyx1QkFBdUIsQ0FBRSxZQUFvQjs7UUFDakQsSUFBSSxNQUFBLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxZQUFZLENBQUMsMENBQUUsTUFBTTtZQUNuRCxPQUFPLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV2RCxPQUFPLElBQUksQ0FBQyx1QkFBdUIsQ0FBQztJQUN4QyxDQUFDO0lBRU8sNkJBQTZCLENBQUcsU0FBaUI7UUFDckQsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQUMsT0FBQSxDQUFBLE1BQUEsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLDBDQUFFLEVBQUUsTUFBSyxTQUFTLENBQUEsRUFBQSxDQUFDLENBQUM7UUFFNUgsT0FBTyx5QkFBeUIsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMseUJBQXlCLENBQUM7SUFDOUcsQ0FBQztJQUVPLDJCQUEyQixDQUFFLEVBQUUsSUFBSSxFQUFxQixFQUFFLFlBQW9COztRQUNsRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixLQUFJLE1BQUEsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFlBQVksQ0FBQywwQ0FBRSxNQUFNLENBQUE7WUFDL0UsT0FBTztRQUVYLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsNkJBQTZCLENBQUMsTUFBQSxJQUFJLENBQUMsT0FBTywwQ0FBRSxFQUFZLENBQUMsQ0FBQyxDQUFDO0lBQ3pKLENBQUM7SUFFRCxNQUFNO0lBQ04sSUFBVyxpQkFBaUI7UUFDeEIsSUFBSSxJQUFJLENBQUMsdUJBQXVCLENBQUMsTUFBTTtZQUNuQyxPQUFPLElBQUksQ0FBQztRQUVoQixLQUFLLE1BQU0sWUFBWSxJQUFJLElBQUksQ0FBQyx3QkFBd0IsRUFBRTtZQUN0RCxJQUFJLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNO2dCQUNsRCxPQUFPLElBQUksQ0FBQztTQUNuQjtRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFRCxJQUFXLGNBQWM7UUFDckIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDbEYsQ0FBQztJQUVNLEtBQUssQ0FBQyxrQkFBa0IsQ0FBRSxVQUE2QjtRQUMxRCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUMzQixNQUFNLFlBQVksR0FBUSxJQUFJLENBQUMsdUJBQXVCLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3RFLE1BQU0saUJBQWlCLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTFDLElBQUksQ0FBQyxpQkFBaUI7Z0JBQ2xCLE1BQU07WUFFVixNQUFNLHNCQUFzQixHQUFHLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFFckYsSUFBSSxDQUFDLHNCQUFzQjtnQkFDdkIsTUFBTTtZQUVWLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDN0MsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxpQkFBaUIsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbkUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFFOUMsSUFBSSxJQUFJLENBQUMsT0FBTyxLQUFLLGdCQUFnQixDQUFDLFdBQVcsRUFBRTtnQkFDL0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7Z0JBQ3pDLElBQUksQ0FBQyxVQUFVLEdBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFFL0IsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBRTFDLElBQUksQ0FBQyxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDO2FBQzNDO1lBRUQsTUFBTSxVQUFVLEdBQUcsTUFBTSxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUU5RSxJQUFJLFVBQVUsRUFBRTtnQkFDWixPQUFPO29CQUNILFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsRUFBRTtvQkFDdkMsR0FBRyxFQUFRLFVBQVU7aUJBQ3hCLENBQUM7YUFDTDtTQUNKO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVNLEtBQUs7UUFDUixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyw0QkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzFELENBQUM7Q0FDSjtBQTFRRCw2QkEwUUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwdWxsIGFzIHJlbW92ZSB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgQXN5bmNFdmVudEVtaXR0ZXIgZnJvbSAnLi4vdXRpbHMvYXN5bmMtZXZlbnQtZW1pdHRlcic7XG5pbXBvcnQgVGVzdFJ1bkNvbnRyb2xsZXIgZnJvbSAnLi90ZXN0LXJ1bi1jb250cm9sbGVyJztcbmltcG9ydCBTZXNzaW9uQ29udHJvbGxlciBmcm9tICcuLi90ZXN0LXJ1bi9zZXNzaW9uLWNvbnRyb2xsZXInO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uIGZyb20gJy4uL2Jyb3dzZXIvY29ubmVjdGlvbic7XG5pbXBvcnQgeyBQcm94eSB9IGZyb20gJ3Rlc3RjYWZlLWhhbW1lcmhlYWQnO1xuaW1wb3J0IFRlc3QgZnJvbSAnLi4vYXBpL3N0cnVjdHVyZS90ZXN0JztcbmltcG9ydCBTY3JlZW5zaG90cyBmcm9tICcuLi9zY3JlZW5zaG90cyc7XG5pbXBvcnQgV2FybmluZ0xvZyBmcm9tICcuLi9ub3RpZmljYXRpb25zL3dhcm5pbmctbG9nJztcbmltcG9ydCBGaXh0dXJlSG9va0NvbnRyb2xsZXIgZnJvbSAnLi9maXh0dXJlLWhvb2stY29udHJvbGxlcic7XG5pbXBvcnQgeyBEaWN0aW9uYXJ5IH0gZnJvbSAnLi4vY29uZmlndXJhdGlvbi9pbnRlcmZhY2VzJztcbmltcG9ydCBCcm93c2VySm9iUmVzdWx0IGZyb20gJy4vYnJvd3Nlci1qb2ItcmVzdWx0JztcbmltcG9ydCB7IEJyb3dzZXJKb2JJbml0IH0gZnJvbSAnLi9pbnRlcmZhY2VzJztcbmltcG9ydCBNZXNzYWdlQnVzIGZyb20gJy4uL3V0aWxzL21lc3NhZ2UtYnVzJztcbmltcG9ydCBUZXN0UnVuSG9va0NvbnRyb2xsZXIgZnJvbSAnLi90ZXN0LXJ1bi1ob29rLWNvbnRyb2xsZXInO1xuaW1wb3J0IFRlc3RSdW4gZnJvbSAnLi4vdGVzdC1ydW4nO1xuLy8gQHRzLWlnbm9yZVxuaW1wb3J0IHsgVGVzdFJ1biBhcyBMZWdhY3lUZXN0UnVuIH0gZnJvbSAndGVzdGNhZmUtbGVnYWN5LWFwaSc7XG5pbXBvcnQgeyBOZXh0VGVzdFJ1bkluZm8gfSBmcm9tICcuLi9zaGFyZWQvdHlwZXMnO1xuXG5pbnRlcmZhY2UgQnJvd3NlckpvYlJlc3VsdEluZm8ge1xuICAgIHN0YXR1czogQnJvd3NlckpvYlJlc3VsdDtcbiAgICBkYXRhPzogYW55O1xufVxuXG5lbnVtIEJyb3dzZXJKb2JTdGF0dXMgeyBpbml0aWFsaXplZCwgc3RhcnRpbmcsIHN0YXJ0ZWQgfVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCcm93c2VySm9iIGV4dGVuZHMgQXN5bmNFdmVudEVtaXR0ZXIge1xuICAgIHByaXZhdGUgX3N0YXR1czogQnJvd3NlckpvYlN0YXR1cztcbiAgICBwcml2YXRlIF9zdGFydFRpbWU6IERhdGU7XG4gICAgcHJpdmF0ZSBfdG90YWw6IG51bWJlcjtcbiAgICBwcml2YXRlIF9wYXNzZWQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9vcHRzOiBEaWN0aW9uYXJ5PE9wdGlvblZhbHVlPjtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9wcm94eTogUHJveHk7XG4gICAgcHVibGljIHJlYWRvbmx5IGJyb3dzZXJDb25uZWN0aW9uczogQnJvd3NlckNvbm5lY3Rpb25bXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9zY3JlZW5zaG90czogU2NyZWVuc2hvdHM7XG4gICAgcHVibGljIHJlYWRvbmx5IHdhcm5pbmdMb2c6IFdhcm5pbmdMb2c7XG4gICAgcHVibGljIHJlYWRvbmx5IGZpeHR1cmVIb29rQ29udHJvbGxlcjogRml4dHVyZUhvb2tDb250cm9sbGVyO1xuICAgIHByaXZhdGUgX3Jlc3VsdDogQnJvd3NlckpvYlJlc3VsdEluZm8gfCBudWxsO1xuICAgIHByaXZhdGUgX3Rlc3RSdW5Db250cm9sbGVyUXVldWU6IFRlc3RSdW5Db250cm9sbGVyW107XG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVwb3J0c1BlbmRpbmc6IFRlc3RSdW5Db250cm9sbGVyW107XG4gICAgcHJpdmF0ZSByZWFkb25seSBfY29ubmVjdGlvbkVycm9yTGlzdGVuZXI6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfY29tcGxldGlvblF1ZXVlOiBUZXN0UnVuQ29udHJvbGxlcltdO1xuICAgIHByaXZhdGUgX3Jlc29sdmVXYWl0aW5nTGFzdFRlc3RJbkZpeHR1cmU6IEZ1bmN0aW9uIHwgbnVsbDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tZXNzYWdlQnVzOiBNZXNzYWdlQnVzO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3Rlc3RSdW5Ib29rOiBUZXN0UnVuSG9va0NvbnRyb2xsZXI7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfZGlzYWJsZUNvbmN1cnJlbmN5UXVldWU6IERpY3Rpb25hcnk8VGVzdFJ1bkNvbnRyb2xsZXJbXT47XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKHtcbiAgICAgICAgdGVzdHMsXG4gICAgICAgIGJyb3dzZXJDb25uZWN0aW9ucyxcbiAgICAgICAgcHJveHksXG4gICAgICAgIHNjcmVlbnNob3RzLFxuICAgICAgICB3YXJuaW5nTG9nLFxuICAgICAgICBmaXh0dXJlSG9va0NvbnRyb2xsZXIsXG4gICAgICAgIG9wdHMsXG4gICAgICAgIG1lc3NhZ2VCdXMsXG4gICAgfTogQnJvd3NlckpvYkluaXQpIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLl9zdGF0dXMgPSBCcm93c2VySm9iU3RhdHVzLmluaXRpYWxpemVkO1xuICAgICAgICB0aGlzLl9zdGFydFRpbWUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAgIHRoaXMuX3RvdGFsICAgICAgICAgICAgICAgID0gMDtcbiAgICAgICAgdGhpcy5fcGFzc2VkICAgICAgICAgICAgICAgPSAwO1xuICAgICAgICB0aGlzLl9vcHRzICAgICAgICAgICAgICAgICA9IG9wdHM7XG4gICAgICAgIHRoaXMuX3Byb3h5ICAgICAgICAgICAgICAgID0gcHJveHk7XG4gICAgICAgIHRoaXMuYnJvd3NlckNvbm5lY3Rpb25zICAgID0gYnJvd3NlckNvbm5lY3Rpb25zO1xuICAgICAgICB0aGlzLl9zY3JlZW5zaG90cyAgICAgICAgICA9IHNjcmVlbnNob3RzO1xuICAgICAgICB0aGlzLndhcm5pbmdMb2cgICAgICAgICAgICA9IHdhcm5pbmdMb2c7XG4gICAgICAgIHRoaXMuZml4dHVyZUhvb2tDb250cm9sbGVyID0gZml4dHVyZUhvb2tDb250cm9sbGVyO1xuICAgICAgICB0aGlzLl9yZXN1bHQgICAgICAgICAgICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMuX21lc3NhZ2VCdXMgICAgICAgICAgID0gbWVzc2FnZUJ1cztcbiAgICAgICAgdGhpcy5fdGVzdFJ1bkhvb2sgICAgICAgICAgPSBuZXcgVGVzdFJ1bkhvb2tDb250cm9sbGVyKHRlc3RzLCAob3B0cy5ob29rcyBhcyBHbG9iYWxIb29rcyk/LnRlc3RSdW4pO1xuXG4gICAgICAgIHRoaXMuX3Rlc3RSdW5Db250cm9sbGVyUXVldWUgPSB0ZXN0cy5tYXAoKHRlc3QsIGluZGV4KSA9PiB0aGlzLl9jcmVhdGVUZXN0UnVuQ29udHJvbGxlcih0ZXN0LCBpbmRleCkpO1xuXG4gICAgICAgIHRoaXMuX2Rpc2FibGVDb25jdXJyZW5jeVF1ZXVlID0ge307XG4gICAgICAgIHRoaXMuX2NvbXBsZXRpb25RdWV1ZSAgICAgICAgID0gW107XG4gICAgICAgIHRoaXMuX3JlcG9ydHNQZW5kaW5nICAgICAgICAgID0gW107XG5cbiAgICAgICAgdGhpcy5fY29ubmVjdGlvbkVycm9yTGlzdGVuZXIgPSAoZXJyb3I6IEVycm9yKSA9PiB0aGlzLl9zZXRSZXN1bHQoQnJvd3NlckpvYlJlc3VsdC5lcnJvcmVkLCBlcnJvcik7XG5cbiAgICAgICAgdGhpcy5fcmVzb2x2ZVdhaXRpbmdMYXN0VGVzdEluRml4dHVyZSA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5icm93c2VyQ29ubmVjdGlvbnMubWFwKGJjID0+IGJjLm9uY2UoJ2Vycm9yJywgdGhpcy5fY29ubmVjdGlvbkVycm9yTGlzdGVuZXIpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jcmVhdGVUZXN0UnVuQ29udHJvbGxlciAodGVzdDogVGVzdCwgaW5kZXg6IG51bWJlcik6IFRlc3RSdW5Db250cm9sbGVyIHtcbiAgICAgICAgY29uc3QgdGVzdFJ1bkNvbnRyb2xsZXIgPSBuZXcgVGVzdFJ1bkNvbnRyb2xsZXIoe1xuICAgICAgICAgICAgdGVzdCxcbiAgICAgICAgICAgIGluZGV4OiAgICAgICAgICAgICAgICAgaW5kZXggKyAxLFxuICAgICAgICAgICAgcHJveHk6ICAgICAgICAgICAgICAgICB0aGlzLl9wcm94eSxcbiAgICAgICAgICAgIHNjcmVlbnNob3RzOiAgICAgICAgICAgdGhpcy5fc2NyZWVuc2hvdHMsXG4gICAgICAgICAgICB3YXJuaW5nTG9nOiAgICAgICAgICAgIHRoaXMud2FybmluZ0xvZyxcbiAgICAgICAgICAgIGZpeHR1cmVIb29rQ29udHJvbGxlcjogdGhpcy5maXh0dXJlSG9va0NvbnRyb2xsZXIsXG4gICAgICAgICAgICBvcHRzOiAgICAgICAgICAgICAgICAgIHRoaXMuX29wdHMsXG4gICAgICAgICAgICBtZXNzYWdlQnVzOiAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VCdXMsXG4gICAgICAgICAgICB0ZXN0UnVuSG9vazogICAgICAgICAgIHRoaXMuX3Rlc3RSdW5Ib29rLFxuICAgICAgICB9KTtcblxuICAgICAgICB0ZXN0UnVuQ29udHJvbGxlci5vbigndGVzdC1ydW4tY3JlYXRlJywgYXN5bmMgdGVzdFJ1bkluZm8gPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LXJ1bi1jcmVhdGUnLCB0ZXN0UnVuSW5mbyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0ZXN0UnVuQ29udHJvbGxlci5vbigndGVzdC1ydW4tcmVhZHknLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLXJlYWR5JywgdGVzdFJ1bkNvbnRyb2xsZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGVzdFJ1bkNvbnRyb2xsZXIub24oJ3Rlc3QtcnVuLXJlc3RhcnQnLCBhc3luYyAoKSA9PiB0aGlzLl9vblRlc3RSdW5SZXN0YXJ0KHRlc3RSdW5Db250cm9sbGVyKSk7XG4gICAgICAgIHRlc3RSdW5Db250cm9sbGVyLm9uKCd0ZXN0LXJ1bi1iZWZvcmUtZG9uZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZW1pdCgndGVzdC1ydW4tYmVmb3JlLWRvbmUnLCB0ZXN0UnVuQ29udHJvbGxlcik7XG4gICAgICAgIH0pO1xuICAgICAgICB0ZXN0UnVuQ29udHJvbGxlci5vbigndGVzdC1ydW4tZG9uZScsIGFzeW5jICgpID0+IHRoaXMuX29uVGVzdFJ1bkRvbmUodGVzdFJ1bkNvbnRyb2xsZXIpKTtcblxuICAgICAgICB0ZXN0UnVuQ29udHJvbGxlci5vbigndGVzdC1hY3Rpb24tZG9uZScsIGFzeW5jIGFyZ3MgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LWFjdGlvbi1kb25lJywgYXJncyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0ZXN0UnVuQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9zZXRSZXN1bHQgKHN0YXR1czogQnJvd3NlckpvYlJlc3VsdCwgZGF0YT86IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5fcmVzdWx0KVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuX3Jlc3VsdCA9IHsgc3RhdHVzLCBkYXRhIH07XG5cbiAgICAgICAgdGhpcy5icm93c2VyQ29ubmVjdGlvbnMuZm9yRWFjaChiYyA9PiBiYy5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCB0aGlzLl9jb25uZWN0aW9uRXJyb3JMaXN0ZW5lcikpO1xuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuYnJvd3NlckNvbm5lY3Rpb25zLm1hcChiYyA9PiBiYy5yZXBvcnRKb2JSZXN1bHQoKHRoaXMuX3Jlc3VsdCBhcyBCcm93c2VySm9iUmVzdWx0SW5mbykuc3RhdHVzLCAodGhpcy5fcmVzdWx0IGFzIEJyb3dzZXJKb2JSZXN1bHRJbmZvKS5kYXRhKSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2FkZFRvQ29tcGxldGlvblF1ZXVlICh0ZXN0UnVuSW5mbzogVGVzdFJ1bkNvbnRyb2xsZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fY29tcGxldGlvblF1ZXVlLnB1c2godGVzdFJ1bkluZm8pO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3JlbW92ZUZyb21Db21wbGV0aW9uUXVldWUgKHRlc3RSdW5JbmZvOiBUZXN0UnVuQ29udHJvbGxlcik6IHZvaWQge1xuICAgICAgICByZW1vdmUodGhpcy5fY29tcGxldGlvblF1ZXVlLCB0ZXN0UnVuSW5mbyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfb25UZXN0UnVuUmVzdGFydCAodGVzdFJ1bkNvbnRyb2xsZXI6IFRlc3RSdW5Db250cm9sbGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNvbmVjdGlvbklkID0gdGVzdFJ1bkNvbnRyb2xsZXIudGVzdFJ1bi5icm93c2VyQ29ubmVjdGlvbi5pZDtcblxuICAgICAgICB0aGlzLl9yZW1vdmVGcm9tQ29tcGxldGlvblF1ZXVlKHRlc3RSdW5Db250cm9sbGVyKTtcbiAgICAgICAgdGhpcy5fZ2V0VGVzdENvbnRyb2xsZXJRdWV1ZShjb25lY3Rpb25JZCkudW5zaGlmdCh0ZXN0UnVuQ29udHJvbGxlcik7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LXJ1bi1yZXN0YXJ0JywgdGVzdFJ1bkNvbnRyb2xsZXIpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX29uVGVzdFJ1bkRvbmUgKHRlc3RSdW5Db250cm9sbGVyOiBUZXN0UnVuQ29udHJvbGxlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0ZXN0UnVuQ29udHJvbGxlci50ZXN0UnVuLmZpbmlzaFRpbWUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAgIHRoaXMuX3RvdGFsKys7XG5cbiAgICAgICAgaWYgKCF0ZXN0UnVuQ29udHJvbGxlci50ZXN0UnVuLmVycnMubGVuZ3RoKVxuICAgICAgICAgICAgdGhpcy5fcGFzc2VkKys7XG5cbiAgICAgICAgd2hpbGUgKHRoaXMuX2NvbXBsZXRpb25RdWV1ZS5sZW5ndGggJiYgdGhpcy5fY29tcGxldGlvblF1ZXVlWzBdLmRvbmUpIHtcbiAgICAgICAgICAgIHRlc3RSdW5Db250cm9sbGVyID0gdGhpcy5fY29tcGxldGlvblF1ZXVlLnNoaWZ0KCkgYXMgVGVzdFJ1bkNvbnRyb2xsZXI7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZW1pdCgndGVzdC1ydW4tZG9uZScsIHRlc3RSdW5Db250cm9sbGVyLnRlc3RSdW4pO1xuXG4gICAgICAgICAgICByZW1vdmUodGhpcy5fcmVwb3J0c1BlbmRpbmcsIHRlc3RSdW5Db250cm9sbGVyKTtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLl9yZXBvcnRzUGVuZGluZy5sZW5ndGggJiYgdGhpcy5fcmVzb2x2ZVdhaXRpbmdMYXN0VGVzdEluRml4dHVyZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVXYWl0aW5nTGFzdFRlc3RJbkZpeHR1cmUoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVXYWl0aW5nTGFzdFRlc3RJbkZpeHR1cmUgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl9jb21wbGV0aW9uUXVldWUubGVuZ3RoICYmICF0aGlzLmhhc1F1ZXVlZFRlc3RSdW5zKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX29wdHMubGl2ZSlcbiAgICAgICAgICAgICAgICBTZXNzaW9uQ29udHJvbGxlci5jbG9zZVNlc3Npb24odGVzdFJ1bkNvbnRyb2xsZXIudGVzdFJ1bik7XG5cbiAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgICAgICAuX3NldFJlc3VsdChCcm93c2VySm9iUmVzdWx0LmRvbmUsIHsgdG90YWw6IHRoaXMuX3RvdGFsLCBwYXNzZWQ6IHRoaXMuX3Bhc3NlZCB9KVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHRoaXMuZW1pdCgnZG9uZScpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2lzTmV4dFRlc3RSdW5BdmFpbGFibGUgKHRlc3RSdW5Db250cm9sbGVyOiBUZXN0UnVuQ29udHJvbGxlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICAvLyBOT1RFOiBldmVudCB0YXNrIHN0YXJ0IGlzIGN1cnJlbnRseSBleGVjdXRpbmcsXG4gICAgICAgIC8vIHNvIHRlc3QgcnVuIGlzIHRlbXBvcmFyeSBibG9ja2VkXG4gICAgICAgIGlmICh0aGlzLl9zdGF0dXMgPT09IEJyb3dzZXJKb2JTdGF0dXMuc3RhcnRpbmcpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgLy8gTk9URTogYmVmb3JlIGhvb2sgZm9yIHRlc3QgcnVuIGZpeHR1cmUgaXMgY3VycmVudGx5XG4gICAgICAgIC8vIGV4ZWN1dGluZywgc28gdGVzdCBydW4gaXMgdGVtcG9yYXJ5IGJsb2NrZWRcbiAgICAgICAgY29uc3QgaXNCbG9ja2VkICAgICAgICAgICAgICAgICA9IHRlc3RSdW5Db250cm9sbGVyLmJsb2NrZWQ7XG4gICAgICAgIGNvbnN0IGlzQ29uY3VycmVuY3kgICAgICAgICAgICAgPSB0aGlzLl9vcHRzLmNvbmN1cnJlbmN5IGFzIG51bWJlciA+IDE7XG4gICAgICAgIGNvbnN0IGhhc0luY29tcGxldGVUZXN0UnVucyAgICAgPSB0aGlzLl9jb21wbGV0aW9uUXVldWUuc29tZShjb250cm9sbGVyID0+ICFjb250cm9sbGVyLmRvbmUpO1xuICAgICAgICBjb25zdCBuZWVkV2FpdExhc3RUZXN0SW5GaXh0dXJlID0gdGhpcy5fcmVwb3J0c1BlbmRpbmcuc29tZShjb250cm9sbGVyID0+IGNvbnRyb2xsZXIudGVzdC5maXh0dXJlICE9PSB0ZXN0UnVuQ29udHJvbGxlci50ZXN0LmZpeHR1cmUpO1xuXG4gICAgICAgIGlmIChpc0Jsb2NrZWQgfHwgKGhhc0luY29tcGxldGVUZXN0UnVucyB8fCBuZWVkV2FpdExhc3RUZXN0SW5GaXh0dXJlKSAmJiAhaXNDb25jdXJyZW5jeSkge1xuICAgICAgICAgICAgY29uc3QgZGlzYWJsZVBhZ2VSZWxvYWRzID0gdGVzdFJ1bkNvbnRyb2xsZXIudGVzdC5kaXNhYmxlUGFnZVJlbG9hZHMgfHxcbiAgICAgICAgICAgICAgICB0aGlzLl9vcHRzLmRpc2FibGVQYWdlUmVsb2FkcyAmJiB0ZXN0UnVuQ29udHJvbGxlci50ZXN0LmRpc2FibGVQYWdlUmVsb2FkcyAhPT0gZmFsc2U7XG5cbiAgICAgICAgICAgIGlmICghbmVlZFdhaXRMYXN0VGVzdEluRml4dHVyZSB8fCAhZGlzYWJsZVBhZ2VSZWxvYWRzKVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICAgICAgLy8gTk9URTogaWYgd2UgaGF2ZSBgZGlzYWJsZVBhZ2VSZWxvYWRzYCBlbmFibGVkIGFuZCB0aGUgbmV4dCB0ZXN0IGlzIGZyb20gbmV4dFxuICAgICAgICAgICAgLy8gZml4dHVyZSwgdGhlbiB3ZSBuZWVkIHRvIHdhaXQgdW50aWwgYWxsIHJlcG9ydGVycyBmaW5pc2hlZCB0byBwcmV2ZW50XG4gICAgICAgICAgICAvLyByZWRpcmVjdGluZyB0byB0aGUgYGlkbGVgIHBhZ2VcbiAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Jlc29sdmVXYWl0aW5nTGFzdFRlc3RJbkZpeHR1cmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRUZXN0Q29udHJvbGxlclF1ZXVlIChjb25uZWN0aW9uSWQ6IHN0cmluZyk6IFRlc3RSdW5Db250cm9sbGVyW10ge1xuICAgICAgICBpZiAodGhpcy5fZGlzYWJsZUNvbmN1cnJlbmN5UXVldWVbY29ubmVjdGlvbklkXT8ubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Rpc2FibGVDb25jdXJyZW5jeVF1ZXVlW2Nvbm5lY3Rpb25JZF07XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3Rlc3RSdW5Db250cm9sbGVyUXVldWU7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0TmV4dEZpeHR1cmVGaXJzdFRlc3RJbmRleCAoIGZpeHR1cmVJZDogc3RyaW5nICk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IG5leHRGaXh0dXJlRmlyc3RUZXN0SW5kZXggPSB0aGlzLl90ZXN0UnVuQ29udHJvbGxlclF1ZXVlLmZpbmRJbmRleCh0ZXN0UnVuID0+IHRlc3RSdW4udGVzdC5maXh0dXJlPy5pZCAhPT0gZml4dHVyZUlkKTtcblxuICAgICAgICByZXR1cm4gbmV4dEZpeHR1cmVGaXJzdFRlc3RJbmRleCA9PT0gLTEgPyB0aGlzLl90ZXN0UnVuQ29udHJvbGxlclF1ZXVlLmxlbmd0aCA6IG5leHRGaXh0dXJlRmlyc3RUZXN0SW5kZXg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfdXBkYXRlVGVzdENvbnRyb2xsZXJRdWV1ZXMgKHsgdGVzdCB9OiBUZXN0UnVuQ29udHJvbGxlciwgY29ubmVjdGlvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0ZXN0LmRpc2FibGVDb25jdXJyZW5jeSB8fCB0aGlzLl9kaXNhYmxlQ29uY3VycmVuY3lRdWV1ZVtjb25uZWN0aW9uSWRdPy5sZW5ndGgpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5fZGlzYWJsZUNvbmN1cnJlbmN5UXVldWVbY29ubmVjdGlvbklkXSA9IHRoaXMuX3Rlc3RSdW5Db250cm9sbGVyUXVldWUuc3BsaWNlKDAsIHRoaXMuX2dldE5leHRGaXh0dXJlRmlyc3RUZXN0SW5kZXgodGVzdC5maXh0dXJlPy5pZCBhcyBzdHJpbmcpKTtcbiAgICB9XG5cbiAgICAvLyBBUElcbiAgICBwdWJsaWMgZ2V0IGhhc1F1ZXVlZFRlc3RSdW5zICgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKHRoaXMuX3Rlc3RSdW5Db250cm9sbGVyUXVldWUubGVuZ3RoKVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uSWQgaW4gdGhpcy5fZGlzYWJsZUNvbmN1cnJlbmN5UXVldWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9kaXNhYmxlQ29uY3VycmVuY3lRdWV1ZVtjb25uZWN0aW9uSWRdLmxlbmd0aClcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0IGN1cnJlbnRUZXN0UnVuICgpOiBMZWdhY3lUZXN0UnVuIHwgVGVzdFJ1biB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29tcGxldGlvblF1ZXVlLmxlbmd0aCA/IHRoaXMuX2NvbXBsZXRpb25RdWV1ZVswXS50ZXN0UnVuIDogbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcG9wTmV4dFRlc3RSdW5JbmZvIChjb25uZWN0aW9uOiBCcm93c2VyQ29ubmVjdGlvbik6IFByb21pc2U8TmV4dFRlc3RSdW5JbmZvIHwgbnVsbD4ge1xuICAgICAgICB3aGlsZSAodGhpcy5oYXNRdWV1ZWRUZXN0UnVucykge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudFF1ZXVlICAgICAgPSB0aGlzLl9nZXRUZXN0Q29udHJvbGxlclF1ZXVlKGNvbm5lY3Rpb24uaWQpO1xuICAgICAgICAgICAgY29uc3QgdGVzdFJ1bkNvbnRyb2xsZXIgPSBjdXJyZW50UXVldWVbMF07XG5cbiAgICAgICAgICAgIGlmICghdGVzdFJ1bkNvbnRyb2xsZXIpXG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNvbnN0IGlzTmV4dFRlc3RSdW5BdmFpbGFibGUgPSBhd2FpdCB0aGlzLl9pc05leHRUZXN0UnVuQXZhaWxhYmxlKHRlc3RSdW5Db250cm9sbGVyKTtcblxuICAgICAgICAgICAgaWYgKCFpc05leHRUZXN0UnVuQXZhaWxhYmxlKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICB0aGlzLl9yZXBvcnRzUGVuZGluZy5wdXNoKHRlc3RSdW5Db250cm9sbGVyKTtcbiAgICAgICAgICAgIGN1cnJlbnRRdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlVGVzdENvbnRyb2xsZXJRdWV1ZXModGVzdFJ1bkNvbnRyb2xsZXIsIGNvbm5lY3Rpb24uaWQpO1xuICAgICAgICAgICAgdGhpcy5fYWRkVG9Db21wbGV0aW9uUXVldWUodGVzdFJ1bkNvbnRyb2xsZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5fc3RhdHVzID09PSBCcm93c2VySm9iU3RhdHVzLmluaXRpYWxpemVkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3RhdHVzID0gQnJvd3NlckpvYlN0YXR1cy5zdGFydGluZztcbiAgICAgICAgICAgICAgICB0aGlzLl9zdGFydFRpbWUgICA9IG5ldyBEYXRlKCk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3N0YXJ0JywgdGhpcy5fc3RhcnRUaW1lKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuX3N0YXR1cyA9IEJyb3dzZXJKb2JTdGF0dXMuc3RhcnRlZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgdGVzdFJ1blVybCA9IGF3YWl0IHRlc3RSdW5Db250cm9sbGVyLnN0YXJ0KGNvbm5lY3Rpb24sIHRoaXMuX3N0YXJ0VGltZSk7XG5cbiAgICAgICAgICAgIGlmICh0ZXN0UnVuVXJsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdGVzdFJ1bklkOiB0ZXN0UnVuQ29udHJvbGxlci50ZXN0UnVuLmlkLFxuICAgICAgICAgICAgICAgICAgICB1cmw6ICAgICAgIHRlc3RSdW5VcmwsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHB1YmxpYyBhYm9ydCAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2xlYXJMaXN0ZW5lcnMoKTtcbiAgICAgICAgdGhpcy5fc2V0UmVzdWx0KEJyb3dzZXJKb2JSZXN1bHQuYWJvcnRlZCk7XG4gICAgICAgIHRoaXMuYnJvd3NlckNvbm5lY3Rpb25zLm1hcChiYyA9PiBiYy5yZW1vdmVKb2IodGhpcykpO1xuICAgIH1cbn1cbiJdfQ==