"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const url_1 = require("url"); const chrome_remote_interface_1 = __importDefault(require("chrome-remote-interface")); const child_process_1 = require("child_process"); const endpoint_utils_1 = require("endpoint-utils"); const io_1 = require("./io"); const test_structure_1 = require("../serialization/test-structure"); const prepare_options_1 = __importDefault(require("../serialization/prepare-options")); const test_run_tracker_1 = __importDefault(require("../../api/test-run-tracker")); const test_controller_1 = __importDefault(require("../../api/test-controller")); const proxy_1 = require("../utils/ipc/proxy"); const transport_1 = require("../utils/ipc/transport"); const async_event_emitter_1 = __importDefault(require("../../utils/async-event-emitter")); const error_list_1 = __importDefault(require("../../errors/error-list")); const debug_action_1 = __importDefault(require("../../utils/debug-action")); const observation_1 = require("../../test-run/commands/observation"); const method_should_not_be_called_error_1 = __importDefault(require("../utils/method-should-not-be-called-error")); const test_run_1 = require("../../errors/test-run"); const handle_errors_1 = require("../../utils/handle-errors"); const node_arguments_filter_1 = require("../../cli/node-arguments-filter"); const SERVICE_PATH = require.resolve('./service-loader'); const INTERNAL_FILES_URL = (0, url_1.pathToFileURL)(path_1.default.join(__dirname, '../../')); const INSPECT_RE = new RegExp(`^(${node_arguments_filter_1.V8_DEBUG_FLAGS.join('|')})`); const INSPECT_PORT_RE = new RegExp(`^(${node_arguments_filter_1.V8_DEBUG_FLAGS.join('|')})=(.+:)?(\\d+)$`); const INITIAL_DEBUGGER_BREAK_ON_START = 'Break on start'; const errorTypeConstructors = new Map([ [test_run_1.UnhandledPromiseRejectionError.name, test_run_1.UnhandledPromiseRejectionError], [test_run_1.UncaughtExceptionError.name, test_run_1.UncaughtExceptionError], ]); class CompilerHost extends async_event_emitter_1.default { constructor({ developmentMode, v8Flags }) { super(); this.runtime = Promise.resolve(void 0); this.developmentMode = developmentMode; this.v8Flags = v8Flags; this.initialized = false; } _setupRoutes(proxy) { proxy.register([ this.executeCommand, this.ready, this.onRequestHookEvent, this.setMock, this.setConfigureResponseEventOptions, this.setHeaderOnConfigureResponseEvent, this.removeHeaderOnConfigureResponseEvent, this.executeRequestFilterRulePredicate, this.executeMockPredicate, this.getWarningMessages, this.addRequestEventListeners, this.removeRequestEventListeners, this.initializeTestRunData, this.getAssertionActualValue, this.executeRoleInitFn, this.getCtx, this.getFixtureCtx, this.setCtx, this.setFixtureCtx, this.updateRoleProperty, this.executeJsExpression, this.executeAsyncJsExpression, this.executeAssertionFn, this.addUnexpectedError, this.checkWindow, this.removeTestRunFromState, this.removeFixtureCtxsFromState, this.removeUnitsFromState, ], this); } _setupDebuggerHandlers() { if (!this.cdp) return; test_run_tracker_1.default.on(debug_action_1.default.resume, async () => { if (!this.cdp) return; const disableDebugMethodName = test_controller_1.default.disableDebugForNonDebugCommands.name; // NOTE: disable `debugger` for non-debug commands if the `Resume` button is clicked // the `includeCommandLineAPI` option allows to use the `require` functoion in the expression // TODO: debugging: refactor to use absolute paths await this.cdp.Runtime.evaluate({ expression: `require.main.require('../../api/test-controller').${disableDebugMethodName}()`, includeCommandLineAPI: true, }); await this.cdp.Debugger.resume({ terminateOnResume: false }); }); test_run_tracker_1.default.on(debug_action_1.default.step, async () => { if (!this.cdp) return; const enableDebugMethodName = test_controller_1.default.enableDebugForNonDebugCommands.name; // NOTE: enable `debugger` for non-debug commands in the `Next Action` button is clicked // the `includeCommandLineAPI` option allows to use the `require` functoion in the expression // TODO: debugging: refactor to use absolute paths await this.cdp.Runtime.evaluate({ expression: `require.main.require('../../api/test-controller').${enableDebugMethodName}()`, includeCommandLineAPI: true, }); await this.cdp.Debugger.resume({ terminateOnResume: false }); }); // NOTE: need to step out from the source code until breakpoint is set in the code of test // force DebugCommand if breakpoint stopped in the test code // TODO: debugging: refactor to this.cdp.Debugger.on('paused') after updating to chrome-remote-interface@0.30.0 this.cdp.on('Debugger.paused', (args) => { const { callFrames } = args; if (this.cdp) { if (args.reason === INITIAL_DEBUGGER_BREAK_ON_START) return this.cdp.Debugger.resume({ terminateOnResume: false }); if (callFrames[0].url.includes(INTERNAL_FILES_URL)) return this.cdp.Debugger.stepOut(); Object.values(test_run_tracker_1.default.activeTestRuns).forEach(testRun => { if (!testRun.debugging) testRun.executeCommand(new observation_1.DebugCommand()); }); } return Promise.resolve(); }); // NOTE: need to hide Status Bar if debugger is resumed // TODO: debugging: refactor to this.cdp.Debugger.on('resumed') after updating to chrome-remote-interface@0.30.0 this.cdp.on('Debugger.resumed', () => { Object.values(test_run_tracker_1.default.activeTestRuns).forEach(testRun => { if (testRun.debugging) testRun.executeCommand(new observation_1.DisableDebugCommand()); }); }); } parseDebugPort() { if (this.v8Flags) { for (let i = 0; i < this.v8Flags.length; i++) { const match = this.v8Flags[i].match(INSPECT_PORT_RE); if (match) return match[3]; } } return null; } _getServiceProcessArgs(port) { let args = []; if (this.v8Flags) args = this.v8Flags.filter(flag => !INSPECT_RE.test(flag)); // TODO: debugging: refactor to a separate debug info parsing unit const inspectBrkFlag = `--inspect-brk=127.0.0.1:${port}`; args.push(inspectBrkFlag, SERVICE_PATH); return args; } async _init(runtime) { const resolvedRuntime = await runtime; if (resolvedRuntime) return resolvedRuntime; try { const port = this.parseDebugPort() || await (0, endpoint_utils_1.getFreePort)(); const args = this._getServiceProcessArgs(port.toString()); const service = (0, child_process_1.spawn)(process.argv0, args, { stdio: [0, 1, 2, 'pipe', 'pipe', 'pipe'] }); // NOTE: need to wait, otherwise the error will be at `await cdp(...)` // TODO: debugging: refactor to use delay and multiple tries await new Promise(r => setTimeout(r, 2000)); // @ts-ignore this.cdp = await (0, chrome_remote_interface_1.default)({ port }); if (!this.cdp) return void 0; if (!this.developmentMode) this._setupDebuggerHandlers(); await this.cdp.Debugger.enable({}); await this.cdp.Runtime.enable(); await this.cdp.Runtime.runIfWaitingForDebugger(); // HACK: Node.js definition are not correct when additional I/O channels are sp const stdio = service.stdio; const proxy = new proxy_1.IPCProxy(new transport_1.HostTransport(stdio[io_1.HOST_INPUT_FD], stdio[io_1.HOST_OUTPUT_FD], stdio[io_1.HOST_SYNC_FD])); this._setupRoutes(proxy); await this.once('ready'); return { proxy, service }; } catch (e) { return void 0; } } async _getRuntime() { const runtime = await this.runtime; if (!runtime) throw new Error('Runtime is not available.'); return runtime; } _getTargetTestRun(id) { return test_run_tracker_1.default.activeTestRuns[id]; } async init() { this.runtime = this._init(this.runtime); await this.runtime; this.initialized = true; } async stop() { if (!this.initialized) return; const { service, proxy } = await this._getRuntime(); service.kill(); proxy.stop(); } _wrapTestFunction(id, functionName) { return async (testRun) => { try { return await this.runTestFn({ id, functionName, testRunId: testRun.id }); } catch (err) { const errList = new error_list_1.default(); errList.addError(err); throw errList; } }; } _wrapRequestFilterRulePredicate({ testId, hookId, ruleId }) { return async (requestInfo) => { return await this.executeRequestFilterRulePredicate({ testId, hookId, ruleId, requestInfo }); }; } _wrapMockPredicate({ mock, testId, hookId, ruleId }) { mock.body = async (requestInfo, res) => { return await this.executeMockPredicate({ testId, hookId, ruleId, requestInfo, res }); }; } _getErrorTypeConstructor(type) { return errorTypeConstructors.get(type); } async ready() { this.emit('ready'); } executeCommandSync() { throw new method_should_not_be_called_error_1.default(); } async executeCommand({ command, id, callsite }) { return this ._getTargetTestRun(id) .executeCommand(command, callsite); } async getTests({ sourceList, compilerOptions, runnableConfigurationId }, baseUrl) { const { proxy } = await this._getRuntime(); const units = await proxy.call(this.getTests, { sourceList, compilerOptions, runnableConfigurationId }, baseUrl); return (0, test_structure_1.restore)(units, (...args) => this._wrapTestFunction(...args), (ruleLocator) => this._wrapRequestFilterRulePredicate(ruleLocator)); } async runTestFn({ id, functionName, testRunId }) { const { proxy } = await this._getRuntime(); return await proxy.call(this.runTestFn, { id, functionName, testRunId }); } async cleanUp() { const { proxy } = await this._getRuntime(); await proxy.call(this.cleanUp); } async setUserVariables(userVariables) { const { proxy } = await this._getRuntime(); await proxy.call(this.setUserVariables, userVariables); } async setOptions({ value }) { const { proxy } = await this._getRuntime(); const preparedOptions = (0, prepare_options_1.default)(value); await proxy.call(this.setOptions, { value: preparedOptions }); } async onRequestHookEvent({ name, testId, hookId, eventData }) { const { proxy } = await this._getRuntime(); await proxy.call(this.onRequestHookEvent, { name, testId, hookId, eventData, }); } async setMock({ testId, hookId, ruleId, responseEventId, mock }) { if (mock.isPredicate) this._wrapMockPredicate({ mock, testId, hookId, ruleId }); await this.emit('setMock', [responseEventId, mock]); } async setConfigureResponseEventOptions({ eventId, opts }) { await this.emit('setConfigureResponseEventOptions', [eventId, opts]); } async setHeaderOnConfigureResponseEvent({ eventId, headerName, headerValue }) { await this.emit('setHeaderOnConfigureResponseEvent', [eventId, headerName, headerValue]); } async removeHeaderOnConfigureResponseEvent({ eventId, headerName }) { await this.emit('removeHeaderOnConfigureResponseEvent', [eventId, headerName]); } async executeRequestFilterRulePredicate({ testId, hookId, ruleId, requestInfo }) { const { proxy } = await this._getRuntime(); return await proxy.call(this.executeRequestFilterRulePredicate, { testId, hookId, ruleId, requestInfo }); } async executeMockPredicate({ testId, hookId, ruleId, requestInfo, res }) { const { proxy } = await this._getRuntime(); return await proxy.call(this.executeMockPredicate, { testId, hookId, ruleId, requestInfo, res }); } async getWarningMessages({ testRunId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.getWarningMessages, { testRunId }); } async addRequestEventListeners({ hookId, hookClassName, rules }) { await this.emit('addRequestEventListeners', { hookId, hookClassName, rules }); } async removeRequestEventListeners({ rules }) { await this.emit('removeRequestEventListeners', { rules }); } async initializeTestRunData({ testRunId, testId, browser, activeWindowId, messageBus }) { const { proxy } = await this._getRuntime(); return proxy.call(this.initializeTestRunData, { testRunId, testId, browser, activeWindowId, messageBus }); } async getAssertionActualValue({ testRunId, commandId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.getAssertionActualValue, { testRunId, commandId: commandId }); } async executeRoleInitFn({ testRunId, roleId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.executeRoleInitFn, { testRunId, roleId }); } async getCtx({ testRunId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.getCtx, { testRunId }); } async getFixtureCtx({ testRunId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.getFixtureCtx, { testRunId }); } async setCtx({ testRunId, value }) { const { proxy } = await this._getRuntime(); return proxy.call(this.setCtx, { testRunId, value }); } async setFixtureCtx({ testRunId, value }) { const { proxy } = await this._getRuntime(); return proxy.call(this.setFixtureCtx, { testRunId, value }); } onRoleAppeared() { throw new method_should_not_be_called_error_1.default(); } async updateRoleProperty({ roleId, name, value }) { const { proxy } = await this._getRuntime(); return proxy.call(this.updateRoleProperty, { roleId, name, value }); } async executeJsExpression({ expression, testRunId, options }) { const { proxy } = await this._getRuntime(); return proxy.call(this.executeJsExpression, { expression, testRunId, options }); } async executeAsyncJsExpression({ expression, testRunId, callsite }) { const { proxy } = await this._getRuntime(); return proxy.call(this.executeAsyncJsExpression, { expression, testRunId, callsite }); } async executeAssertionFn({ testRunId, commandId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.executeAssertionFn, { testRunId, commandId }); } async addUnexpectedError({ type, message }) { const ErrorTypeConstructor = this._getErrorTypeConstructor(type); (0, handle_errors_1.handleUnexpectedError)(ErrorTypeConstructor, message); } async checkWindow({ testRunId, commandId, url, title }) { const { proxy } = await this._getRuntime(); return proxy.call(this.checkWindow, { testRunId, commandId, url, title }); } async removeTestRunFromState({ testRunId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.removeTestRunFromState, { testRunId }); } async removeFixtureCtxsFromState({ fixtureIds }) { const { proxy } = await this._getRuntime(); return proxy.call(this.removeFixtureCtxsFromState, { fixtureIds }); } async removeUnitsFromState({ runnableConfigurationId }) { const { proxy } = await this._getRuntime(); return proxy.call(this.removeUnitsFromState, { runnableConfigurationId }); } } exports.default = CompilerHost; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy9jb21waWxlci9ob3N0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsZ0RBQXdCO0FBQ3hCLDZCQUFvQztBQUNwQyxzRkFBMEM7QUFFMUMsaURBQW9EO0FBQ3BELG1EQUE2QztBQUU3Qyw2QkFJYztBQUVkLG9FQUFrRjtBQUNsRix1RkFBOEQ7QUFDOUQsa0ZBQXVFO0FBQ3ZFLGdGQUF1RDtBQUV2RCw4Q0FBOEM7QUFDOUMsc0RBQXVEO0FBQ3ZELDBGQUFnRTtBQUNoRSx5RUFBd0Q7QUFDeEQsNEVBQW9EO0FBaUJwRCxxRUFBd0Y7QUFDeEYsbUhBQXNGO0FBNkJ0RixvREFBK0Y7QUFDL0YsNkRBQWtFO0FBQ2xFLDJFQUFpRTtBQUdqRSxNQUFNLFlBQVksR0FBUyxPQUFPLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDL0QsTUFBTSxrQkFBa0IsR0FBRyxJQUFBLG1CQUFhLEVBQUMsY0FBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztBQUV6RSxNQUFNLFVBQVUsR0FBUSxJQUFJLE1BQU0sQ0FBQyxLQUFLLHNDQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNyRSxNQUFNLGVBQWUsR0FBRyxJQUFJLE1BQU0sQ0FBQyxLQUFLLHNDQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBbUJuRixNQUFNLCtCQUErQixHQUFHLGdCQUFnQixDQUFDO0FBRXpELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxHQUFHLENBQW1CO0lBQ3BELENBQUMseUNBQThCLENBQUMsSUFBSSxFQUFFLHlDQUE4QixDQUFDO0lBQ3JFLENBQUMsaUNBQXNCLENBQUMsSUFBSSxFQUFFLGlDQUFzQixDQUFDO0NBQ3hELENBQUMsQ0FBQztBQU9ILE1BQXFC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QUFDO1FBRTNDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRU0sS0FBSyxDQUFDLHNCQUFzQixDQUFFLEVBQUUsU0FBUyxFQUFrQjtRQUM5RCxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFM0MsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVNLEtBQUssQ0FBQywwQkFBMEIsQ0FBRSxFQUFFLFVBQVUsRUFBOEI7UUFDL0UsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRTNDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsMEJBQTBCLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFFTSxLQUFLLENBQUMsb0JBQW9CLENBQUUsRUFBRSx1QkFBdUIsRUFBaUM7UUFDekYsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRTNDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsRUFBRSx1QkFBdUIsRUFBRSxDQUFDLENBQUM7SUFDOUUsQ0FBQztDQUNKO0FBM2NELCtCQTJjQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcGF0aFRvRmlsZVVSTCB9IGZyb20gJ3VybCc7XG5pbXBvcnQgY2RwIGZyb20gJ2Nocm9tZS1yZW1vdGUtaW50ZXJmYWNlJztcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IHNwYXduLCBDaGlsZFByb2Nlc3MgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IGdldEZyZWVQb3J0IH0gZnJvbSAnZW5kcG9pbnQtdXRpbHMnO1xuXG5pbXBvcnQge1xuICAgIEhPU1RfSU5QVVRfRkQsXG4gICAgSE9TVF9PVVRQVVRfRkQsXG4gICAgSE9TVF9TWU5DX0ZELFxufSBmcm9tICcuL2lvJztcblxuaW1wb3J0IHsgcmVzdG9yZSBhcyByZXN0b3JlVGVzdFN0cnVjdHVyZSB9IGZyb20gJy4uL3NlcmlhbGl6YXRpb24vdGVzdC1zdHJ1Y3R1cmUnO1xuaW1wb3J0IHByZXBhcmVPcHRpb25zIGZyb20gJy4uL3NlcmlhbGl6YXRpb24vcHJlcGFyZS1vcHRpb25zJztcbmltcG9ydCB7IGRlZmF1bHQgYXMgdGVzdFJ1blRyYWNrZXIgfSBmcm9tICcuLi8uLi9hcGkvdGVzdC1ydW4tdHJhY2tlcic7XG5pbXBvcnQgVGVzdENvbnRyb2xsZXIgZnJvbSAnLi4vLi4vYXBpL3Rlc3QtY29udHJvbGxlcic7XG5pbXBvcnQgVGVzdFJ1biBmcm9tICcuLi8uLi90ZXN0LXJ1bic7XG5pbXBvcnQgeyBJUENQcm94eSB9IGZyb20gJy4uL3V0aWxzL2lwYy9wcm94eSc7XG5pbXBvcnQgeyBIb3N0VHJhbnNwb3J0IH0gZnJvbSAnLi4vdXRpbHMvaXBjL3RyYW5zcG9ydCc7XG5pbXBvcnQgQXN5bmNFdmVudEVtaXR0ZXIgZnJvbSAnLi4vLi4vdXRpbHMvYXN5bmMtZXZlbnQtZW1pdHRlcic7XG5pbXBvcnQgVGVzdENhZmVFcnJvckxpc3QgZnJvbSAnLi4vLi4vZXJyb3JzL2Vycm9yLWxpc3QnO1xuaW1wb3J0IERFQlVHX0FDVElPTiBmcm9tICcuLi8uLi91dGlscy9kZWJ1Zy1hY3Rpb24nO1xuXG5pbXBvcnQge1xuICAgIENvbXBpbGVyUHJvdG9jb2wsXG4gICAgUnVuVGVzdEFyZ3VtZW50cyxcbiAgICBGdW5jdGlvblByb3BlcnRpZXMsXG59IGZyb20gJy4vcHJvdG9jb2wnO1xuXG5pbXBvcnQgeyBDb21waWxlckFyZ3VtZW50cyB9IGZyb20gJy4uLy4uL2NvbXBpbGVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IFRlc3QgZnJvbSAnLi4vLi4vYXBpL3N0cnVjdHVyZS90ZXN0JztcblxuaW1wb3J0IHtcbiAgICBSZXF1ZXN0SW5mbyxcbiAgICBSZXNwb25zZU1vY2ssXG4gICAgSW5jb21pbmdNZXNzYWdlTGlrZUluaXRPcHRpb25zLFxufSBmcm9tICd0ZXN0Y2FmZS1oYW1tZXJoZWFkJztcblxuaW1wb3J0IHsgRGVidWdDb21tYW5kLCBEaXNhYmxlRGVidWdDb21tYW5kIH0gZnJvbSAnLi4vLi4vdGVzdC1ydW4vY29tbWFuZHMvb2JzZXJ2YXRpb24nO1xuaW1wb3J0IE1ldGhvZFNob3VsZE5vdEJlQ2FsbGVkRXJyb3IgZnJvbSAnLi4vdXRpbHMvbWV0aG9kLXNob3VsZC1ub3QtYmUtY2FsbGVkLWVycm9yJztcblxuaW1wb3J0IHtcbiAgICBBZGRSZXF1ZXN0RXZlbnRMaXN0ZW5lcnNBcmd1bWVudHMsXG4gICAgRXhlY3V0ZUNvbW1hbmRBcmd1bWVudHMsXG4gICAgRXhlY3V0ZU1vY2tQcmVkaWNhdGUsXG4gICAgRXhlY3V0ZVJlcXVlc3RGaWx0ZXJSdWxlUHJlZGljYXRlQXJndW1lbnRzLFxuICAgIEV4ZWN1dGVSb2xlSW5pdEZuQXJndW1lbnRzLFxuICAgIEluaXRpYWxpemVUZXN0UnVuRGF0YUFyZ3VtZW50cyxcbiAgICBSZW1vdmVIZWFkZXJPbkNvbmZpZ3VyZVJlc3BvbnNlRXZlbnRBcmd1bWVudHMsXG4gICAgUmVtb3ZlUmVxdWVzdEV2ZW50TGlzdGVuZXJzQXJndW1lbnRzLFxuICAgIFJlcXVlc3RGaWx0ZXJSdWxlTG9jYXRvcixcbiAgICBSZXF1ZXN0SG9va0V2ZW50QXJndW1lbnRzLFxuICAgIFNldENvbmZpZ3VyZVJlc3BvbnNlRXZlbnRPcHRpb25zQXJndW1lbnRzLFxuICAgIFNldEN0eEFyZ3VtZW50cyxcbiAgICBTZXRNb2NrQXJndW1lbnRzLFxuICAgIFNldEhlYWRlck9uQ29uZmlndXJlUmVzcG9uc2VFdmVudEFyZ3VtZW50cyxcbiAgICBTZXRPcHRpb25zQXJndW1lbnRzLFxuICAgIFRlc3RSdW5Mb2NhdG9yLFxuICAgIFVwZGF0ZVJvbGVQcm9wZXJ0eUFyZ3VtZW50cyxcbiAgICBFeGVjdXRlSnNFeHByZXNzaW9uQXJndW1lbnRzLFxuICAgIEV4ZWN1dGVBc3luY0pzRXhwcmVzc2lvbkFyZ3VtZW50cyxcbiAgICBDb21tYW5kTG9jYXRvcixcbiAgICBBZGRVbmV4cGVjdGVkRXJyb3JBcmd1bWVudHMsXG4gICAgQ2hlY2tXaW5kb3dBcmd1bWVudCxcbiAgICBSZW1vdmVGaXh0dXJlQ3R4c0FyZ3VtZW50cyxcbiAgICBSZW1vdmVVbml0c0Zyb21TdGF0ZUFyZ3VtZW50cyxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzJztcblxuaW1wb3J0IHsgVW5jYXVnaHRFeGNlcHRpb25FcnJvciwgVW5oYW5kbGVkUHJvbWlzZVJlamVjdGlvbkVycm9yIH0gZnJvbSAnLi4vLi4vZXJyb3JzL3Rlc3QtcnVuJztcbmltcG9ydCB7IGhhbmRsZVVuZXhwZWN0ZWRFcnJvciB9IGZyb20gJy4uLy4uL3V0aWxzL2hhbmRsZS1lcnJvcnMnO1xuaW1wb3J0IHsgVjhfREVCVUdfRkxBR1MgfSBmcm9tICcuLi8uLi9jbGkvbm9kZS1hcmd1bWVudHMtZmlsdGVyJztcbmltcG9ydCB7IFdhcm5pbmdMb2dNZXNzYWdlIH0gZnJvbSAnLi4vLi4vbm90aWZpY2F0aW9ucy93YXJuaW5nLWxvZyc7XG5cbmNvbnN0IFNFUlZJQ0VfUEFUSCAgICAgICA9IHJlcXVpcmUucmVzb2x2ZSgnLi9zZXJ2aWNlLWxvYWRlcicpO1xuY29uc3QgSU5URVJOQUxfRklMRVNfVVJMID0gcGF0aFRvRmlsZVVSTChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vJykpO1xuXG5jb25zdCBJTlNQRUNUX1JFICAgICAgPSBuZXcgUmVnRXhwKGBeKCR7VjhfREVCVUdfRkxBR1Muam9pbignfCcpfSlgKTtcbmNvbnN0IElOU1BFQ1RfUE9SVF9SRSA9IG5ldyBSZWdFeHAoYF4oJHtWOF9ERUJVR19GTEFHUy5qb2luKCd8Jyl9KT0oLis6KT8oXFxcXGQrKSRgKTtcblxuaW50ZXJmYWNlIFJ1bnRpbWVSZXNvdXJjZXMge1xuICAgIHNlcnZpY2U6IENoaWxkUHJvY2VzcztcbiAgICBwcm94eTogSVBDUHJveHk7XG59XG5cbmludGVyZmFjZSBUZXN0RnVuY3Rpb24ge1xuICAgICh0ZXN0UnVuOiBUZXN0UnVuKTogUHJvbWlzZTx1bmtub3duPjtcbn1cblxuaW50ZXJmYWNlIFJlcXVlc3RGaWx0ZXJSdWxlUHJlZGljYXRlIHtcbiAgICAocmVxdWVzdEluZm86IFJlcXVlc3RJbmZvKTogUHJvbWlzZTxib29sZWFuPjtcbn1cblxuaW50ZXJmYWNlIFdyYXBNb2NrUHJlZGljYXRlQXJndW1lbnRzIGV4dGVuZHMgUmVxdWVzdEZpbHRlclJ1bGVMb2NhdG9yIHtcbiAgICBtb2NrOiBSZXNwb25zZU1vY2s7XG59XG5cbmNvbnN0IElOSVRJQUxfREVCVUdHRVJfQlJFQUtfT05fU1RBUlQgPSAnQnJlYWsgb24gc3RhcnQnO1xuXG5jb25zdCBlcnJvclR5cGVDb25zdHJ1Y3RvcnMgPSBuZXcgTWFwPHN0cmluZywgRnVuY3Rpb24+KFtcbiAgICBbVW5oYW5kbGVkUHJvbWlzZVJlamVjdGlvbkVycm9yLm5hbWUsIFVuaGFuZGxlZFByb21pc2VSZWplY3Rpb25FcnJvcl0sXG4gICAgW1VuY2F1Z2h0RXhjZXB0aW9uRXJyb3IubmFtZSwgVW5jYXVnaHRFeGNlcHRpb25FcnJvcl0sXG5dKTtcblxuaW50ZXJmYWNlIENvbXBpbGVySG9zdEluaXRPcHRpb25zIHtcbiAgICBkZXZlbG9wbWVudE1vZGU6IGJvb2xlYW47XG4gICAgdjhGbGFnczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENvbXBpbGVySG9zdCBleHRlbmRzIEFzeW5jRXZlbnRFbWl0dGVyIGltcGxlbWVudHMgQ29tcGlsZXJQcm90b2NvbCB7XG4gICAgcHJpdmF0ZSBydW50aW1lOiBQcm9taXNlPFJ1bnRpbWVSZXNvdXJjZXMgfCB1bmRlZmluZWQ+O1xuICAgIHByaXZhdGUgY2RwOiBjZHAuUHJvdG9jb2xBcGkgJiBFdmVudEVtaXR0ZXIgfCB1bmRlZmluZWQ7XG4gICAgcHJpdmF0ZSByZWFkb25seSBkZXZlbG9wbWVudE1vZGU6IGJvb2xlYW47XG4gICAgcHJpdmF0ZSByZWFkb25seSB2OEZsYWdzOiBzdHJpbmdbXTtcbiAgICBwdWJsaWMgaW5pdGlhbGl6ZWQ6IGJvb2xlYW47XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKHsgZGV2ZWxvcG1lbnRNb2RlLCB2OEZsYWdzIH06IENvbXBpbGVySG9zdEluaXRPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5ydW50aW1lICAgICAgICAgPSBQcm9taXNlLnJlc29sdmUodm9pZCAwKTtcbiAgICAgICAgdGhpcy5kZXZlbG9wbWVudE1vZGUgPSBkZXZlbG9wbWVudE1vZGU7XG4gICAgICAgIHRoaXMudjhGbGFncyAgICAgICAgID0gdjhGbGFncztcbiAgICAgICAgdGhpcy5pbml0aWFsaXplZCAgICAgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9zZXR1cFJvdXRlcyAocHJveHk6IElQQ1Byb3h5KTogdm9pZCB7XG4gICAgICAgIHByb3h5LnJlZ2lzdGVyKFtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZUNvbW1hbmQsXG4gICAgICAgICAgICB0aGlzLnJlYWR5LFxuICAgICAgICAgICAgdGhpcy5vblJlcXVlc3RIb29rRXZlbnQsXG4gICAgICAgICAgICB0aGlzLnNldE1vY2ssXG4gICAgICAgICAgICB0aGlzLnNldENvbmZpZ3VyZVJlc3BvbnNlRXZlbnRPcHRpb25zLFxuICAgICAgICAgICAgdGhpcy5zZXRIZWFkZXJPbkNvbmZpZ3VyZVJlc3BvbnNlRXZlbnQsXG4gICAgICAgICAgICB0aGlzLnJlbW92ZUhlYWRlck9uQ29uZmlndXJlUmVzcG9uc2VFdmVudCxcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZVJlcXVlc3RGaWx0ZXJSdWxlUHJlZGljYXRlLFxuICAgICAgICAgICAgdGhpcy5leGVjdXRlTW9ja1ByZWRpY2F0ZSxcbiAgICAgICAgICAgIHRoaXMuZ2V0V2FybmluZ01lc3NhZ2VzLFxuICAgICAgICAgICAgdGhpcy5hZGRSZXF1ZXN0RXZlbnRMaXN0ZW5lcnMsXG4gICAgICAgICAgICB0aGlzLnJlbW92ZVJlcXVlc3RFdmVudExpc3RlbmVycyxcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZVRlc3RSdW5EYXRhLFxuICAgICAgICAgICAgdGhpcy5nZXRBc3NlcnRpb25BY3R1YWxWYWx1ZSxcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZVJvbGVJbml0Rm4sXG4gICAgICAgICAgICB0aGlzLmdldEN0eCxcbiAgICAgICAgICAgIHRoaXMuZ2V0Rml4dHVyZUN0eCxcbiAgICAgICAgICAgIHRoaXMuc2V0Q3R4LFxuICAgICAgICAgICAgdGhpcy5zZXRGaXh0dXJlQ3R4LFxuICAgICAgICAgICAgdGhpcy51cGRhdGVSb2xlUHJvcGVydHksXG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVKc0V4cHJlc3Npb24sXG4gICAgICAgICAgICB0aGlzLmV4ZWN1dGVBc3luY0pzRXhwcmVzc2lvbixcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0ZUFzc2VydGlvbkZuLFxuICAgICAgICAgICAgdGhpcy5hZGRVbmV4cGVjdGVkRXJyb3IsXG4gICAgICAgICAgICB0aGlzLmNoZWNrV2luZG93LFxuICAgICAgICAgICAgdGhpcy5yZW1vdmVUZXN0UnVuRnJvbVN0YXRlLFxuICAgICAgICAgICAgdGhpcy5yZW1vdmVGaXh0dXJlQ3R4c0Zyb21TdGF0ZSxcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlVW5pdHNGcm9tU3RhdGUsXG4gICAgICAgIF0sIHRoaXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3NldHVwRGVidWdnZXJIYW5kbGVycyAoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5jZHApXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGVzdFJ1blRyYWNrZXIub24oREVCVUdfQUNUSU9OLnJlc3VtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNkcClcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIGNvbnN0IGRpc2FibGVEZWJ1Z01ldGhvZE5hbWUgPSBUZXN0Q29udHJvbGxlci5kaXNhYmxlRGVidWdGb3JOb25EZWJ1Z0NvbW1hbmRzLm5hbWU7XG5cbiAgICAgICAgICAgIC8vIE5PVEU6IGRpc2FibGUgYGRlYnVnZ2VyYCBmb3Igbm9uLWRlYnVnIGNvbW1hbmRzIGlmIHRoZSBgUmVzdW1lYCBidXR0b24gaXMgY2xpY2tlZFxuICAgICAgICAgICAgLy8gdGhlIGBpbmNsdWRlQ29tbWFuZExpbmVBUElgIG9wdGlvbiBhbGxvd3MgdG8gdXNlIHRoZSBgcmVxdWlyZWAgZnVuY3RvaW9uIGluIHRoZSBleHByZXNzaW9uXG4gICAgICAgICAgICAvLyBUT0RPOiBkZWJ1Z2dpbmc6IHJlZmFjdG9yIHRvIHVzZSBhYnNvbHV0ZSBwYXRoc1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jZHAuUnVudGltZS5ldmFsdWF0ZSh7XG4gICAgICAgICAgICAgICAgZXhwcmVzc2lvbjogICAgICAgICAgICBgcmVxdWlyZS5tYWluLnJlcXVpcmUoJy4uLy4uL2FwaS90ZXN0LWNvbnRyb2xsZXInKS4ke2Rpc2FibGVEZWJ1Z01ldGhvZE5hbWV9KClgLFxuICAgICAgICAgICAgICAgIGluY2x1ZGVDb21tYW5kTGluZUFQSTogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNkcC5EZWJ1Z2dlci5yZXN1bWUoeyB0ZXJtaW5hdGVPblJlc3VtZTogZmFsc2UgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRlc3RSdW5UcmFja2VyLm9uKERFQlVHX0FDVElPTi5zdGVwLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY2RwKVxuICAgICAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAgICAgY29uc3QgZW5hYmxlRGVidWdNZXRob2ROYW1lID0gVGVzdENvbnRyb2xsZXIuZW5hYmxlRGVidWdGb3JOb25EZWJ1Z0NvbW1hbmRzLm5hbWU7XG5cbiAgICAgICAgICAgIC8vIE5PVEU6IGVuYWJsZSBgZGVidWdnZXJgIGZvciBub24tZGVidWcgY29tbWFuZHMgaW4gdGhlIGBOZXh0IEFjdGlvbmAgYnV0dG9uIGlzIGNsaWNrZWRcbiAgICAgICAgICAgIC8vIHRoZSBgaW5jbHVkZUNvbW1hbmRMaW5lQVBJYCBvcHRpb24gYWxsb3dzIHRvIHVzZSB0aGUgYHJlcXVpcmVgIGZ1bmN0b2lvbiBpbiB0aGUgZXhwcmVzc2lvblxuICAgICAgICAgICAgLy8gVE9ETzogZGVidWdnaW5nOiByZWZhY3RvciB0byB1c2UgYWJzb2x1dGUgcGF0aHNcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2RwLlJ1bnRpbWUuZXZhbHVhdGUoe1xuICAgICAgICAgICAgICAgIGV4cHJlc3Npb246ICAgICAgICAgICAgYHJlcXVpcmUubWFpbi5yZXF1aXJlKCcuLi8uLi9hcGkvdGVzdC1jb250cm9sbGVyJykuJHtlbmFibGVEZWJ1Z01ldGhvZE5hbWV9KClgLFxuICAgICAgICAgICAgICAgIGluY2x1ZGVDb21tYW5kTGluZUFQSTogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNkcC5EZWJ1Z2dlci5yZXN1bWUoeyB0ZXJtaW5hdGVPblJlc3VtZTogZmFsc2UgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIE5PVEU6IG5lZWQgdG8gc3RlcCBvdXQgZnJvbSB0aGUgc291cmNlIGNvZGUgdW50aWwgYnJlYWtwb2ludCBpcyBzZXQgaW4gdGhlIGNvZGUgb2YgdGVzdFxuICAgICAgICAvLyBmb3JjZSBEZWJ1Z0NvbW1hbmQgaWYgYnJlYWtwb2ludCBzdG9wcGVkIGluIHRoZSB0ZXN0IGNvZGVcbiAgICAgICAgLy8gVE9ETzogZGVidWdnaW5nOiByZWZhY3RvciB0byB0aGlzLmNkcC5EZWJ1Z2dlci5vbigncGF1c2VkJykgYWZ0ZXIgdXBkYXRpbmcgdG8gY2hyb21lLXJlbW90ZS1pbnRlcmZhY2VAMC4zMC4wXG4gICAgICAgIHRoaXMuY2RwLm9uKCdEZWJ1Z2dlci5wYXVzZWQnLCAoYXJnczogYW55KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGNhbGxGcmFtZXMgfSA9IGFyZ3M7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmNkcCkge1xuICAgICAgICAgICAgICAgIGlmIChhcmdzLnJlYXNvbiA9PT0gSU5JVElBTF9ERUJVR0dFUl9CUkVBS19PTl9TVEFSVClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2RwLkRlYnVnZ2VyLnJlc3VtZSh7IHRlcm1pbmF0ZU9uUmVzdW1lOiBmYWxzZSB9KTtcblxuICAgICAgICAgICAgICAgIGlmIChjYWxsRnJhbWVzWzBdLnVybC5pbmNsdWRlcyhJTlRFUk5BTF9GSUxFU19VUkwpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jZHAuRGVidWdnZXIuc3RlcE91dCgpO1xuXG4gICAgICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyh0ZXN0UnVuVHJhY2tlci5hY3RpdmVUZXN0UnVucykuZm9yRWFjaCh0ZXN0UnVuID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0ZXN0UnVuLmRlYnVnZ2luZylcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlc3RSdW4uZXhlY3V0ZUNvbW1hbmQobmV3IERlYnVnQ29tbWFuZCgpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBOT1RFOiBuZWVkIHRvIGhpZGUgU3RhdHVzIEJhciBpZiBkZWJ1Z2dlciBpcyByZXN1bWVkXG4gICAgICAgIC8vIFRPRE86IGRlYnVnZ2luZzogcmVmYWN0b3IgdG8gdGhpcy5jZHAuRGVidWdnZXIub24oJ3Jlc3VtZWQnKSBhZnRlciB1cGRhdGluZyB0byBjaHJvbWUtcmVtb3RlLWludGVyZmFjZUAwLjMwLjBcbiAgICAgICAgdGhpcy5jZHAub24oJ0RlYnVnZ2VyLnJlc3VtZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBPYmplY3QudmFsdWVzKHRlc3RSdW5UcmFja2VyLmFjdGl2ZVRlc3RSdW5zKS5mb3JFYWNoKHRlc3RSdW4gPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0ZXN0UnVuLmRlYnVnZ2luZylcbiAgICAgICAgICAgICAgICAgICAgdGVzdFJ1bi5leGVjdXRlQ29tbWFuZChuZXcgRGlzYWJsZURlYnVnQ29tbWFuZCgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHBhcnNlRGVidWdQb3J0ICgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgaWYgKHRoaXMudjhGbGFncykge1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnY4RmxhZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXRjaCA9IHRoaXMudjhGbGFnc1tpXS5tYXRjaChJTlNQRUNUX1BPUlRfUkUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hbM107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9nZXRTZXJ2aWNlUHJvY2Vzc0FyZ3MgKHBvcnQ6IHN0cmluZyk6IHN0cmluZyBbXSB7XG4gICAgICAgIGxldCBhcmdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGlmICh0aGlzLnY4RmxhZ3MpXG4gICAgICAgICAgICBhcmdzID0gdGhpcy52OEZsYWdzLmZpbHRlcihmbGFnID0+ICFJTlNQRUNUX1JFLnRlc3QoZmxhZykpO1xuXG4gICAgICAgIC8vIFRPRE86IGRlYnVnZ2luZzogcmVmYWN0b3IgdG8gYSBzZXBhcmF0ZSBkZWJ1ZyBpbmZvIHBhcnNpbmcgdW5pdFxuICAgICAgICBjb25zdCBpbnNwZWN0QnJrRmxhZyA9IGAtLWluc3BlY3QtYnJrPTEyNy4wLjAuMTokeyBwb3J0IH1gO1xuXG4gICAgICAgIGFyZ3MucHVzaChpbnNwZWN0QnJrRmxhZywgU0VSVklDRV9QQVRIKTtcblxuICAgICAgICByZXR1cm4gYXJncztcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9pbml0IChydW50aW1lOiBQcm9taXNlPFJ1bnRpbWVSZXNvdXJjZXMgfCB1bmRlZmluZWQ+KTogUHJvbWlzZTxSdW50aW1lUmVzb3VyY2VzIHwgdW5kZWZpbmVkPiB7XG4gICAgICAgIGNvbnN0IHJlc29sdmVkUnVudGltZSA9IGF3YWl0IHJ1bnRpbWU7XG5cbiAgICAgICAgaWYgKHJlc29sdmVkUnVudGltZSlcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlZFJ1bnRpbWU7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBvcnQgICAgPSB0aGlzLnBhcnNlRGVidWdQb3J0KCkgfHwgYXdhaXQgZ2V0RnJlZVBvcnQoKTtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3MgICAgPSB0aGlzLl9nZXRTZXJ2aWNlUHJvY2Vzc0FyZ3MocG9ydC50b1N0cmluZygpKTtcbiAgICAgICAgICAgIGNvbnN0IHNlcnZpY2UgPSBzcGF3bihwcm9jZXNzLmFyZ3YwLCBhcmdzLCB7IHN0ZGlvOiBbMCwgMSwgMiwgJ3BpcGUnLCAncGlwZScsICdwaXBlJ10gfSk7XG5cbiAgICAgICAgICAgIC8vIE5PVEU6IG5lZWQgdG8gd2FpdCwgb3RoZXJ3aXNlIHRoZSBlcnJvciB3aWxsIGJlIGF0IGBhd2FpdCBjZHAoLi4uKWBcbiAgICAgICAgICAgIC8vIFRPRE86IGRlYnVnZ2luZzogcmVmYWN0b3IgdG8gdXNlIGRlbGF5IGFuZCBtdWx0aXBsZSB0cmllc1xuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UociA9PiBzZXRUaW1lb3V0KHIsIDIwMDApKTtcblxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5jZHAgPSBhd2FpdCBjZHAoeyBwb3J0IH0pO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuY2RwKVxuICAgICAgICAgICAgICAgIHJldHVybiB2b2lkIDA7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5kZXZlbG9wbWVudE1vZGUpXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0dXBEZWJ1Z2dlckhhbmRsZXJzKCk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2RwLkRlYnVnZ2VyLmVuYWJsZSh7fSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNkcC5SdW50aW1lLmVuYWJsZSgpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jZHAuUnVudGltZS5ydW5JZldhaXRpbmdGb3JEZWJ1Z2dlcigpO1xuXG4gICAgICAgICAgICAvLyBIQUNLOiBOb2RlLmpzIGRlZmluaXRpb24gYXJlIG5vdCBjb3JyZWN0IHdoZW4gYWRkaXRpb25hbCBJL08gY2hhbm5lbHMgYXJlIHNwXG4gICAgICAgICAgICBjb25zdCBzdGRpbyA9IHNlcnZpY2Uuc3RkaW8gYXMgYW55O1xuICAgICAgICAgICAgY29uc3QgcHJveHkgPSBuZXcgSVBDUHJveHkobmV3IEhvc3RUcmFuc3BvcnQoc3RkaW9bSE9TVF9JTlBVVF9GRF0sIHN0ZGlvW0hPU1RfT1VUUFVUX0ZEXSwgc3RkaW9bSE9TVF9TWU5DX0ZEXSkpO1xuXG4gICAgICAgICAgICB0aGlzLl9zZXR1cFJvdXRlcyhwcm94eSk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMub25jZSgncmVhZHknKTtcblxuICAgICAgICAgICAgcmV0dXJuIHsgcHJveHksIHNlcnZpY2UgfTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIHZvaWQgMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2dldFJ1bnRpbWUgKCk6IFByb21pc2U8UnVudGltZVJlc291cmNlcz4ge1xuICAgICAgICBjb25zdCBydW50aW1lID0gYXdhaXQgdGhpcy5ydW50aW1lO1xuXG4gICAgICAgIGlmICghcnVudGltZSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUnVudGltZSBpcyBub3QgYXZhaWxhYmxlLicpO1xuXG4gICAgICAgIHJldHVybiBydW50aW1lO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2dldFRhcmdldFRlc3RSdW4gKGlkOiBzdHJpbmcpOiBUZXN0UnVuIHtcbiAgICAgICAgcmV0dXJuIHRlc3RSdW5UcmFja2VyLmFjdGl2ZVRlc3RSdW5zW2lkXSBhcyB1bmtub3duIGFzIFRlc3RSdW47XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGluaXQgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLnJ1bnRpbWUgPSB0aGlzLl9pbml0KHRoaXMucnVudGltZSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5ydW50aW1lO1xuXG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzdG9wICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHsgc2VydmljZSwgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICBzZXJ2aWNlLmtpbGwoKTtcbiAgICAgICAgcHJveHkuc3RvcCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3dyYXBUZXN0RnVuY3Rpb24gKGlkOiBzdHJpbmcsIGZ1bmN0aW9uTmFtZTogRnVuY3Rpb25Qcm9wZXJ0aWVzKTogVGVzdEZ1bmN0aW9uIHtcbiAgICAgICAgcmV0dXJuIGFzeW5jIHRlc3RSdW4gPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5UZXN0Rm4oeyBpZCwgZnVuY3Rpb25OYW1lLCB0ZXN0UnVuSWQ6IHRlc3RSdW4uaWQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyTGlzdCA9IG5ldyBUZXN0Q2FmZUVycm9yTGlzdCgpO1xuXG4gICAgICAgICAgICAgICAgZXJyTGlzdC5hZGRFcnJvcihlcnIpO1xuXG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyTGlzdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF93cmFwUmVxdWVzdEZpbHRlclJ1bGVQcmVkaWNhdGUgKHsgdGVzdElkLCBob29rSWQsIHJ1bGVJZCB9OiBSZXF1ZXN0RmlsdGVyUnVsZUxvY2F0b3IpOiBSZXF1ZXN0RmlsdGVyUnVsZVByZWRpY2F0ZSB7XG4gICAgICAgIHJldHVybiBhc3luYyAocmVxdWVzdEluZm86IFJlcXVlc3RJbmZvKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlUmVxdWVzdEZpbHRlclJ1bGVQcmVkaWNhdGUoeyB0ZXN0SWQsIGhvb2tJZCwgcnVsZUlkLCByZXF1ZXN0SW5mbyB9KTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF93cmFwTW9ja1ByZWRpY2F0ZSAoeyBtb2NrLCB0ZXN0SWQsIGhvb2tJZCwgcnVsZUlkIH06IFdyYXBNb2NrUHJlZGljYXRlQXJndW1lbnRzKTogdm9pZCB7XG4gICAgICAgIG1vY2suYm9keSA9IGFzeW5jIChyZXF1ZXN0SW5mbzogUmVxdWVzdEluZm8sIHJlczogSW5jb21pbmdNZXNzYWdlTGlrZUluaXRPcHRpb25zKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5leGVjdXRlTW9ja1ByZWRpY2F0ZSh7IHRlc3RJZCwgaG9va0lkLCBydWxlSWQsIHJlcXVlc3RJbmZvLCByZXMgfSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0RXJyb3JUeXBlQ29uc3RydWN0b3IgKHR5cGU6IHN0cmluZyk6IEZ1bmN0aW9uIHtcbiAgICAgICAgcmV0dXJuIGVycm9yVHlwZUNvbnN0cnVjdG9ycy5nZXQodHlwZSkgYXMgRnVuY3Rpb247XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlYWR5ICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5lbWl0KCdyZWFkeScpO1xuICAgIH1cblxuICAgIHB1YmxpYyBleGVjdXRlQ29tbWFuZFN5bmMgKCk6IG5ldmVyIHtcbiAgICAgICAgdGhyb3cgbmV3IE1ldGhvZFNob3VsZE5vdEJlQ2FsbGVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZXhlY3V0ZUNvbW1hbmQgKHsgY29tbWFuZCwgaWQsIGNhbGxzaXRlIH06IEV4ZWN1dGVDb21tYW5kQXJndW1lbnRzKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIHJldHVybiB0aGlzXG4gICAgICAgICAgICAuX2dldFRhcmdldFRlc3RSdW4oaWQpXG4gICAgICAgICAgICAuZXhlY3V0ZUNvbW1hbmQoY29tbWFuZCwgY2FsbHNpdGUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRUZXN0cyAoeyBzb3VyY2VMaXN0LCBjb21waWxlck9wdGlvbnMsIHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkIH06IENvbXBpbGVyQXJndW1lbnRzLCBiYXNlVXJsPzogc3RyaW5nKTogUHJvbWlzZTxUZXN0W10+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIGNvbnN0IHVuaXRzID0gYXdhaXQgcHJveHkuY2FsbCh0aGlzLmdldFRlc3RzLCB7IHNvdXJjZUxpc3QsIGNvbXBpbGVyT3B0aW9ucywgcnVubmFibGVDb25maWd1cmF0aW9uSWQgfSwgYmFzZVVybCk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3RvcmVUZXN0U3RydWN0dXJlKFxuICAgICAgICAgICAgdW5pdHMsXG4gICAgICAgICAgICAoLi4uYXJncykgPT4gdGhpcy5fd3JhcFRlc3RGdW5jdGlvbiguLi5hcmdzKSxcbiAgICAgICAgICAgIChydWxlTG9jYXRvcjogUmVxdWVzdEZpbHRlclJ1bGVMb2NhdG9yKSA9PiB0aGlzLl93cmFwUmVxdWVzdEZpbHRlclJ1bGVQcmVkaWNhdGUocnVsZUxvY2F0b3IpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJ1blRlc3RGbiAoeyBpZCwgZnVuY3Rpb25OYW1lLCB0ZXN0UnVuSWQgfTogUnVuVGVzdEFyZ3VtZW50cyk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IHByb3h5LmNhbGwodGhpcy5ydW5UZXN0Rm4sIHsgaWQsIGZ1bmN0aW9uTmFtZSwgdGVzdFJ1bklkIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBjbGVhblVwICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIGF3YWl0IHByb3h5LmNhbGwodGhpcy5jbGVhblVwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2V0VXNlclZhcmlhYmxlcyAodXNlclZhcmlhYmxlczogVXNlclZhcmlhYmxlcyB8IG51bGwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIGF3YWl0IHByb3h5LmNhbGwodGhpcy5zZXRVc2VyVmFyaWFibGVzLCB1c2VyVmFyaWFibGVzKTtcbiAgICB9XG5cblxuICAgIHB1YmxpYyBhc3luYyBzZXRPcHRpb25zICh7IHZhbHVlIH06IFNldE9wdGlvbnNBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIGNvbnN0IHByZXBhcmVkT3B0aW9ucyA9IHByZXBhcmVPcHRpb25zKHZhbHVlKTtcblxuICAgICAgICBhd2FpdCBwcm94eS5jYWxsKHRoaXMuc2V0T3B0aW9ucywgeyB2YWx1ZTogcHJlcGFyZWRPcHRpb25zIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBvblJlcXVlc3RIb29rRXZlbnQgKHsgbmFtZSwgdGVzdElkLCBob29rSWQsIGV2ZW50RGF0YSB9OiBSZXF1ZXN0SG9va0V2ZW50QXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICBhd2FpdCBwcm94eS5jYWxsKHRoaXMub25SZXF1ZXN0SG9va0V2ZW50LCB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgdGVzdElkLFxuICAgICAgICAgICAgaG9va0lkLFxuICAgICAgICAgICAgZXZlbnREYXRhLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2V0TW9jayAoeyB0ZXN0SWQsIGhvb2tJZCwgcnVsZUlkLCByZXNwb25zZUV2ZW50SWQsIG1vY2sgfTogU2V0TW9ja0FyZ3VtZW50cyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAobW9jay5pc1ByZWRpY2F0ZSlcbiAgICAgICAgICAgIHRoaXMuX3dyYXBNb2NrUHJlZGljYXRlKHsgbW9jaywgdGVzdElkLCBob29rSWQsIHJ1bGVJZCB9KTtcblxuICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3NldE1vY2snLCBbcmVzcG9uc2VFdmVudElkLCBtb2NrXSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldENvbmZpZ3VyZVJlc3BvbnNlRXZlbnRPcHRpb25zICh7IGV2ZW50SWQsIG9wdHMgfTogU2V0Q29uZmlndXJlUmVzcG9uc2VFdmVudE9wdGlvbnNBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCdzZXRDb25maWd1cmVSZXNwb25zZUV2ZW50T3B0aW9ucycsIFtldmVudElkLCBvcHRzXSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldEhlYWRlck9uQ29uZmlndXJlUmVzcG9uc2VFdmVudCAoeyBldmVudElkLCBoZWFkZXJOYW1lLCBoZWFkZXJWYWx1ZSB9OiBTZXRIZWFkZXJPbkNvbmZpZ3VyZVJlc3BvbnNlRXZlbnRBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCdzZXRIZWFkZXJPbkNvbmZpZ3VyZVJlc3BvbnNlRXZlbnQnLCBbZXZlbnRJZCwgaGVhZGVyTmFtZSwgaGVhZGVyVmFsdWVdKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcmVtb3ZlSGVhZGVyT25Db25maWd1cmVSZXNwb25zZUV2ZW50ICh7IGV2ZW50SWQsIGhlYWRlck5hbWUgfTogUmVtb3ZlSGVhZGVyT25Db25maWd1cmVSZXNwb25zZUV2ZW50QXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMuZW1pdCgncmVtb3ZlSGVhZGVyT25Db25maWd1cmVSZXNwb25zZUV2ZW50JywgW2V2ZW50SWQsIGhlYWRlck5hbWVdKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZXhlY3V0ZVJlcXVlc3RGaWx0ZXJSdWxlUHJlZGljYXRlICh7IHRlc3RJZCwgaG9va0lkLCBydWxlSWQsIHJlcXVlc3RJbmZvIH06IEV4ZWN1dGVSZXF1ZXN0RmlsdGVyUnVsZVByZWRpY2F0ZUFyZ3VtZW50cyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IHByb3h5LmNhbGwodGhpcy5leGVjdXRlUmVxdWVzdEZpbHRlclJ1bGVQcmVkaWNhdGUsIHsgdGVzdElkLCBob29rSWQsIHJ1bGVJZCwgcmVxdWVzdEluZm8gfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGV4ZWN1dGVNb2NrUHJlZGljYXRlICh7IHRlc3RJZCwgaG9va0lkLCBydWxlSWQsIHJlcXVlc3RJbmZvLCByZXMgfTogRXhlY3V0ZU1vY2tQcmVkaWNhdGUpOiBQcm9taXNlPEluY29taW5nTWVzc2FnZUxpa2VJbml0T3B0aW9ucz4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IHByb3h5LmNhbGwodGhpcy5leGVjdXRlTW9ja1ByZWRpY2F0ZSwgeyB0ZXN0SWQsIGhvb2tJZCwgcnVsZUlkLCByZXF1ZXN0SW5mbywgcmVzIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRXYXJuaW5nTWVzc2FnZXMgKHsgdGVzdFJ1bklkIH06IFRlc3RSdW5Mb2NhdG9yKTogUHJvbWlzZTxXYXJuaW5nTG9nTWVzc2FnZVtdPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLmdldFdhcm5pbmdNZXNzYWdlcywgeyB0ZXN0UnVuSWQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGFkZFJlcXVlc3RFdmVudExpc3RlbmVycyAoIHsgaG9va0lkLCBob29rQ2xhc3NOYW1lLCBydWxlcyB9OiBBZGRSZXF1ZXN0RXZlbnRMaXN0ZW5lcnNBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCdhZGRSZXF1ZXN0RXZlbnRMaXN0ZW5lcnMnLCB7IGhvb2tJZCwgaG9va0NsYXNzTmFtZSwgcnVsZXMgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlbW92ZVJlcXVlc3RFdmVudExpc3RlbmVycyAoeyBydWxlcyB9OiBSZW1vdmVSZXF1ZXN0RXZlbnRMaXN0ZW5lcnNBcmd1bWVudHMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCdyZW1vdmVSZXF1ZXN0RXZlbnRMaXN0ZW5lcnMnLCB7IHJ1bGVzIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBpbml0aWFsaXplVGVzdFJ1bkRhdGEgKHsgdGVzdFJ1bklkLCB0ZXN0SWQsIGJyb3dzZXIsIGFjdGl2ZVdpbmRvd0lkLCBtZXNzYWdlQnVzIH06IEluaXRpYWxpemVUZXN0UnVuRGF0YUFyZ3VtZW50cyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5pbml0aWFsaXplVGVzdFJ1bkRhdGEsIHsgdGVzdFJ1bklkLCB0ZXN0SWQsIGJyb3dzZXIsIGFjdGl2ZVdpbmRvd0lkLCBtZXNzYWdlQnVzIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRBc3NlcnRpb25BY3R1YWxWYWx1ZSAoeyB0ZXN0UnVuSWQsIGNvbW1hbmRJZCB9OiBDb21tYW5kTG9jYXRvcik6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5nZXRBc3NlcnRpb25BY3R1YWxWYWx1ZSwgeyB0ZXN0UnVuSWQsIGNvbW1hbmRJZDogY29tbWFuZElkIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBleGVjdXRlUm9sZUluaXRGbiAoeyB0ZXN0UnVuSWQsIHJvbGVJZCB9OiBFeGVjdXRlUm9sZUluaXRGbkFyZ3VtZW50cyk6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5leGVjdXRlUm9sZUluaXRGbiwgeyB0ZXN0UnVuSWQsIHJvbGVJZCB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0Q3R4ICh7IHRlc3RSdW5JZCB9OiBUZXN0UnVuTG9jYXRvcik6IFByb21pc2U8b2JqZWN0PiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLmdldEN0eCwgeyB0ZXN0UnVuSWQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGdldEZpeHR1cmVDdHggKHsgdGVzdFJ1bklkIH06IFRlc3RSdW5Mb2NhdG9yKTogUHJvbWlzZTxvYmplY3Q+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIHJldHVybiBwcm94eS5jYWxsKHRoaXMuZ2V0Rml4dHVyZUN0eCwgeyB0ZXN0UnVuSWQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHNldEN0eCAoeyB0ZXN0UnVuSWQsIHZhbHVlIH06IFNldEN0eEFyZ3VtZW50cyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5zZXRDdHgsIHsgdGVzdFJ1bklkLCB2YWx1ZSB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2V0Rml4dHVyZUN0eCAoeyB0ZXN0UnVuSWQsIHZhbHVlIH06IFNldEN0eEFyZ3VtZW50cyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5zZXRGaXh0dXJlQ3R4LCB7IHRlc3RSdW5JZCwgdmFsdWUgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uUm9sZUFwcGVhcmVkICgpOiB2b2lkIHtcbiAgICAgICAgdGhyb3cgbmV3IE1ldGhvZFNob3VsZE5vdEJlQ2FsbGVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlUm9sZVByb3BlcnR5ICh7IHJvbGVJZCwgbmFtZSwgdmFsdWUgfTogVXBkYXRlUm9sZVByb3BlcnR5QXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLnVwZGF0ZVJvbGVQcm9wZXJ0eSwgeyByb2xlSWQsIG5hbWUsIHZhbHVlIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBleGVjdXRlSnNFeHByZXNzaW9uICh7IGV4cHJlc3Npb24sIHRlc3RSdW5JZCwgb3B0aW9ucyB9OiBFeGVjdXRlSnNFeHByZXNzaW9uQXJndW1lbnRzKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLmV4ZWN1dGVKc0V4cHJlc3Npb24sIHsgZXhwcmVzc2lvbiwgdGVzdFJ1bklkLCBvcHRpb25zIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBleGVjdXRlQXN5bmNKc0V4cHJlc3Npb24gKHsgZXhwcmVzc2lvbiwgdGVzdFJ1bklkLCBjYWxsc2l0ZSB9OiBFeGVjdXRlQXN5bmNKc0V4cHJlc3Npb25Bcmd1bWVudHMpOiBQcm9taXNlPHVua25vd24+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIHJldHVybiBwcm94eS5jYWxsKHRoaXMuZXhlY3V0ZUFzeW5jSnNFeHByZXNzaW9uLCB7IGV4cHJlc3Npb24sIHRlc3RSdW5JZCwgY2FsbHNpdGUgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGV4ZWN1dGVBc3NlcnRpb25GbiAoeyB0ZXN0UnVuSWQsIGNvbW1hbmRJZCB9OiBDb21tYW5kTG9jYXRvcik6IFByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBjb25zdCB7IHByb3h5IH0gPSBhd2FpdCB0aGlzLl9nZXRSdW50aW1lKCk7XG5cbiAgICAgICAgcmV0dXJuIHByb3h5LmNhbGwodGhpcy5leGVjdXRlQXNzZXJ0aW9uRm4sIHsgdGVzdFJ1bklkLCBjb21tYW5kSWQgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGFkZFVuZXhwZWN0ZWRFcnJvciAoeyB0eXBlLCBtZXNzYWdlIH06IEFkZFVuZXhwZWN0ZWRFcnJvckFyZ3VtZW50cyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBFcnJvclR5cGVDb25zdHJ1Y3RvciA9IHRoaXMuX2dldEVycm9yVHlwZUNvbnN0cnVjdG9yKHR5cGUpO1xuXG4gICAgICAgIGhhbmRsZVVuZXhwZWN0ZWRFcnJvcihFcnJvclR5cGVDb25zdHJ1Y3RvciwgbWVzc2FnZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNoZWNrV2luZG93ICh7IHRlc3RSdW5JZCwgY29tbWFuZElkLCB1cmwsIHRpdGxlIH06IENoZWNrV2luZG93QXJndW1lbnQpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgeyBwcm94eSB9ID0gYXdhaXQgdGhpcy5fZ2V0UnVudGltZSgpO1xuXG4gICAgICAgIHJldHVybiBwcm94eS5jYWxsKHRoaXMuY2hlY2tXaW5kb3csIHsgdGVzdFJ1bklkLCBjb21tYW5kSWQsIHVybCwgdGl0bGUgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlbW92ZVRlc3RSdW5Gcm9tU3RhdGUgKHsgdGVzdFJ1bklkIH06IFRlc3RSdW5Mb2NhdG9yKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLnJlbW92ZVRlc3RSdW5Gcm9tU3RhdGUsIHsgdGVzdFJ1bklkIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZW1vdmVGaXh0dXJlQ3R4c0Zyb21TdGF0ZSAoeyBmaXh0dXJlSWRzIH06IFJlbW92ZUZpeHR1cmVDdHhzQXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLnJlbW92ZUZpeHR1cmVDdHhzRnJvbVN0YXRlLCB7IGZpeHR1cmVJZHMgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlbW92ZVVuaXRzRnJvbVN0YXRlICh7IHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkIH06IFJlbW92ZVVuaXRzRnJvbVN0YXRlQXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJveHkgfSA9IGF3YWl0IHRoaXMuX2dldFJ1bnRpbWUoKTtcblxuICAgICAgICByZXR1cm4gcHJveHkuY2FsbCh0aGlzLnJlbW92ZVVuaXRzRnJvbVN0YXRlLCB7IHJ1bm5hYmxlQ29uZmlndXJhdGlvbklkIH0pO1xuICAgIH1cbn1cbiJdfQ==