439 lines
64 KiB
JavaScript
439 lines
64 KiB
JavaScript
"use strict";
|
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
var t = {};
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
t[p] = s[p];
|
|
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
t[p[i]] = s[p[i]];
|
|
}
|
|
return t;
|
|
};
|
|
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 is_stream_1 = require("is-stream");
|
|
const plugin_host_1 = __importDefault(require("./plugin-host"));
|
|
const plugin_methods_1 = __importDefault(require("./plugin-methods"));
|
|
const format_command_1 = __importDefault(require("./command/format-command"));
|
|
const runtime_1 = require("../errors/runtime");
|
|
const reporter_1 = require("../utils/reporter");
|
|
const resolve_path_relatively_cwd_1 = __importDefault(require("../utils/resolve-path-relatively-cwd"));
|
|
const make_dir_1 = __importDefault(require("make-dir"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const fs_1 = __importDefault(require("fs"));
|
|
const debug_1 = __importDefault(require("debug"));
|
|
const debugLog = (0, debug_1.default)('testcafe:reporter');
|
|
class Reporter {
|
|
constructor(plugin, messageBus, outStream, name) {
|
|
this.plugin = new plugin_host_1.default(plugin, outStream, name);
|
|
this.messageBus = messageBus;
|
|
this.disposed = false;
|
|
this.taskInfo = null;
|
|
this.outStream = outStream;
|
|
this._assignMessageBusEventHandlers();
|
|
}
|
|
static _isSpecialStream(stream) {
|
|
return stream.isTTY || stream === process.stdout || stream === process.stderr;
|
|
}
|
|
static _createPendingPromise() {
|
|
let resolver = null;
|
|
const promise = new Promise(resolve => {
|
|
resolver = resolve;
|
|
});
|
|
promise.resolve = resolver;
|
|
return promise;
|
|
}
|
|
async init() {
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.init,
|
|
initialObject: null,
|
|
args: [{}],
|
|
});
|
|
}
|
|
async dispatchToPlugin({ method, initialObject, args = [] }) {
|
|
try {
|
|
// @ts-ignore
|
|
await this.plugin[method](...args);
|
|
}
|
|
catch (originalError) {
|
|
const uncaughtError = new runtime_1.ReporterPluginError({
|
|
name: this.plugin.name,
|
|
method,
|
|
originalError,
|
|
});
|
|
debugLog('Plugin error: %O', uncaughtError);
|
|
debugLog('Plugin error: initialObject: %O', initialObject);
|
|
if (initialObject)
|
|
await initialObject.emit('error', uncaughtError);
|
|
else
|
|
throw uncaughtError;
|
|
}
|
|
}
|
|
_assignMessageBusEventHandlers() {
|
|
const messageBus = this.messageBus;
|
|
messageBus.on('warning-add', async (e) => await this._onWarningAddHandler(e));
|
|
messageBus.once('start', async (task) => await this._onceTaskStartHandler(task));
|
|
messageBus.on('test-run-start', async (testRun) => await this._onTaskTestRunStartHandler(testRun));
|
|
messageBus.on('test-run-done', async (testRun) => await this._onTaskTestRunDoneHandler(testRun));
|
|
messageBus.on('test-action-start', async (e) => await this._onTaskTestActionStart(e));
|
|
messageBus.on('test-action-done', async (e) => await this._onTaskTestActionDone(e));
|
|
messageBus.once('done', async () => await this._onceTaskDoneHandler());
|
|
}
|
|
async dispose() {
|
|
var _a;
|
|
if (this.disposed)
|
|
return Promise.resolve();
|
|
this.disposed = true;
|
|
if (!(0, lodash_1.isFunction)((_a = this === null || this === void 0 ? void 0 : this.outStream) === null || _a === void 0 ? void 0 : _a.once)
|
|
|| Reporter._isSpecialStream(this.outStream)
|
|
|| !(0, is_stream_1.writable)(this.outStream))
|
|
return Promise.resolve();
|
|
const streamFinishedPromise = new Promise(resolve => {
|
|
this.outStream.once('finish', resolve);
|
|
this.outStream.once('error', resolve);
|
|
});
|
|
this.outStream.end();
|
|
return streamFinishedPromise;
|
|
}
|
|
static async _ensureOutStream(outStream) {
|
|
if (typeof outStream !== 'string')
|
|
return outStream;
|
|
const fullReporterOutputPath = (0, resolve_path_relatively_cwd_1.default)(outStream);
|
|
await (0, make_dir_1.default)(path_1.default.dirname(fullReporterOutputPath));
|
|
return fs_1.default.createWriteStream(fullReporterOutputPath);
|
|
}
|
|
static _addDefaultReporter(reporters) {
|
|
reporters.push({
|
|
name: 'spec',
|
|
output: process.stdout,
|
|
});
|
|
}
|
|
static async getReporterPlugins(reporters = []) {
|
|
if (!reporters.length)
|
|
Reporter._addDefaultReporter(reporters);
|
|
return Promise.all(reporters.map(async ({ name, output, options }) => {
|
|
const pluginFactory = (0, reporter_1.getPluginFactory)(name);
|
|
const processedName = (0, reporter_1.processReporterName)(name);
|
|
const outStream = output ? await Reporter._ensureOutStream(output) : void 0;
|
|
return {
|
|
plugin: pluginFactory(options),
|
|
name: processedName,
|
|
outStream,
|
|
};
|
|
}));
|
|
}
|
|
async _onWarningAddHandler({ message, testRun, actionId }) {
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportWarnings,
|
|
initialObject: this.messageBus,
|
|
args: [
|
|
{
|
|
message,
|
|
testRunId: testRun === null || testRun === void 0 ? void 0 : testRun.id,
|
|
actionId,
|
|
},
|
|
],
|
|
});
|
|
}
|
|
//Task
|
|
static _createTestItem(test, runsPerTest) {
|
|
return {
|
|
fixture: test.fixture,
|
|
test: test,
|
|
testRunIds: [],
|
|
screenshotPath: null,
|
|
screenshots: [],
|
|
videos: [],
|
|
quarantine: null,
|
|
errs: [],
|
|
warnings: [],
|
|
unstable: false,
|
|
startTime: null,
|
|
testRunInfo: null,
|
|
pendingRuns: runsPerTest,
|
|
pendingStarts: runsPerTest,
|
|
pendingTestRunDonePromise: Reporter._createPendingPromise(),
|
|
pendingTestRunStartPromise: Reporter._createPendingPromise(),
|
|
browsers: [],
|
|
};
|
|
}
|
|
static _createTestQueue(task) {
|
|
const runsPerTest = task.browserConnectionGroups.length;
|
|
return task.tests.map(test => Reporter._createTestItem(test, runsPerTest));
|
|
}
|
|
static _createTestRunInfo(reportItem) {
|
|
return {
|
|
errs: (0, lodash_1.sortBy)(reportItem.errs, ['userAgent', 'code']),
|
|
warnings: reportItem.warnings,
|
|
durationMs: +new Date() - reportItem.startTime,
|
|
unstable: reportItem.unstable,
|
|
screenshotPath: reportItem.screenshotPath,
|
|
screenshots: reportItem.screenshots,
|
|
videos: reportItem.videos,
|
|
quarantine: reportItem.quarantine,
|
|
skipped: reportItem.test.skip,
|
|
browsers: reportItem.browsers,
|
|
testId: reportItem.test.id,
|
|
fixture: {
|
|
id: reportItem.fixture.id,
|
|
name: reportItem.fixture.name,
|
|
path: reportItem.fixture.path,
|
|
meta: reportItem.fixture.meta,
|
|
},
|
|
};
|
|
}
|
|
_getTestItemForTestRun(taskInfo, testRun) {
|
|
return (0, lodash_1.find)(taskInfo.testQueue, i => i.test === testRun.test);
|
|
}
|
|
async _shiftTestQueue() {
|
|
if (!this.taskInfo)
|
|
return;
|
|
let currentFixture = null;
|
|
let nextReportItem = null;
|
|
let testItem = null;
|
|
const testQueue = this.taskInfo.testQueue;
|
|
while (testQueue.length && testQueue[0].testRunInfo) {
|
|
testItem = testQueue.shift();
|
|
currentFixture = testItem.fixture;
|
|
// NOTE: here we assume that tests are sorted by fixture.
|
|
// Therefore, if the next report item has a different
|
|
// fixture, we can report this fixture start.
|
|
nextReportItem = testQueue[0];
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTestDone,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
testItem.test.name,
|
|
testItem.testRunInfo,
|
|
testItem.test.meta,
|
|
],
|
|
});
|
|
if (!nextReportItem || nextReportItem.fixture === currentFixture)
|
|
continue;
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportFixtureStart,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
nextReportItem.fixture.name,
|
|
nextReportItem.fixture.path,
|
|
nextReportItem.fixture.meta,
|
|
],
|
|
});
|
|
}
|
|
}
|
|
async _resolveTestItem(taskInfo, testItem, testRun) {
|
|
if (!taskInfo.task)
|
|
return;
|
|
if (taskInfo.task.screenshots.hasCapturedFor(testRun.test)) {
|
|
testItem.screenshotPath = taskInfo.task.screenshots.getPathFor(testRun.test);
|
|
testItem.screenshots = taskInfo.task.screenshots.getScreenshotsInfo(testRun.test);
|
|
}
|
|
if (taskInfo.task.videos)
|
|
testItem.videos = taskInfo.task.videos.getTestVideos(testItem.test.id);
|
|
if (testRun.quarantine) {
|
|
const testItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors }, index) => {
|
|
const passed = !errors.length;
|
|
const quarantineAttempt = index + 1;
|
|
result[quarantineAttempt] = { passed };
|
|
return result;
|
|
}, {});
|
|
Object.assign(testItem.quarantine, testItemQuarantine);
|
|
}
|
|
if (!testItem.testRunInfo) {
|
|
testItem.testRunInfo = Reporter._createTestRunInfo(testItem);
|
|
if (testItem.test.skip)
|
|
taskInfo.skipped++;
|
|
else if (testItem.errs.length)
|
|
taskInfo.failed++;
|
|
else
|
|
taskInfo.passed++;
|
|
}
|
|
await this._shiftTestQueue();
|
|
testItem.pendingTestRunDonePromise.resolve();
|
|
}
|
|
_prepareReportTestActionEventArgs({ command, duration, result, testRun, err }) {
|
|
const args = {};
|
|
if (err)
|
|
args.err = err;
|
|
if (typeof duration === 'number')
|
|
args.duration = duration;
|
|
const testFixture = testRun.test.fixture;
|
|
return Object.assign(args, {
|
|
testRunId: testRun.id,
|
|
test: {
|
|
id: testRun.test.id,
|
|
name: testRun.test.name,
|
|
phase: testRun.phase,
|
|
},
|
|
fixture: {
|
|
name: testFixture.name,
|
|
id: testFixture.id,
|
|
},
|
|
command: (0, format_command_1.default)(command, result),
|
|
browser: testRun.browser,
|
|
});
|
|
}
|
|
async _onceTaskStartHandler(task) {
|
|
this.taskInfo = {
|
|
task: task,
|
|
passed: 0,
|
|
failed: 0,
|
|
skipped: 0,
|
|
testCount: task.tests.filter(test => !test.skip).length,
|
|
testQueue: Reporter._createTestQueue(task),
|
|
stopOnFirstFail: task.opts.stopOnFirstFail,
|
|
pendingTaskDonePromise: Reporter._createPendingPromise(),
|
|
};
|
|
const startTime = task.startTime;
|
|
const browserConnectionsInfo = []
|
|
.concat(...task.browserConnectionGroups)
|
|
.map(connection => connection.connectionInfo);
|
|
const first = this.taskInfo.testQueue[0];
|
|
const taskProperties = {
|
|
configuration: task.opts,
|
|
dashboardUrl: task.opts.dashboardUrl,
|
|
};
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTaskStart,
|
|
initialObject: task,
|
|
args: [
|
|
startTime,
|
|
browserConnectionsInfo,
|
|
this.taskInfo.testCount,
|
|
task.testStructure,
|
|
taskProperties,
|
|
],
|
|
});
|
|
if (first) {
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportFixtureStart,
|
|
initialObject: task,
|
|
args: [
|
|
first.fixture.name,
|
|
first.fixture.path,
|
|
first.fixture.meta,
|
|
],
|
|
});
|
|
}
|
|
}
|
|
async _onTaskTestRunStartHandler(testRun) {
|
|
if (!this.taskInfo)
|
|
return void 0;
|
|
const testItem = this._getTestItemForTestRun(this.taskInfo, testRun);
|
|
testItem.testRunIds.push(testRun.id);
|
|
if (!testItem.startTime)
|
|
testItem.startTime = +new Date();
|
|
testItem.pendingStarts--;
|
|
if (!testItem.pendingStarts) {
|
|
// @ts-ignore
|
|
if (this.plugin.reportTestStart) {
|
|
const testStartInfo = {
|
|
testRunIds: testItem.testRunIds,
|
|
testId: testItem.test.id,
|
|
startTime: new Date(testItem.startTime),
|
|
skipped: testItem.test.skip,
|
|
};
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTestStart,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
testItem.test.name,
|
|
testItem.test.meta,
|
|
testStartInfo,
|
|
],
|
|
});
|
|
}
|
|
testItem.pendingTestRunStartPromise.resolve();
|
|
}
|
|
return testItem.pendingTestRunStartPromise;
|
|
}
|
|
async _onTaskTestRunDoneHandler(testRun) {
|
|
if (!this.taskInfo)
|
|
return;
|
|
const reportItem = this._getTestItemForTestRun(this.taskInfo, testRun);
|
|
const isTestRunStoppedTaskExecution = !!testRun.errs.length && this.taskInfo.stopOnFirstFail;
|
|
const browser = Object.assign({ testRunId: testRun.id }, testRun.browser);
|
|
reportItem.browsers.push(browser);
|
|
reportItem.pendingRuns = isTestRunStoppedTaskExecution ? 0 : reportItem.pendingRuns - 1;
|
|
reportItem.unstable = reportItem.unstable || testRun.unstable;
|
|
reportItem.errs = reportItem.errs.concat(testRun.errs);
|
|
reportItem.warnings = testRun.warningLog ? (0, lodash_1.union)(reportItem.warnings, testRun.warningLog.messages) : [];
|
|
if (testRun.quarantine) {
|
|
reportItem.quarantine = reportItem.quarantine || {};
|
|
const reportItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors, testRunId }) => {
|
|
const passed = !errors.length;
|
|
result[testRunId] = { passed, errors };
|
|
browser.quarantineAttemptsTestRunIds = browser.quarantineAttemptsTestRunIds || [];
|
|
browser.quarantineAttemptsTestRunIds.push(testRunId);
|
|
return result;
|
|
}, {});
|
|
Object.assign(reportItem.quarantine, reportItemQuarantine);
|
|
}
|
|
if (!reportItem.pendingRuns)
|
|
await this._resolveTestItem(this.taskInfo, reportItem, testRun);
|
|
await reportItem.pendingTestRunDonePromise;
|
|
}
|
|
async _onTaskTestActionStart(_a) {
|
|
var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]);
|
|
if (!this.taskInfo)
|
|
return;
|
|
// @ts-ignore
|
|
if (this.plugin.reportTestActionStart) {
|
|
restArgs = this._prepareReportTestActionEventArgs(restArgs);
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTestActionStart,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
apiActionName,
|
|
restArgs,
|
|
],
|
|
});
|
|
}
|
|
}
|
|
async _onTaskTestActionDone(_a) {
|
|
var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]);
|
|
if (!this.taskInfo)
|
|
return;
|
|
// @ts-ignore
|
|
if (this.plugin.reportTestActionDone) {
|
|
restArgs = this._prepareReportTestActionEventArgs(restArgs);
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTestActionDone,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
apiActionName,
|
|
restArgs,
|
|
],
|
|
});
|
|
}
|
|
}
|
|
async _onceTaskDoneHandler() {
|
|
var _a;
|
|
if (!this.taskInfo)
|
|
return;
|
|
const endTime = new Date();
|
|
const result = {
|
|
passedCount: this.taskInfo.passed,
|
|
failedCount: this.taskInfo.failed,
|
|
skippedCount: this.taskInfo.skipped,
|
|
};
|
|
await this.dispatchToPlugin({
|
|
method: plugin_methods_1.default.reportTaskDone,
|
|
initialObject: this.taskInfo.task,
|
|
args: [
|
|
endTime,
|
|
this.taskInfo.passed,
|
|
(_a = this.taskInfo.task) === null || _a === void 0 ? void 0 : _a.warningLog.messages,
|
|
result,
|
|
],
|
|
});
|
|
this.taskInfo.pendingTaskDonePromise.resolve();
|
|
}
|
|
}
|
|
exports.default = Reporter;
|
|
module.exports = exports.default;
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQUtnQjtBQUVoQix5Q0FBeUQ7QUFDekQsZ0VBQStDO0FBQy9DLHNFQUFvRDtBQUNwRCw4RUFBcUQ7QUFDckQsK0NBQXdEO0FBZ0J4RCxnREFBMEU7QUFDMUUsdUdBQTRFO0FBQzVFLHdEQUErQjtBQUMvQixnREFBd0I7QUFDeEIsNENBQW9CO0FBSXBCLGtEQUEwQjtBQTBGMUIsTUFBTSxRQUFRLEdBQUcsSUFBQSxlQUFLLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUU1QyxNQUFxQixRQUFRO0lBT3pCLFlBQW9CLE1BQXNCLEVBQUUsVUFBc0IsRUFBRSxTQUFtQixFQUFFLElBQVk7UUFDakcsSUFBSSxDQUFDLE1BQU0sR0FBTyxJQUFJLHFCQUFrQixDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFFN0IsSUFBSSxDQUFDLFFBQVEsR0FBSSxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsR0FBSSxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFFM0IsSUFBSSxDQUFDLDhCQUE4QixFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBRSxNQUFnQjtRQUM3QyxPQUFRLE1BQXNCLENBQUMsS0FBSyxJQUFJLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUFJLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQ25HLENBQUM7SUFFTyxNQUFNLENBQUMscUJBQXFCO1FBQ2hDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQztRQUVwQixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFP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QU0sR0FBRztZQUNYLFdBQVcsRUFBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU07WUFDbEMsV0FBVyxFQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTTtZQUNsQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPO1NBQ3RDLENBQUM7UUFFRixNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztZQUN4QixNQUFNLEVBQVMsd0JBQW9CLENBQUMsY0FBYztZQUNsRCxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJO1lBQ2pDLElBQUksRUFBVztnQkFDWCxPQUFPO2dCQUNQLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTTtnQkFDcEIsTUFBQSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksMENBQUUsVUFBVSxDQUFDLFFBQVE7Z0JBQ3ZDLE1BQU07YUFDVDtTQUNKLENBQUMsQ0FBQztRQUVGLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUMsT0FBb0IsRUFBRSxDQUFDO0lBQ2pFLENBQUM7Q0FDSjtBQTVmRCwyQkE0ZkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIGZpbmQsXG4gICAgc29ydEJ5LFxuICAgIHVuaW9uLFxuICAgIGlzRnVuY3Rpb24sXG59IGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCB7IHdyaXRhYmxlIGFzIGlzV3JpdGFibGVTdHJlYW0gfSBmcm9tICdpcy1zdHJlYW0nO1xuaW1wb3J0IFJlcG9ydGVyUGx1Z2luSG9zdCBmcm9tICcuL3BsdWdpbi1ob3N0JztcbmltcG9ydCBSZXBvcnRlclBsdWdpbk1ldGhvZCBmcm9tICcuL3BsdWdpbi1tZXRob2RzJztcbmltcG9ydCBmb3JtYXRDb21tYW5kIGZyb20gJy4vY29tbWFuZC9mb3JtYXQtY29tbWFuZCc7XG5pbXBvcnQgeyBSZXBvcnRlclBsdWdpbkVycm9yIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUnO1xuaW1wb3J0IFRhc2sgZnJvbSAnLi4vcnVubmVyL3Rhc2snO1xuaW1wb3J0IHsgV3JpdGFibGUgYXMgV3JpdGFibGVTdHJlYW0sIFdyaXRhYmxlIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IFdyaXRlU3RyZWFtIH0gZnJvbSAndHR5JztcbmltcG9ydCBUZXN0UnVuIGZyb20gJy4uL3Rlc3QtcnVuJztcbmltcG9ydCBUZXN0IGZyb20gJy4uL2FwaS9zdHJ1Y3R1cmUvdGVzdCc7XG5pbXBvcnQgRml4dHVyZSBmcm9tICcuLi9hcGkvc3RydWN0dXJlL2ZpeHR1cmUnO1xuaW1wb3J0IFRlc3RSdW5FcnJvckZvcm1hdHRhYmxlQWRhcHRlciBmcm9tICcuLi9lcnJvcnMvdGVzdC1ydW4vZm9ybWF0dGFibGUtYWRhcHRlcic7XG5pbXBvcnQgeyBDb21tYW5kQmFzZSB9IGZyb20gJy4uL3Rlc3QtcnVuL2NvbW1hbmRzL2Jhc2UnO1xuXG5pbXBvcnQge1xuICAgIFJlcG9ydGVyUGx1Z2luLFxuICAgIFJlcG9ydGVyUGx1Z2luU291cmNlLFxuICAgIFJlcG9ydGVyU291cmNlLFxufSBmcm9tICcuL2ludGVyZmFjZXMnO1xuXG5pbXBvcnQgeyBnZXRQbHVnaW5GYWN0b3J5LCBwcm9jZXNzUmVwb3J0ZXJOYW1lIH0gZnJvbSAnLi4vdXRpbHMvcmVwb3J0ZXInO1xuaW1wb3J0IHJlc29sdmVQYXRoUmVsYXRpdmVseUN3ZCBmcm9tICcuLi91dGlscy9yZXNvbHZlLXBhdGgtcmVsYXRpdmVseS1jd2QnO1xuaW1wb3J0IG1ha2VEaXIgZnJvbSAnbWFrZS1kaXInO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IE1lc3NhZ2VCdXMgZnJvbSAnLi4vdXRpbHMvbWVzc2FnZS1idXMnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uIGZyb20gJy4uL2Jyb3dzZXIvY29ubmVjdGlvbic7XG5pbXBvcnQgeyBEaWN0aW9uYXJ5IH0gZnJvbSAnLi4vY29uZmlndXJhdGlvbi9pbnRlcmZhY2VzJztcbmltcG9ydCBkZWJ1ZyBmcm9tICdkZWJ1Zyc7XG5cbmludGVyZmFjZSBQZW5kaW5nUHJvbWlzZSB7XG4gICAgcmVzb2x2ZTogRnVuY3Rpb24gfCBudWxsO1xuICAgIHRoZW46IEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgVGFza0luZm8ge1xuICAgIHRhc2s6IFRhc2sgfCBudWxsO1xuICAgIHBhc3NlZDogbnVtYmVyO1xuICAgIGZhaWxlZDogbnVtYmVyO1xuICAgIHNraXBwZWQ6IG51bWJlcjtcbiAgICB0ZXN0Q291bnQ6IG51bWJlcjtcbiAgICB0ZXN0UXVldWU6IFRlc3RJbmZvW107XG4gICAgcmVhZG9ubHkgc3RvcE9uRmlyc3RGYWlsOiBib29sZWFuO1xuICAgIHJlYWRvbmx5IHBlbmRpbmdUYXNrRG9uZVByb21pc2U6IFBlbmRpbmdQcm9taXNlO1xufVxuXG5pbnRlcmZhY2UgVGVzdEluZm8ge1xuICAgIGZpeHR1cmU6IEZpeHR1cmU7XG4gICAgdGVzdDogVGVzdDtcbiAgICB0ZXN0UnVuSWRzOiBzdHJpbmdbXTtcbiAgICBzY3JlZW5zaG90UGF0aDogbnVsbCB8IHN0cmluZztcbiAgICBzY3JlZW5zaG90czogdW5rbm93bltdO1xuICAgIHZpZGVvczogdW5rbm93bltdO1xuICAgIHF1YXJhbnRpbmU6IG51bGwgfCBSZWNvcmQ8c3RyaW5nLCBvYmplY3Q+O1xuICAgIGVycnM6IFRlc3RSdW5FcnJvckZvcm1hdHRhYmxlQWRhcHRlcltdO1xuICAgIHdhcm5pbmdzOiBzdHJpbmdbXTtcbiAgICB1bnN0YWJsZTogYm9vbGVhbjtcbiAgICBzdGFydFRpbWU6IG51bGwgfCBudW1iZXI7XG4gICAgdGVzdFJ1bkluZm86IG51bGwgfCBUZXN0UnVuSW5mbztcbiAgICBwZW5kaW5nUnVuczogbnVtYmVyO1xuICAgIHBlbmRpbmdTdGFydHM6IG51bWJlcjtcbiAgICBwZW5kaW5nVGVzdFJ1bkRvbmVQcm9taXNlOiBQZW5kaW5nUHJvbWlzZTtcbiAgICBwZW5kaW5nVGVzdFJ1blN0YXJ0UHJvbWlzZTogUGVuZGluZ1Byb21pc2U7XG4gICAgYnJvd3NlcnM6IEJyb3dzZXJSdW5JbmZvW107XG59XG5cbmludGVyZmFjZSBGaXh0dXJlSW5mbyB7XG4gICAgaWQ6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmcgfCBudWxsO1xuICAgIHBhdGg6IHN0cmluZztcbiAgICBtZXRhOiBEaWN0aW9uYXJ5PHN0cmluZz47XG59XG5cbmludGVyZmFjZSBCcm93c2VyUnVuSW5mbyBleHRlbmRzIEJyb3dzZXIge1xuICAgIHRlc3RSdW5JZDogc3RyaW5nO1xuICAgIHF1YXJhbnRpbmVBdHRlbXB0c1Rlc3RSdW5JZHM/OiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIFRlc3RSdW5JbmZvIHtcbiAgICBlcnJzOiBUZXN0UnVuRXJyb3JGb3JtYXR0YWJsZUFkYXB0ZXJbXTtcbiAgICB3YXJuaW5nczogc3RyaW5nW107XG4gICAgZHVyYXRpb25NczogbnVtYmVyO1xuICAgIHVuc3RhYmxlOiBib29sZWFuO1xuICAgIHNjcmVlbnNob3RQYXRoOiBzdHJpbmc7XG4gICAgc2NyZWVuc2hvdHM6IHVua25vd247XG4gICAgdmlkZW9zOiB1bmtub3duO1xuICAgIHF1YXJhbnRpbmU6IHVua25vd247XG4gICAgc2tpcHBlZDogYm9vbGVhbjtcbiAgICBicm93c2VyczogdW5rbm93bltdO1xuICAgIHRlc3RJZDogc3RyaW5nO1xuICAgIGZpeHR1cmU6IEZpeHR1cmVJbmZvO1xufVxuXG5pbnRlcmZhY2UgUGx1Z2luTWV0aG9kQXJndW1lbnRzIHtcbiAgICBpbml0aWFsT2JqZWN0OiBUYXNrIHwgTWVzc2FnZUJ1cyB8IG51bGw7XG4gICAgbWV0aG9kOiBzdHJpbmc7XG4gICAgYXJnczogdW5rbm93bltdO1xufVxuXG5pbnRlcmZhY2UgUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJndW1lbnRzIHtcbiAgICBjb21tYW5kOiBDb21tYW5kQmFzZTtcbiAgICBkdXJhdGlvbjogbnVtYmVyO1xuICAgIHJlc3VsdDogdW5rbm93bjtcbiAgICB0ZXN0UnVuOiBUZXN0UnVuO1xuICAgIGVycjogVGVzdFJ1bkVycm9yRm9ybWF0dGFibGVBZGFwdGVyO1xufVxuXG5pbnRlcmZhY2UgUmVwb3J0VGFza0FjdGlvbkV2ZW50QXJndW1lbnRzIHtcbiAgICBhcGlBY3Rpb25OYW1lOiBzdHJpbmc7XG4gICAgcmVzdEFyZ3M6IG9iamVjdDtcbn1cblxuaW50ZXJmYWNlIFJlcG9ydFdhcm5pbmdFdmVudEFyZ3VtZW50cyB7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuICAgIHRlc3RSdW4/OiBUZXN0UnVuO1xuICAgIGFjdGlvbklkPzogc3RyaW5nO1xufVxuXG5jb25zdCBkZWJ1Z0xvZyA9IGRlYnVnKCd0ZXN0Y2FmZTpyZXBvcnRlcicpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZXBvcnRlciB7XG4gICAgcHVibGljIHJlYWRvbmx5IHBsdWdpbjogUmVwb3J0ZXJQbHVnaW5Ib3N0O1xuICAgIHB1YmxpYyByZWFkb25seSBtZXNzYWdlQnVzOiBNZXNzYWdlQnVzO1xuICAgIHB1YmxpYyBkaXNwb3NlZDogYm9vbGVhbjtcbiAgICBwdWJsaWMgdGFza0luZm86IFRhc2tJbmZvIHwgbnVsbDtcbiAgICBwdWJsaWMgcmVhZG9ubHkgb3V0U3RyZWFtOiBXcml0YWJsZTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvciAocGx1Z2luOiBSZXBvcnRlclBsdWdpbiwgbWVzc2FnZUJ1czogTWVzc2FnZUJ1cywgb3V0U3RyZWFtOiBXcml0YWJsZSwgbmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMucGx1Z2luICAgICA9IG5ldyBSZXBvcnRlclBsdWdpbkhvc3QocGx1Z2luLCBvdXRTdHJlYW0sIG5hbWUpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VCdXMgPSBtZXNzYWdlQnVzO1xuXG4gICAgICAgIHRoaXMuZGlzcG9zZWQgID0gZmFsc2U7XG4gICAgICAgIHRoaXMudGFza0luZm8gID0gbnVsbDtcbiAgICAgICAgdGhpcy5vdXRTdHJlYW0gPSBvdXRTdHJlYW07XG5cbiAgICAgICAgdGhpcy5fYXNzaWduTWVzc2FnZUJ1c0V2ZW50SGFuZGxlcnMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfaXNTcGVjaWFsU3RyZWFtIChzdHJlYW06IFdyaXRhYmxlKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoc3RyZWFtIGFzIFdyaXRlU3RyZWFtKS5pc1RUWSB8fCBzdHJlYW0gPT09IHByb2Nlc3Muc3Rkb3V0IHx8IHN0cmVhbSA9PT0gcHJvY2Vzcy5zdGRlcnI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2NyZWF0ZVBlbmRpbmdQcm9taXNlICgpOiBQZW5kaW5nUHJvbWlzZSB7XG4gICAgICAgIGxldCByZXNvbHZlciA9IG51bGw7XG5cbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZXIgPSByZXNvbHZlO1xuICAgICAgICB9KSBhcyB1bmtub3duIGFzIFBlbmRpbmdQcm9taXNlO1xuXG4gICAgICAgIHByb21pc2UucmVzb2x2ZSA9IHJlc29sdmVyO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBpbml0ICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFRvUGx1Z2luKHtcbiAgICAgICAgICAgIG1ldGhvZDogICAgICAgIFJlcG9ydGVyUGx1Z2luTWV0aG9kLmluaXQsXG4gICAgICAgICAgICBpbml0aWFsT2JqZWN0OiBudWxsLFxuICAgICAgICAgICAgYXJnczogICAgICAgICAgW3t9XSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGRpc3BhdGNoVG9QbHVnaW4gKHsgbWV0aG9kLCBpbml0aWFsT2JqZWN0LCBhcmdzID0gW10gfTogUGx1Z2luTWV0aG9kQXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpblttZXRob2RdKC4uLmFyZ3MpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChvcmlnaW5hbEVycm9yKSB7XG4gICAgICAgICAgICBjb25zdCB1bmNhdWdodEVycm9yID0gbmV3IFJlcG9ydGVyUGx1Z2luRXJyb3Ioe1xuICAgICAgICAgICAgICAgIG5hbWU6IHRoaXMucGx1Z2luLm5hbWUsXG4gICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgIG9yaWdpbmFsRXJyb3IsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgZGVidWdMb2coJ1BsdWdpbiBlcnJvcjogJU8nLCB1bmNhdWdodEVycm9yKTtcbiAgICAgICAgICAgIGRlYnVnTG9nKCdQbHVnaW4gZXJyb3I6IGluaXRpYWxPYmplY3Q6ICVPJywgaW5pdGlhbE9iamVjdCk7XG5cbiAgICAgICAgICAgIGlmIChpbml0aWFsT2JqZWN0KVxuICAgICAgICAgICAgICAgIGF3YWl0IGluaXRpYWxPYmplY3QuZW1pdCgnZXJyb3InLCB1bmNhdWdodEVycm9yKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aHJvdyB1bmNhdWdodEVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfYXNzaWduTWVzc2FnZUJ1c0V2ZW50SGFuZGxlcnMgKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBtZXNzYWdlQnVzID0gdGhpcy5tZXNzYWdlQnVzO1xuXG4gICAgICAgIG1lc3NhZ2VCdXMub24oJ3dhcm5pbmctYWRkJywgYXN5bmMgZSA9PiBhd2FpdCB0aGlzLl9vbldhcm5pbmdBZGRIYW5kbGVyKGUpKTtcblxuICAgICAgICBtZXNzYWdlQnVzLm9uY2UoJ3N0YXJ0JywgYXN5bmMgKHRhc2s6IFRhc2spID0+IGF3YWl0IHRoaXMuX29uY2VUYXNrU3RhcnRIYW5kbGVyKHRhc2spKTtcblxuICAgICAgICBtZXNzYWdlQnVzLm9uKCd0ZXN0LXJ1bi1zdGFydCcsIGFzeW5jIHRlc3RSdW4gPT4gYXdhaXQgdGhpcy5fb25UYXNrVGVzdFJ1blN0YXJ0SGFuZGxlcih0ZXN0UnVuKSk7XG5cbiAgICAgICAgbWVzc2FnZUJ1cy5vbigndGVzdC1ydW4tZG9uZScsIGFzeW5jIHRlc3RSdW4gPT4gYXdhaXQgdGhpcy5fb25UYXNrVGVzdFJ1bkRvbmVIYW5kbGVyKHRlc3RSdW4pKTtcblxuICAgICAgICBtZXNzYWdlQnVzLm9uKCd0ZXN0LWFjdGlvbi1zdGFydCcsIGFzeW5jIGUgPT4gYXdhaXQgdGhpcy5fb25UYXNrVGVzdEFjdGlvblN0YXJ0KGUpKTtcblxuICAgICAgICBtZXNzYWdlQnVzLm9uKCd0ZXN0LWFjdGlvbi1kb25lJywgYXN5bmMgZSA9PiBhd2FpdCB0aGlzLl9vblRhc2tUZXN0QWN0aW9uRG9uZShlKSk7XG5cbiAgICAgICAgbWVzc2FnZUJ1cy5vbmNlKCdkb25lJywgYXN5bmMgKCkgPT4gYXdhaXQgdGhpcy5fb25jZVRhc2tEb25lSGFuZGxlcigpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZGlzcG9zZSAoKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGlmICh0aGlzLmRpc3Bvc2VkKVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuXG4gICAgICAgIGlmICghaXNGdW5jdGlvbih0aGlzPy5vdXRTdHJlYW0/Lm9uY2UpXG4gICAgICAgICAgICB8fCBSZXBvcnRlci5faXNTcGVjaWFsU3RyZWFtKHRoaXMub3V0U3RyZWFtKVxuICAgICAgICAgICAgfHwgIWlzV3JpdGFibGVTdHJlYW0odGhpcy5vdXRTdHJlYW0pKVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbUZpbmlzaGVkUHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgICAgdGhpcy5vdXRTdHJlYW0ub25jZSgnZmluaXNoJywgcmVzb2x2ZSk7XG4gICAgICAgICAgICB0aGlzLm91dFN0cmVhbS5vbmNlKCdlcnJvcicsIHJlc29sdmUpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLm91dFN0cmVhbS5lbmQoKTtcblxuICAgICAgICByZXR1cm4gc3RyZWFtRmluaXNoZWRQcm9taXNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIGFzeW5jIF9lbnN1cmVPdXRTdHJlYW0gKG91dFN0cmVhbTogc3RyaW5nIHwgV3JpdGFibGVTdHJlYW0pOiBQcm9taXNlPFdyaXRhYmxlU3RyZWFtPiB7XG4gICAgICAgIGlmICh0eXBlb2Ygb3V0U3RyZWFtICE9PSAnc3RyaW5nJylcbiAgICAgICAgICAgIHJldHVybiBvdXRTdHJlYW07XG5cbiAgICAgICAgY29uc3QgZnVsbFJlcG9ydGVyT3V0cHV0UGF0aCA9IHJlc29sdmVQYXRoUmVsYXRpdmVseUN3ZChvdXRTdHJlYW0pO1xuXG4gICAgICAgIGF3YWl0IG1ha2VEaXIocGF0aC5kaXJuYW1lKGZ1bGxSZXBvcnRlck91dHB1dFBhdGgpKTtcblxuICAgICAgICByZXR1cm4gZnMuY3JlYXRlV3JpdGVTdHJlYW0oZnVsbFJlcG9ydGVyT3V0cHV0UGF0aCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX2FkZERlZmF1bHRSZXBvcnRlciAocmVwb3J0ZXJzOiBSZXBvcnRlclNvdXJjZVtdKTogdm9pZCB7XG4gICAgICAgIHJlcG9ydGVycy5wdXNoKHtcbiAgICAgICAgICAgIG5hbWU6ICAgJ3NwZWMnLFxuICAgICAgICAgICAgb3V0cHV0OiBwcm9jZXNzLnN0ZG91dCxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBhc3luYyBnZXRSZXBvcnRlclBsdWdpbnMgKHJlcG9ydGVyczogUmVwb3J0ZXJTb3VyY2VbXSA9IFtdKTogUHJvbWlzZTxSZXBvcnRlclBsdWdpblNvdXJjZVtdPiB7XG4gICAgICAgIGlmICghcmVwb3J0ZXJzLmxlbmd0aClcbiAgICAgICAgICAgIFJlcG9ydGVyLl9hZGREZWZhdWx0UmVwb3J0ZXIocmVwb3J0ZXJzKTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChhc3luYyAoeyBuYW1lLCBvdXRwdXQsIG9wdGlvbnMgfSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGx1Z2luRmFjdG9yeSA9IGdldFBsdWdpbkZhY3RvcnkobmFtZSk7XG4gICAgICAgICAgICBjb25zdCBwcm9jZXNzZWROYW1lID0gcHJvY2Vzc1JlcG9ydGVyTmFtZShuYW1lKTtcbiAgICAgICAgICAgIGNvbnN0IG91dFN0cmVhbSAgICAgPSBvdXRwdXQgPyBhd2FpdCBSZXBvcnRlci5fZW5zdXJlT3V0U3RyZWFtKG91dHB1dCkgOiB2b2lkIDA7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgcGx1Z2luOiBwbHVnaW5GYWN0b3J5KG9wdGlvbnMpLFxuICAgICAgICAgICAgICAgIG5hbWU6ICAgcHJvY2Vzc2VkTmFtZSxcbiAgICAgICAgICAgICAgICBvdXRTdHJlYW0sXG4gICAgICAgICAgICB9O1xuICAgICAgICB9KSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfb25XYXJuaW5nQWRkSGFuZGxlciAoeyBtZXNzYWdlLCB0ZXN0UnVuLCBhY3Rpb25JZCB9OiBSZXBvcnRXYXJuaW5nRXZlbnRBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFRvUGx1Z2luKHtcbiAgICAgICAgICAgIG1ldGhvZDogICAgICAgIFJlcG9ydGVyUGx1Z2luTWV0aG9kLnJlcG9ydFdhcm5pbmdzIGFzIHN0cmluZyxcbiAgICAgICAgICAgIGluaXRpYWxPYmplY3Q6IHRoaXMubWVzc2FnZUJ1cyxcbiAgICAgICAgICAgIGFyZ3M6ICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIHRlc3RSdW5JZDogdGVzdFJ1bj8uaWQsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbklkLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvL1Rhc2tcbiAgICBwcml2YXRlIHN0YXRpYyBfY3JlYXRlVGVzdEl0ZW0gKHRlc3Q6IFRlc3QsIHJ1bnNQZXJUZXN0OiBudW1iZXIpOiBUZXN0SW5mbyB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBmaXh0dXJlOiAgICAgICAgICAgICAgICAgICAgdGVzdC5maXh0dXJlIGFzIEZpeHR1cmUsXG4gICAgICAgICAgICB0ZXN0OiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCxcbiAgICAgICAgICAgIHRlc3RSdW5JZHM6ICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgIHNjcmVlbnNob3RQYXRoOiAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgdmlkZW9zOiAgICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgcXVhcmFudGluZTogICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICBlcnJzOiAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB1bnN0YWJsZTogICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICBzdGFydFRpbWU6ICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIHRlc3RSdW5JbmZvOiAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgcGVuZGluZ1J1bnM6ICAgICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1N0YXJ0czogICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZTogIFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpLFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2U6IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpLFxuICAgICAgICAgICAgYnJvd3NlcnM6ICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9jcmVhdGVUZXN0UXVldWUgKHRhc2s6IFRhc2spOiBUZXN0SW5mb1tdIHtcbiAgICAgICAgY29uc3QgcnVuc1BlclRlc3QgPSB0YXNrLmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzLmxlbmd0aDtcblxuICAgICAgICByZXR1cm4gdGFzay50ZXN0cy5tYXAodGVzdCA9PiBSZXBvcnRlci5fY3JlYXRlVGVzdEl0ZW0odGVzdCwgcnVuc1BlclRlc3QpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfY3JlYXRlVGVzdFJ1bkluZm8gKHJlcG9ydEl0ZW06IFRlc3RJbmZvKTogVGVzdFJ1bkluZm8ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyczogICAgICAgICAgIHNvcnRCeShyZXBvcnRJdGVtLmVycnMsIFsndXNlckFnZW50JywgJ2NvZGUnXSksXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgcmVwb3J0SXRlbS53YXJuaW5ncyxcbiAgICAgICAgICAgIGR1cmF0aW9uTXM6ICAgICArbmV3IERhdGUoKSAtIChyZXBvcnRJdGVtLnN0YXJ0VGltZSBhcyBudW1iZXIpLCAvL2VzbGludC1kaXNhYmxlLWxpbmUgIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHRyYS1wYXJlbnNcbiAgICAgICAgICAgIHVuc3RhYmxlOiAgICAgICByZXBvcnRJdGVtLnVuc3RhYmxlLFxuICAgICAgICAgICAgc2NyZWVuc2hvdFBhdGg6IHJlcG9ydEl0ZW0uc2NyZWVuc2hvdFBhdGggYXMgc3RyaW5nLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgIHJlcG9ydEl0ZW0uc2NyZWVuc2hvdHMsXG4gICAgICAgICAgICB2aWRlb3M6ICAgICAgICAgcmVwb3J0SXRlbS52aWRlb3MsXG4gICAgICAgICAgICBxdWFyYW50aW5lOiAgICAgcmVwb3J0SXRlbS5xdWFyYW50aW5lLFxuICAgICAgICAgICAgc2tpcHBlZDogICAgICAgIHJlcG9ydEl0ZW0udGVzdC5za2lwLFxuICAgICAgICAgICAgYnJvd3NlcnM6ICAgICAgIHJlcG9ydEl0ZW0uYnJvd3NlcnMsXG4gICAgICAgICAgICB0ZXN0SWQ6ICAgICAgICAgcmVwb3J0SXRlbS50ZXN0LmlkLFxuICAgICAgICAgICAgZml4dHVyZTogICAgICAgIHtcbiAgICAgICAgICAgICAgICBpZDogICByZXBvcnRJdGVtLmZpeHR1cmUuaWQsXG4gICAgICAgICAgICAgICAgbmFtZTogcmVwb3J0SXRlbS5maXh0dXJlLm5hbWUsXG4gICAgICAgICAgICAgICAgcGF0aDogcmVwb3J0SXRlbS5maXh0dXJlLnBhdGgsXG4gICAgICAgICAgICAgICAgbWV0YTogcmVwb3J0SXRlbS5maXh0dXJlLm1ldGEsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldFRlc3RJdGVtRm9yVGVzdFJ1biAodGFza0luZm86IFRhc2tJbmZvLCB0ZXN0UnVuOiBUZXN0UnVuKTogVGVzdEluZm8gfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gZmluZCh0YXNrSW5mby50ZXN0UXVldWUsIGkgPT4gaS50ZXN0ID09PSB0ZXN0UnVuLnRlc3QpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3NoaWZ0VGVzdFF1ZXVlICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnRhc2tJbmZvKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGxldCBjdXJyZW50Rml4dHVyZSA9IG51bGw7XG4gICAgICAgIGxldCBuZXh0UmVwb3J0SXRlbSA9IG51bGw7XG4gICAgICAgIGxldCB0ZXN0SXRlbSAgICAgICA9IG51bGw7XG4gICAgICAgIGNvbnN0IHRlc3RRdWV1ZSAgICA9IHRoaXMudGFza0luZm8udGVzdFF1ZXVlO1xuXG4gICAgICAgIHdoaWxlICh0ZXN0UXVldWUubGVuZ3RoICYmIHRlc3RRdWV1ZVswXS50ZXN0UnVuSW5mbykge1xuICAgICAgICAgICAgdGVzdEl0ZW0gICAgICAgPSB0ZXN0UXVldWUuc2hpZnQoKSBhcyBUZXN0SW5mbztcbiAgICAgICAgICAgIGN1cnJlbnRGaXh0dXJlID0gdGVzdEl0ZW0uZml4dHVyZTtcblxuICAgICAgICAgICAgLy8gTk9URTogaGVyZSB3ZSBhc3N1bWUgdGhhdCB0ZXN0cyBhcmUgc29ydGVkIGJ5IGZpeHR1cmUuXG4gICAgICAgICAgICAvLyBUaGVyZWZvcmUsIGlmIHRoZSBuZXh0IHJlcG9ydCBpdGVtIGhhcyBhIGRpZmZlcmVudFxuICAgICAgICAgICAgLy8gZml4dHVyZSwgd2UgY2FuIHJlcG9ydCB0aGlzIGZpeHR1cmUgc3RhcnQuXG4gICAgICAgICAgICBuZXh0UmVwb3J0SXRlbSA9IHRlc3RRdWV1ZVswXTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFRvUGx1Z2luKHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICAgICAgICBSZXBvcnRlclBsdWdpbk1ldGhvZC5yZXBvcnRUZXN0RG9uZSxcbiAgICAgICAgICAgICAgICBpbml0aWFsT2JqZWN0OiB0aGlzLnRhc2tJbmZvLnRhc2ssXG4gICAgICAgICAgICAgICAgYXJnczogICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICB0ZXN0SXRlbS50ZXN0Lm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHRlc3RJdGVtLnRlc3RSdW5JbmZvLFxuICAgICAgICAgICAgICAgICAgICB0ZXN0SXRlbS50ZXN0Lm1ldGEsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIW5leHRSZXBvcnRJdGVtIHx8IG5leHRSZXBvcnRJdGVtLmZpeHR1cmUgPT09IGN1cnJlbnRGaXh0dXJlKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoVG9QbHVnaW4oe1xuICAgICAgICAgICAgICAgIG1ldGhvZDogICAgICAgIFJlcG9ydGVyUGx1Z2luTWV0aG9kLnJlcG9ydEZpeHR1cmVTdGFydCxcbiAgICAgICAgICAgICAgICBpbml0aWFsT2JqZWN0OiB0aGlzLnRhc2tJbmZvLnRhc2ssXG4gICAgICAgICAgICAgICAgYXJnczogICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBuZXh0UmVwb3J0SXRlbS5maXh0dXJlLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgIG5leHRSZXBvcnRJdGVtLmZpeHR1cmUucGF0aCxcbiAgICAgICAgICAgICAgICAgICAgbmV4dFJlcG9ydEl0ZW0uZml4dHVyZS5tZXRhLFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3Jlc29sdmVUZXN0SXRlbSAodGFza0luZm86IFRhc2tJbmZvLCB0ZXN0SXRlbTogVGVzdEluZm8sIHRlc3RSdW46IFRlc3RSdW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0YXNrSW5mby50YXNrKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmICh0YXNrSW5mby50YXNrLnNjcmVlbnNob3RzLmhhc0NhcHR1cmVkRm9yKHRlc3RSdW4udGVzdCkpIHtcbiAgICAgICAgICAgIHRlc3RJdGVtLnNjcmVlbnNob3RQYXRoID0gdGFza0luZm8udGFzay5zY3JlZW5zaG90cy5nZXRQYXRoRm9yKHRlc3RSdW4udGVzdCk7XG4gICAgICAgICAgICB0ZXN0SXRlbS5zY3JlZW5zaG90cyAgICA9IHRhc2tJbmZvLnRhc2suc2NyZWVuc2hvdHMuZ2V0U2NyZWVuc2hvdHNJbmZvKHRlc3RSdW4udGVzdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGFza0luZm8udGFzay52aWRlb3MpXG4gICAgICAgICAgICB0ZXN0SXRlbS52aWRlb3MgPSB0YXNrSW5mby50YXNrLnZpZGVvcy5nZXRUZXN0VmlkZW9zKHRlc3RJdGVtLnRlc3QuaWQpO1xuXG4gICAgICAgIGlmICh0ZXN0UnVuLnF1YXJhbnRpbmUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRlc3RJdGVtUXVhcmFudGluZSA9IHRlc3RSdW4ucXVhcmFudGluZS5hdHRlbXB0cy5yZWR1Y2UoKHJlc3VsdDogUmVjb3JkPHN0cmluZywgb2JqZWN0PiwgeyBlcnJvcnMgfSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhc3NlZCAgICAgICAgICAgID0gIWVycm9ycy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QgcXVhcmFudGluZUF0dGVtcHQgPSBpbmRleCArIDE7XG5cbiAgICAgICAgICAgICAgICByZXN1bHRbcXVhcmFudGluZUF0dGVtcHRdID0geyBwYXNzZWQgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LCB7IH0pO1xuXG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKHRlc3RJdGVtLnF1YXJhbnRpbmUgYXMgb2JqZWN0LCB0ZXN0SXRlbVF1YXJhbnRpbmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0ZXN0SXRlbS50ZXN0UnVuSW5mbykge1xuICAgICAgICAgICAgdGVzdEl0ZW0udGVzdFJ1bkluZm8gPSBSZXBvcnRlci5fY3JlYXRlVGVzdFJ1bkluZm8odGVzdEl0ZW0pO1xuXG4gICAgICAgICAgICBpZiAodGVzdEl0ZW0udGVzdC5za2lwKVxuICAgICAgICAgICAgICAgIHRhc2tJbmZvLnNraXBwZWQrKztcbiAgICAgICAgICAgIGVsc2UgaWYgKHRlc3RJdGVtLmVycnMubGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRhc2tJbmZvLmZhaWxlZCsrO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHRhc2tJbmZvLnBhc3NlZCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fc2hpZnRUZXN0UXVldWUoKTtcblxuICAgICAgICAodGVzdEl0ZW0ucGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZS5yZXNvbHZlIGFzIEZ1bmN0aW9uKSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3ByZXBhcmVSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmdzICh7IGNvbW1hbmQsIGR1cmF0aW9uLCByZXN1bHQsIHRlc3RSdW4sIGVyciB9OiBSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmd1bWVudHMpOiBhbnkge1xuICAgICAgICBjb25zdCBhcmdzOiBhbnkgPSB7fTtcblxuICAgICAgICBpZiAoZXJyKVxuICAgICAgICAgICAgYXJncy5lcnIgPSBlcnI7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBkdXJhdGlvbiA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICBhcmdzLmR1cmF0aW9uID0gZHVyYXRpb247XG5cbiAgICAgICAgY29uc3QgdGVzdEZpeHR1cmUgPSB0ZXN0UnVuLnRlc3QuZml4dHVyZSBhcyBGaXh0dXJlO1xuXG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGFyZ3MsIHtcbiAgICAgICAgICAgIHRlc3RSdW5JZDogdGVzdFJ1bi5pZCxcbiAgICAgICAgICAgIHRlc3Q6ICAgICAge1xuICAgICAgICAgICAgICAgIGlkOiAgICB0ZXN0UnVuLnRlc3QuaWQsXG4gICAgICAgICAgICAgICAgbmFtZTogIHRlc3RSdW4udGVzdC5uYW1lLFxuICAgICAgICAgICAgICAgIHBoYXNlOiB0ZXN0UnVuLnBoYXNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZpeHR1cmU6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiB0ZXN0Rml4dHVyZS5uYW1lLFxuICAgICAgICAgICAgICAgIGlkOiAgIHRlc3RGaXh0dXJlLmlkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbW1hbmQ6IGZvcm1hdENvbW1hbmQoY29tbWFuZCwgcmVzdWx0KSxcbiAgICAgICAgICAgIGJyb3dzZXI6IHRlc3RSdW4uYnJvd3NlcixcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICBwcml2YXRlIGFzeW5jIF9vbmNlVGFza1N0YXJ0SGFuZGxlciAodGFzazogVGFzayk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnRhc2tJbmZvID0ge1xuICAgICAgICAgICAgdGFzazogICAgICAgICAgICAgICAgICAgdGFzayxcbiAgICAgICAgICAgIHBhc3NlZDogICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICBmYWlsZWQ6ICAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgc2tpcHBlZDogICAgICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIHRlc3RDb3VudDogICAgICAgICAgICAgIHRhc2sudGVzdHMuZmlsdGVyKHRlc3QgPT4gIXRlc3Quc2tpcCkubGVuZ3RoLFxuICAgICAgICAgICAgdGVzdFF1ZXVlOiAgICAgICAgICAgICAgUmVwb3J0ZXIuX2NyZWF0ZVRlc3RRdWV1ZSh0YXNrKSxcbiAgICAgICAgICAgIHN0b3BPbkZpcnN0RmFpbDogICAgICAgIHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWwgYXMgYm9vbGVhbixcbiAgICAgICAgICAgIHBlbmRpbmdUYXNrRG9uZVByb21pc2U6IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSAgICAgICAgICAgICAgPSB0YXNrLnN0YXJ0VGltZTtcbiAgICAgICAgY29uc3QgYnJvd3NlckNvbm5lY3Rpb25zSW5mbyA9IChbXSBhcyBCcm93c2VyQ29ubmVjdGlvbltdKVxuICAgICAgICAgICAgLmNvbmNhdCguLi50YXNrLmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzKVxuICAgICAgICAgICAgLm1hcChjb25uZWN0aW9uID0+IGNvbm5lY3Rpb24uY29ubmVjdGlvbkluZm8pO1xuICAgICAgICBjb25zdCBmaXJzdCAgICAgICAgICAgICAgICAgID0gdGhpcy50YXNrSW5mby50ZXN0UXVldWVbMF07XG5cbiAgICAgICAgY29uc3QgdGFza1Byb3BlcnRpZXMgPSB7XG4gICAgICAgICAgICBjb25maWd1cmF0aW9uOiB0YXNrLm9wdHMsXG4gICAgICAgICAgICBkYXNoYm9hcmRVcmw6ICB0YXNrLm9wdHMuZGFzaGJvYXJkVXJsLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hUb1BsdWdpbih7XG4gICAgICAgICAgICBtZXRob2Q6ICAgICAgICBSZXBvcnRlclBsdWdpbk1ldGhvZC5yZXBvcnRUYXNrU3RhcnQsXG4gICAgICAgICAgICBpbml0aWFsT2JqZWN0OiB0YXNrLFxuICAgICAgICAgICAgYXJnczogICAgICAgICAgW1xuICAgICAgICAgICAgICAgIHN0YXJ0VGltZSxcbiAgICAgICAgICAgICAgICBicm93c2VyQ29ubmVjdGlvbnNJbmZvLFxuICAgICAgICAgICAgICAgIHRoaXMudGFza0luZm8udGVzdENvdW50LFxuICAgICAgICAgICAgICAgIHRhc2sudGVzdFN0cnVjdHVyZSxcbiAgICAgICAgICAgICAgICB0YXNrUHJvcGVydGllcyxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChmaXJzdCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFRvUGx1Z2luKHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICAgICAgICBSZXBvcnRlclBsdWdpbk1ldGhvZC5yZXBvcnRGaXh0dXJlU3RhcnQsXG4gICAgICAgICAgICAgICAgaW5pdGlhbE9iamVjdDogdGFzayxcbiAgICAgICAgICAgICAgICBhcmdzOiAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgIGZpcnN0LmZpeHR1cmUubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZmlyc3QuZml4dHVyZS5wYXRoLFxuICAgICAgICAgICAgICAgICAgICBmaXJzdC5maXh0dXJlLm1ldGEsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfb25UYXNrVGVzdFJ1blN0YXJ0SGFuZGxlciAodGVzdFJ1bjogVGVzdFJ1bik6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBpZiAoIXRoaXMudGFza0luZm8pXG4gICAgICAgICAgICByZXR1cm4gdm9pZCAwO1xuXG4gICAgICAgIGNvbnN0IHRlc3RJdGVtID0gdGhpcy5fZ2V0VGVzdEl0ZW1Gb3JUZXN0UnVuKHRoaXMudGFza0luZm8sIHRlc3RSdW4pIGFzIFRlc3RJbmZvO1xuXG4gICAgICAgIHRlc3RJdGVtLnRlc3RSdW5JZHMucHVzaCh0ZXN0UnVuLmlkKTtcblxuICAgICAgICBpZiAoIXRlc3RJdGVtLnN0YXJ0VGltZSlcbiAgICAgICAgICAgIHRlc3RJdGVtLnN0YXJ0VGltZSA9ICtuZXcgRGF0ZSgpO1xuXG4gICAgICAgIHRlc3RJdGVtLnBlbmRpbmdTdGFydHMtLTtcblxuICAgICAgICBpZiAoIXRlc3RJdGVtLnBlbmRpbmdTdGFydHMpIHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGlmICh0aGlzLnBsdWdpbi5yZXBvcnRUZXN0U3RhcnQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZXN0U3RhcnRJbmZvID0ge1xuICAgICAgICAgICAgICAgICAgICB0ZXN0UnVuSWRzOiB0ZXN0SXRlbS50ZXN0UnVuSWRzLFxuICAgICAgICAgICAgICAgICAgICB0ZXN0SWQ6ICAgICB0ZXN0SXRlbS50ZXN0LmlkLFxuICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWU6ICBuZXcgRGF0ZSh0ZXN0SXRlbS5zdGFydFRpbWUpLFxuICAgICAgICAgICAgICAgICAgICBza2lwcGVkOiAgICB0ZXN0SXRlbS50ZXN0LnNraXAsXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hUb1BsdWdpbih7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogICAgICAgIFJlcG9ydGVyUGx1Z2luTWV0aG9kLnJlcG9ydFRlc3RTdGFydCBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxPYmplY3Q6IHRoaXMudGFza0luZm8udGFzayxcbiAgICAgICAgICAgICAgICAgICAgYXJnczogICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdEl0ZW0udGVzdC5uYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdEl0ZW0udGVzdC5tZXRhLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGVzdFN0YXJ0SW5mbyxcbiAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgKHRlc3RJdGVtLnBlbmRpbmdUZXN0UnVuU3RhcnRQcm9taXNlLnJlc29sdmUgYXMgRnVuY3Rpb24pKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGVzdEl0ZW0ucGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfb25UYXNrVGVzdFJ1bkRvbmVIYW5kbGVyICh0ZXN0UnVuOiBUZXN0UnVuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghdGhpcy50YXNrSW5mbylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCByZXBvcnRJdGVtICAgICAgICAgICAgICAgICAgICA9IHRoaXMuX2dldFRlc3RJdGVtRm9yVGVzdFJ1bih0aGlzLnRhc2tJbmZvLCB0ZXN0UnVuKSBhcyBUZXN0SW5mbztcbiAgICAgICAgY29uc3QgaXNUZXN0UnVuU3RvcHBlZFRhc2tFeGVjdXRpb24gPSAhIXRlc3RSdW4uZXJycy5sZW5ndGggJiYgdGhpcy50YXNrSW5mby5zdG9wT25GaXJzdEZhaWw7XG4gICAgICAgIGNvbnN0IGJyb3dzZXI6IEJyb3dzZXJSdW5JbmZvICAgICAgID0gT2JqZWN0LmFzc2lnbih7IHRlc3RSdW5JZDogdGVzdFJ1bi5pZCB9LCB0ZXN0UnVuLmJyb3dzZXIpO1xuXG4gICAgICAgIHJlcG9ydEl0ZW0uYnJvd3NlcnMucHVzaChicm93c2VyKTtcblxuICAgICAgICByZXBvcnRJdGVtLnBlbmRpbmdSdW5zID0gaXNUZXN0UnVuU3RvcHBlZFRhc2tFeGVjdXRpb24gPyAwIDogcmVwb3J0SXRlbS5wZW5kaW5nUnVucyAtIDE7XG4gICAgICAgIHJlcG9ydEl0ZW0udW5zdGFibGUgICAgPSByZXBvcnRJdGVtLnVuc3RhYmxlIHx8IHRlc3RSdW4udW5zdGFibGU7XG4gICAgICAgIHJlcG9ydEl0ZW0uZXJycyAgICAgICAgPSByZXBvcnRJdGVtLmVycnMuY29uY2F0KHRlc3RSdW4uZXJycyk7XG4gICAgICAgIHJlcG9ydEl0ZW0ud2FybmluZ3MgICAgPSB0ZXN0UnVuLndhcm5pbmdMb2cgPyB1bmlvbihyZXBvcnRJdGVtLndhcm5pbmdzLCB0ZXN0UnVuLndhcm5pbmdMb2cubWVzc2FnZXMpIDogW107XG5cbiAgICAgICAgaWYgKHRlc3RSdW4ucXVhcmFudGluZSkge1xuICAgICAgICAgICAgcmVwb3J0SXRlbS5xdWFyYW50aW5lID0gcmVwb3J0SXRlbS5xdWFyYW50aW5lIHx8IHt9O1xuXG4gICAgICAgICAgICBjb25zdCByZXBvcnRJdGVtUXVhcmFudGluZSA9IHRlc3RSdW4ucXVhcmFudGluZS5hdHRlbXB0cy5yZWR1Y2UoKHJlc3VsdDogUmVjb3JkPHN0cmluZywgb2JqZWN0PiwgeyBlcnJvcnMsIHRlc3RSdW5JZCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFzc2VkID0gIWVycm9ycy5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICByZXN1bHRbdGVzdFJ1bklkXSAgICAgICAgICAgICAgICAgICAgPSB7IHBhc3NlZCwgZXJyb3JzIH07XG4gICAgICAgICAgICAgICAgYnJvd3Nlci5xdWFyYW50aW5lQXR0ZW1wdHNUZXN0UnVuSWRzID0gYnJvd3Nlci5xdWFyYW50aW5lQXR0ZW1wdHNUZXN0UnVuSWRzIHx8IFtdO1xuXG4gICAgICAgICAgICAgICAgYnJvd3Nlci5xdWFyYW50aW5lQXR0ZW1wdHNUZXN0UnVuSWRzLnB1c2godGVzdFJ1bklkKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LCB7fSk7XG5cbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ocmVwb3J0SXRlbS5xdWFyYW50aW5lLCByZXBvcnRJdGVtUXVhcmFudGluZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlcG9ydEl0ZW0ucGVuZGluZ1J1bnMpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9yZXNvbHZlVGVzdEl0ZW0odGhpcy50YXNrSW5mbywgcmVwb3J0SXRlbSwgdGVzdFJ1bik7XG5cbiAgICAgICAgYXdhaXQgcmVwb3J0SXRlbS5wZW5kaW5nVGVzdFJ1bkRvbmVQcm9taXNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX29uVGFza1Rlc3RBY3Rpb25TdGFydCAoeyBhcGlBY3Rpb25OYW1lLCAuLi5yZXN0QXJncyB9OiBSZXBvcnRUYXNrQWN0aW9uRXZlbnRBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnRhc2tJbmZvKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgaWYgKHRoaXMucGx1Z2luLnJlcG9ydFRlc3RBY3Rpb25TdGFydCkge1xuICAgICAgICAgICAgcmVzdEFyZ3MgPSB0aGlzLl9wcmVwYXJlUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJncyhyZXN0QXJncyBhcyB1bmtub3duIGFzIFJlcG9ydFRlc3RBY3Rpb25FdmVudEFyZ3VtZW50cyk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hUb1BsdWdpbih7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAgICAgICAgUmVwb3J0ZXJQbHVnaW5NZXRob2QucmVwb3J0VGVzdEFjdGlvblN0YXJ0IGFzIHN0cmluZyxcbiAgICAgICAgICAgICAgICBpbml0aWFsT2JqZWN0OiB0aGlzLnRhc2tJbmZvLnRhc2ssXG4gICAgICAgICAgICAgICAgYXJnczogICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICBhcGlBY3Rpb25OYW1lLFxuICAgICAgICAgICAgICAgICAgICByZXN0QXJncyxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9vblRhc2tUZXN0QWN0aW9uRG9uZSAoeyBhcGlBY3Rpb25OYW1lLCAuLi5yZXN0QXJncyB9OiBSZXBvcnRUYXNrQWN0aW9uRXZlbnRBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLnRhc2tJbmZvKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgaWYgKHRoaXMucGx1Z2luLnJlcG9ydFRlc3RBY3Rpb25Eb25lKSB7XG4gICAgICAgICAgICByZXN0QXJncyA9IHRoaXMuX3ByZXBhcmVSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmdzKHJlc3RBcmdzIGFzIHVua25vd24gYXMgUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJndW1lbnRzKTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5kaXNwYXRjaFRvUGx1Z2luKHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICAgICAgICBSZXBvcnRlclBsdWdpbk1ldGhvZC5yZXBvcnRUZXN0QWN0aW9uRG9uZSBhcyBzdHJpbmcsXG4gICAgICAgICAgICAgICAgaW5pdGlhbE9iamVjdDogdGhpcy50YXNrSW5mby50YXNrLFxuICAgICAgICAgICAgICAgIGFyZ3M6ICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAgICAgYXBpQWN0aW9uTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgcmVzdEFyZ3MsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfb25jZVRhc2tEb25lSGFuZGxlciAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghdGhpcy50YXNrSW5mbylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBlbmRUaW1lID0gbmV3IERhdGUoKTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgICAgICBwYXNzZWRDb3VudDogIHRoaXMudGFza0luZm8ucGFzc2VkLFxuICAgICAgICAgICAgZmFpbGVkQ291bnQ6ICB0aGlzLnRhc2tJbmZvLmZhaWxlZCxcbiAgICAgICAgICAgIHNraXBwZWRDb3VudDogdGhpcy50YXNrSW5mby5za2lwcGVkLFxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IHRoaXMuZGlzcGF0Y2hUb1BsdWdpbih7XG4gICAgICAgICAgICBtZXRob2Q6ICAgICAgICBSZXBvcnRlclBsdWdpbk1ldGhvZC5yZXBvcnRUYXNrRG9uZSxcbiAgICAgICAgICAgIGluaXRpYWxPYmplY3Q6IHRoaXMudGFza0luZm8udGFzayxcbiAgICAgICAgICAgIGFyZ3M6ICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBlbmRUaW1lLFxuICAgICAgICAgICAgICAgIHRoaXMudGFza0luZm8ucGFzc2VkLFxuICAgICAgICAgICAgICAgIHRoaXMudGFza0luZm8udGFzaz8ud2FybmluZ0xvZy5tZXNzYWdlcyxcbiAgICAgICAgICAgICAgICByZXN1bHQsXG4gICAgICAgICAgICBdLFxuICAgICAgICB9KTtcblxuICAgICAgICAodGhpcy50YXNrSW5mby5wZW5kaW5nVGFza0RvbmVQcm9taXNlLnJlc29sdmUgYXMgRnVuY3Rpb24pKCk7XG4gICAgfVxufVxuIl19
|