390 lines
72 KiB
JavaScript
390 lines
72 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
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 commander_1 = __importStar(require("commander"));
|
|
const dedent_1 = __importDefault(require("dedent"));
|
|
const runtime_1 = require("../../errors/runtime");
|
|
const types_1 = require("../../errors/types");
|
|
const type_assertions_1 = require("../../errors/runtime/type-assertions");
|
|
const get_viewport_width_1 = __importDefault(require("../../utils/get-viewport-width"));
|
|
const string_1 = require("../../utils/string");
|
|
const get_options_1 = require("../../utils/get-options");
|
|
const get_filter_fn_1 = __importDefault(require("../../utils/get-filter-fn"));
|
|
const screenshot_option_names_1 = __importDefault(require("../../configuration/screenshot-option-names"));
|
|
const run_option_names_1 = __importDefault(require("../../configuration/run-option-names"));
|
|
const quarantine_option_names_1 = __importDefault(require("../../configuration/quarantine-option-names"));
|
|
const node_arguments_filter_1 = require("../node-arguments-filter");
|
|
const get_testcafe_version_1 = __importDefault(require("../../utils/get-testcafe-version"));
|
|
const parse_utils_1 = require("./parse-utils");
|
|
const command_names_1 = __importDefault(require("./command-names"));
|
|
const skip_js_errors_option_names_1 = require("../../configuration/skip-js-errors-option-names");
|
|
const REMOTE_ALIAS_RE = /^remote(?::(\d*))?$/;
|
|
const DESCRIPTION = (0, dedent_1.default)(`
|
|
|
|
To select a browser, specify an alias ("ie", "chrome", etc.) or the path to the browser executable. You can select more than one browser.
|
|
|
|
Use the "all" alias to run tests against all available browsers.
|
|
Use the "remote" alias to run tests on remote devices, like smartphones or tablets. Specify the number of remote browsers after the semicolon ("remote:3").
|
|
If you use a browser provider plugin, specify both the name of the plugin and the name of the browser. Separate the two with a semicolon ("saucelabs:chrome@51").
|
|
|
|
To execute multiple test files, specify multiple file paths or glob patterns.
|
|
|
|
Full documentation: https://testcafe.io/documentation/402639/reference/command-line-interface
|
|
`);
|
|
class CLIArgumentParser {
|
|
constructor(cwd) {
|
|
this.cwd = cwd || process.cwd();
|
|
this.remoteCount = 0;
|
|
this.opts = {};
|
|
this.args = [];
|
|
this.isDashboardCommand = false;
|
|
this.testCafeCommand = this._addTestCafeCommand();
|
|
this._patchHelpOutput(this.testCafeCommand);
|
|
CLIArgumentParser._setupRootCommand();
|
|
}
|
|
static _setupRootCommand() {
|
|
// NOTE: We are forced to set the name of the root command to 'testcafe'
|
|
// to avoid the automatic command name calculation using the executed file path.
|
|
// It's necessary to correct command description for nested commands.
|
|
commander_1.default.name(command_names_1.default.TestCafe);
|
|
}
|
|
static _removeCommandIfExists(name) {
|
|
// NOTE: Bug in the 'commander' module.
|
|
// It's possible to add a few commands with the same name.
|
|
// Also, removing is a better than conditionally adding
|
|
// because it allows avoiding the parsed option duplicates.
|
|
const index = commander_1.default.commands.findIndex(cmd => cmd.name() === name);
|
|
if (index > -1)
|
|
commander_1.default.commands.splice(index, 1);
|
|
}
|
|
static _getDescription() {
|
|
// NOTE: add empty line to workaround commander-forced indentation on the first line.
|
|
return '\n' + (0, string_1.wordWrap)(DESCRIPTION, 2, (0, get_viewport_width_1.default)(process.stdout));
|
|
}
|
|
_addTestCafeCommand() {
|
|
CLIArgumentParser._removeCommandIfExists(command_names_1.default.TestCafe);
|
|
return commander_1.default
|
|
.command(command_names_1.default.TestCafe, { isDefault: true })
|
|
.version((0, get_testcafe_version_1.default)(), '-v, --version')
|
|
.usage('[options] <comma-separated-browser-list> <file-or-glob ...>')
|
|
.description(CLIArgumentParser._getDescription())
|
|
.allowUnknownOption()
|
|
.option('-b, --list-browsers [provider]', 'display the list of aliases for available browsers and browser providers')
|
|
.option('-r, --reporter <name[:outputFile][,...]>', 'specify reporters and report filenames')
|
|
.option('-s, --screenshots <option=value[,...]>', 'specify screenshot options')
|
|
.option('-S, --screenshots-on-fails', 'take a screenshot on test failure')
|
|
.option('-p, --screenshot-path-pattern <pattern>', 'specify the naming schema for screenshot filenames and paths: ${BROWSER}, ${BROWSER_VERSION}, ${OS}, etc.')
|
|
.option('-q, --quarantine-mode [option=value,...]', 'enable and configure quarantine mode')
|
|
.option('-d, --debug-mode', 'enable debug mode. When you run TestCafe in debug mode, it executes test steps one by one, and pauses the test after each step.')
|
|
.option('-e, --skip-js-errors [option=value,...]', 'ignore JavaScript errors that match the specified criteria')
|
|
.option('-u, --skip-uncaught-errors', 'ignore uncaught errors and unhandled promise rejections')
|
|
.option('-t, --test <name>', 'filter tests by name')
|
|
.option('-T, --test-grep <pattern>', 'filter tests by regular expression')
|
|
.option('-f, --fixture <name>', 'filter fixtures by name')
|
|
.option('-F, --fixture-grep <pattern>', 'filter fixtures by regular expression')
|
|
.option('-a, --app <command>', 'execute a shell command on startup to launch a web application or perform other preparatory tasks')
|
|
.option('-c, --concurrency <number>', 'run tests concurrently')
|
|
.option('-L, --live', 'enable live mode. Live mode restarts tests when you make changes to test files.')
|
|
.option('--test-meta <key=value[,key2=value2,...]>', 'filter tests by metadata')
|
|
.option('--fixture-meta <key=value[,key2=value2,...]>', 'filter fixtures by metadata')
|
|
.option('--debug-on-fail', 'pause tests on failure')
|
|
.option('--experimental-proxyless', 'enable proxyless mode: https://testcafe.io/documentation/404237/guides/experimental-capabilities/proxyless-mode')
|
|
.option('--app-init-delay <ms>', 'specify your application`s initialization time')
|
|
.option('--selector-timeout <ms>', 'specify the maximum Selector resolution time')
|
|
.option('--assertion-timeout <ms>', 'specify the maximum Assertion resolution time')
|
|
.option('--page-load-timeout <ms>', 'specify the maximum time between the window.load event and the DOMContentLoaded event (ms)')
|
|
.option('--page-request-timeout <ms>', 'specify the maximum page request resolution time')
|
|
.option('--ajax-request-timeout <ms>', 'specify the maximum AJAX request resolution time')
|
|
.option('--browser-init-timeout <ms>', 'specify the maximum browser startup time')
|
|
.option('--test-execution-timeout <ms>', 'specify the maximum test execution time')
|
|
.option('--run-execution-timeout <ms>', 'specify the maximum test run time')
|
|
.option('--speed <factor>', 'set test execution speed (0.01 ... 1)')
|
|
.option('--ports <port1,port2>', 'specify network ports to use during the test run. The second port is necessary to access cross-domain resources.')
|
|
.option('--hostname <name>', `specify your hostname. Necessary to run tests in remote browsers.`)
|
|
.option('--proxy <host>', 'specify the proxy server hostname or IP address')
|
|
.option('--proxy-bypass <rules>', 'specify URLs that bypass the proxy server')
|
|
.option('--ssl <options>', 'specify SSL options to run TestCafe over HTTPS')
|
|
.option('--video <path>', 'record videos of test runs')
|
|
.option('--video-options <option=value[,...]>', 'specify video recording options')
|
|
.option('--video-encoding-options <option=value[,...]>', 'specify video encoding options')
|
|
.option('--dev', 'log and diagnose TestCafe errors')
|
|
.option('--qr-code', 'output QR codes with URLs for remote browser connections')
|
|
.option('--sf, --stop-on-first-fail', 'stop the test run if any test fails')
|
|
.option('--config-file <path>', 'specify a custom path to the testcafe configuration file')
|
|
.option('--ts-config-path <path>', 'specify the path to a custom TypeScript configuration file')
|
|
.option('--cs, --client-scripts <paths>', 'inject client-side scripts into the page', parse_utils_1.parseList, [])
|
|
.option('--disable-page-caching', 'do not cache pages')
|
|
.option('--disable-page-reloads', 'do not reload pages between tests')
|
|
.option('--retry-test-pages', 'retry page requests in case of failure')
|
|
.option('--disable-screenshots', 'disable screenshots')
|
|
.option('--screenshots-full-page', 'enable full-page screenshots')
|
|
.option('--compiler-options <option=value[,...]>', 'specify test compilation settings')
|
|
.option('--disable-multiple-windows', 'disable the multi-window mode')
|
|
.option('--disable-http2', 'force the proxy to issue HTTP/1.1 requests')
|
|
.option('--cache', 'cache web assets between test runs')
|
|
.option('--base-url <url>', 'set the base url for the test run')
|
|
// NOTE: these options will be handled by chalk internally
|
|
.option('--color', 'force TestCafe to format CLI output with color')
|
|
.option('--no-color', 'disable text color formatting in the CLI')
|
|
// NOTE: Temporarily exclude experimental options from --help output
|
|
.addOption(new commander_1.Option('--experimental-debug', 'enable experimental the debug mode').hideHelp())
|
|
.addOption(new commander_1.Option('--experimental-esm', 'enable experimental the esm mode').hideHelp())
|
|
.addOption(new commander_1.Option('--disable-cross-domain', 'experimental').hideHelp())
|
|
.action((opts) => {
|
|
this.opts = opts;
|
|
});
|
|
}
|
|
_patchHelpOutput(defaultSubCommand) {
|
|
// NOTE: In the future versions of the 'commander' module
|
|
// need to investigate how to remove this hack.
|
|
commander_1.default.outputHelp = function () {
|
|
const storedParent = defaultSubCommand.parent;
|
|
defaultSubCommand.parent = null;
|
|
defaultSubCommand.outputHelp();
|
|
defaultSubCommand.parent = storedParent;
|
|
};
|
|
}
|
|
_checkAndCountRemotes(browser) {
|
|
const remoteMatch = browser.match(REMOTE_ALIAS_RE);
|
|
if (remoteMatch) {
|
|
this.remoteCount += parseInt(remoteMatch[1], 10) || 1;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
async _parseFilteringOptions() {
|
|
if (this.opts.testGrep)
|
|
this.opts.testGrep = (0, get_options_1.getGrepOptions)('--test-grep', this.opts.testGrep);
|
|
if (this.opts.fixtureGrep)
|
|
this.opts.fixtureGrep = (0, get_options_1.getGrepOptions)('--fixture-grep', this.opts.fixtureGrep);
|
|
if (this.opts.testMeta)
|
|
this.opts.testMeta = await (0, get_options_1.getMetaOptions)('--test-meta', this.opts.testMeta);
|
|
if (this.opts.fixtureMeta)
|
|
this.opts.fixtureMeta = await (0, get_options_1.getMetaOptions)('--fixture-meta', this.opts.fixtureMeta);
|
|
this.opts.filter = (0, get_filter_fn_1.default)(this.opts);
|
|
}
|
|
_parseAppInitDelay() {
|
|
if (this.opts.appInitDelay) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The tested app initialization delay', this.opts.appInitDelay);
|
|
this.opts.appInitDelay = parseInt(this.opts.appInitDelay, 10);
|
|
}
|
|
}
|
|
_parseSelectorTimeout() {
|
|
if (this.opts.selectorTimeout) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The Selector timeout', this.opts.selectorTimeout);
|
|
this.opts.selectorTimeout = parseInt(this.opts.selectorTimeout, 10);
|
|
}
|
|
}
|
|
_parseAssertionTimeout() {
|
|
if (this.opts.assertionTimeout) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The assertion timeout', this.opts.assertionTimeout);
|
|
this.opts.assertionTimeout = parseInt(this.opts.assertionTimeout, 10);
|
|
}
|
|
}
|
|
_parsePageLoadTimeout() {
|
|
if (this.opts.pageLoadTimeout) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The page load timeout', this.opts.pageLoadTimeout);
|
|
this.opts.pageLoadTimeout = parseInt(this.opts.pageLoadTimeout, 10);
|
|
}
|
|
}
|
|
_parsePageRequestTimeout() {
|
|
if (!this.opts.pageRequestTimeout)
|
|
return;
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The page request timeout', this.opts.pageRequestTimeout);
|
|
this.opts.pageRequestTimeout = parseInt(this.opts.pageRequestTimeout, 10);
|
|
}
|
|
_parseAjaxRequestTimeout() {
|
|
if (!this.opts.ajaxRequestTimeout)
|
|
return;
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The AJAX request timeout', this.opts.ajaxRequestTimeout);
|
|
this.opts.ajaxRequestTimeout = parseInt(this.opts.ajaxRequestTimeout, 10);
|
|
}
|
|
_parseBrowserInitTimeout() {
|
|
if (!this.opts.browserInitTimeout)
|
|
return;
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The browser initialization timeout', this.opts.browserInitTimeout);
|
|
this.opts.browserInitTimeout = parseInt(this.opts.browserInitTimeout, 10);
|
|
}
|
|
_parseTestExecutionTimeout() {
|
|
if (this.opts.testExecutionTimeout) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The test execution timeout', this.opts.testExecutionTimeout);
|
|
this.opts.testExecutionTimeout = parseInt(this.opts.testExecutionTimeout, 10);
|
|
}
|
|
}
|
|
_parseRunExecutionTimeout() {
|
|
if (this.opts.runExecutionTimeout) {
|
|
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The run execution timeout', this.opts.runExecutionTimeout);
|
|
this.opts.runExecutionTimeout = parseInt(this.opts.runExecutionTimeout, 10);
|
|
}
|
|
}
|
|
_parseSpeed() {
|
|
if (this.opts.speed)
|
|
this.opts.speed = parseFloat(this.opts.speed);
|
|
}
|
|
_parseConcurrency() {
|
|
if (this.opts.concurrency)
|
|
this.opts.concurrency = parseInt(this.opts.concurrency, 10);
|
|
}
|
|
async _parseQuarantineOptions() {
|
|
if (this.opts.quarantineMode)
|
|
this.opts.quarantineMode = await (0, get_options_1.getQuarantineOptions)('--quarantine-mode', this.opts.quarantineMode);
|
|
}
|
|
async _parseSkipJsErrorsOptions() {
|
|
if (this.opts.skipJsErrors)
|
|
this.opts.skipJsErrors = await (0, get_options_1.getSkipJsErrorsOptions)('--skip-js-errors', this.opts.skipJsErrors);
|
|
}
|
|
_parsePorts() {
|
|
if (this.opts.ports) {
|
|
const parsedPorts = this.opts.ports /* eslint-disable-line no-extra-parens */
|
|
.split(',')
|
|
.map(parse_utils_1.parsePortNumber);
|
|
if (parsedPorts.length < 2)
|
|
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.portsOptionRequiresTwoNumbers);
|
|
this.opts.ports = parsedPorts;
|
|
}
|
|
}
|
|
_parseBrowsersFromArgs() {
|
|
const browsersArg = this.testCafeCommand.args[0] || '';
|
|
this.opts.browsers = (0, string_1.splitQuotedText)(browsersArg, ',')
|
|
.filter(browser => browser && this._checkAndCountRemotes(browser));
|
|
}
|
|
async _parseSslOptions() {
|
|
if (this.opts.ssl)
|
|
this.opts.ssl = await (0, get_options_1.getSSLOptions)(this.opts.ssl);
|
|
}
|
|
async _parseReporters() {
|
|
const reporters = this.opts.reporter ? this.opts.reporter.split(',') : []; /* eslint-disable-line no-extra-parens*/
|
|
this.opts.reporter = reporters.map((reporter) => {
|
|
const separatorIndex = reporter.indexOf(':');
|
|
if (separatorIndex < 0)
|
|
return { name: reporter };
|
|
const name = reporter.substring(0, separatorIndex);
|
|
const output = reporter.substring(separatorIndex + 1);
|
|
return { name, output };
|
|
});
|
|
}
|
|
_parseFileList() {
|
|
this.opts.src = this.testCafeCommand.args.slice(1);
|
|
}
|
|
async _parseScreenshotOptions() {
|
|
if (this.opts.screenshots)
|
|
this.opts.screenshots = await (0, get_options_1.getScreenshotOptions)(this.opts.screenshots);
|
|
else
|
|
this.opts.screenshots = {};
|
|
if (!(0, lodash_1.has)(this.opts.screenshots, screenshot_option_names_1.default.pathPattern) && this.opts.screenshotPathPattern)
|
|
this.opts.screenshots[screenshot_option_names_1.default.pathPattern] = this.opts.screenshotPathPattern;
|
|
if (!(0, lodash_1.has)(this.opts.screenshots, screenshot_option_names_1.default.takeOnFails) && this.opts.screenshotsOnFails)
|
|
this.opts.screenshots[screenshot_option_names_1.default.takeOnFails] = this.opts.screenshotsOnFails;
|
|
}
|
|
async _parseVideoOptions() {
|
|
if (this.opts.videoOptions)
|
|
this.opts.videoOptions = await (0, get_options_1.getVideoOptions)(this.opts.videoOptions);
|
|
if (this.opts.videoEncodingOptions)
|
|
this.opts.videoEncodingOptions = await (0, get_options_1.getVideoOptions)(this.opts.videoEncodingOptions);
|
|
}
|
|
async _parseCompilerOptions() {
|
|
if (!this.opts.compilerOptions)
|
|
return;
|
|
const parsedCompilerOptions = await (0, get_options_1.getCompilerOptions)(this.opts.compilerOptions);
|
|
const resultCompilerOptions = Object.create(null);
|
|
for (const [key, value] of Object.entries(parsedCompilerOptions))
|
|
(0, lodash_1.set)(resultCompilerOptions, key, value);
|
|
this.opts.compilerOptions = resultCompilerOptions;
|
|
}
|
|
async _parseDashboardOptions() {
|
|
if (this.opts.dashboardOptions)
|
|
this.opts.dashboardOptions = await (0, get_options_1.getDashboardOptions)(this.opts.dashboardOptions);
|
|
}
|
|
_parseListBrowsers() {
|
|
const listBrowserOption = this.opts.listBrowsers;
|
|
this.opts.listBrowsers = !!this.opts.listBrowsers;
|
|
if (!this.opts.listBrowsers)
|
|
return;
|
|
this.opts.providerName = typeof listBrowserOption === 'string' ? listBrowserOption : 'locally-installed';
|
|
}
|
|
static _prepareBooleanOrObjectOption(argv, optionNames, subOptionsNames) {
|
|
// NOTE: move options to the end of the array to correctly parse both Boolean and Object type arguments (GH-6231)
|
|
const optionIndex = argv.findIndex(el => optionNames.some(opt => el.startsWith(opt)));
|
|
if (optionIndex > -1) {
|
|
const isNotLastOption = optionIndex < argv.length - 1;
|
|
const shouldMoveOptionToEnd = isNotLastOption &&
|
|
!subOptionsNames.some(opt => argv[optionIndex + 1].startsWith(opt));
|
|
if (shouldMoveOptionToEnd)
|
|
argv.push(argv.splice(optionIndex, 1)[0]);
|
|
}
|
|
}
|
|
async parse(argv) {
|
|
CLIArgumentParser._prepareBooleanOrObjectOption(argv, ['-q', '--quarantine-mode'], Object.values(quarantine_option_names_1.default));
|
|
CLIArgumentParser._prepareBooleanOrObjectOption(argv, ['-e', '--skip-js-errors'], Object.values(skip_js_errors_option_names_1.SKIP_JS_ERRORS_OPTIONS_OBJECT_OPTION_NAMES));
|
|
const { args, v8Flags } = (0, node_arguments_filter_1.extractNodeProcessArguments)(argv);
|
|
commander_1.default.parse(args);
|
|
this.args = commander_1.default.args;
|
|
this.opts = Object.assign(this.opts, { v8Flags });
|
|
this._parseListBrowsers();
|
|
// NOTE: the '--list-browsers' option only lists browsers and immediately exits the app.
|
|
// Therefore, we don't need to process other arguments.
|
|
if (this.opts.listBrowsers)
|
|
return;
|
|
this._parseSelectorTimeout();
|
|
this._parseAssertionTimeout();
|
|
this._parsePageLoadTimeout();
|
|
this._parsePageRequestTimeout();
|
|
this._parseAjaxRequestTimeout();
|
|
this._parseBrowserInitTimeout();
|
|
this._parseTestExecutionTimeout();
|
|
this._parseRunExecutionTimeout();
|
|
this._parseAppInitDelay();
|
|
this._parseSpeed();
|
|
this._parsePorts();
|
|
this._parseBrowsersFromArgs();
|
|
this._parseConcurrency();
|
|
this._parseFileList();
|
|
await this._parseFilteringOptions();
|
|
await this._parseQuarantineOptions();
|
|
await this._parseSkipJsErrorsOptions();
|
|
await this._parseScreenshotOptions();
|
|
await this._parseVideoOptions();
|
|
await this._parseCompilerOptions();
|
|
await this._parseSslOptions();
|
|
await this._parseReporters();
|
|
await this._parseDashboardOptions();
|
|
}
|
|
getRunOptions() {
|
|
const result = Object.create(null);
|
|
run_option_names_1.default.forEach(optionName => {
|
|
if (optionName in this.opts)
|
|
// @ts-ignore a hack to add an index signature to interface
|
|
result[optionName] = this.opts[optionName];
|
|
});
|
|
return result;
|
|
}
|
|
}
|
|
exports.default = CLIArgumentParser;
|
|
module.exports = exports.default;
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2xpL2FyZ3VtZW50LXBhcnNlci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUNBQWtDO0FBRWxDLHVEQUdtQjtBQUVuQixvREFBNEI7QUFDNUIsa0RBQW9EO0FBQ3BELDhDQUFvRDtBQUNwRCwwRUFBc0U7QUFDdEUsd0ZBQThEO0FBQzlELCtDQUErRDtBQUMvRCx5REFVaUM7QUFFakMsOEVBQW9EO0FBQ3BELDBHQUFrRjtBQUNsRiw0RkFBb0U7QUFNcEUsMEdBQWtGO0FBQ2xGLG9FQUF1RTtBQUN2RSw0RkFBa0U7QUFDbEUsK0NBQTJEO0FBQzNELG9FQUE0QztBQUU1QyxpR0FBNkc7QUFFN0csTUFBTSxlQUFlLEdBQUcscUJBQXFCLENBQUM7QUFFOUMsTUFBTSxXQUFXLEdBQUcsSUFBQSxnQkFBTSxFQUFDOzs7Ozs7Ozs7OztDQVcxQixDQUFDLENBQUM7QUF5Q0gsTUFBcUIsaUJBQWlCO0lBU2xDLFlBQW9CLEdBQVk7UUFDNUIsSUFBSSxDQUFDLEdBQUcsR0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEdBQVUsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxJQUFJLEdBQVUsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7UUFDaEMsSUFBSSxDQUFDLGVBQWUsR0FBTSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUVyRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzVDLGlCQUFpQixDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxpQkFBaUI7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cEMsTUFBTSxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7UUFDckMsTUFBTSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUNoQyxNQUFNLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ25DLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDOUIsTUFBTSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDN0IsTUFBTSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRU0sYUFBYTtRQUNoQixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRW5DLDBCQUFnQixDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUNsQyxJQUFJLFVBQVUsSUFBSSxJQUFJLENBQUMsSUFBSTtnQkFDdkIsMkRBQTJEO2dCQUMzRCxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNuRCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sTUFBMEIsQ0FBQztJQUN0QyxDQUFDO0NBQ0o7QUF6YUQsb0NBeWFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaGFzLCBzZXQgfSBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQgcHJvZ3JhbSwge1xuICAgIENvbW1hbmQsXG4gICAgT3B0aW9uLFxufSBmcm9tICdjb21tYW5kZXInO1xuXG5pbXBvcnQgZGVkZW50IGZyb20gJ2RlZGVudCc7XG5pbXBvcnQgeyBHZW5lcmFsRXJyb3IgfSBmcm9tICcuLi8uLi9lcnJvcnMvcnVudGltZSc7XG5pbXBvcnQgeyBSVU5USU1FX0VSUk9SUyB9IGZyb20gJy4uLy4uL2Vycm9ycy90eXBlcyc7XG5pbXBvcnQgeyBhc3NlcnRUeXBlLCBpcyB9IGZyb20gJy4uLy4uL2Vycm9ycy9ydW50aW1lL3R5cGUtYXNzZXJ0aW9ucyc7XG5pbXBvcnQgZ2V0Vmlld1BvcnRXaWR0aCBmcm9tICcuLi8uLi91dGlscy9nZXQtdmlld3BvcnQtd2lkdGgnO1xuaW1wb3J0IHsgd29yZFdyYXAsIHNwbGl0UXVvdGVkVGV4dCB9IGZyb20gJy4uLy4uL3V0aWxzL3N0cmluZyc7XG5pbXBvcnQge1xuICAgIGdldFNTTE9wdGlvbnMsXG4gICAgZ2V0UXVhcmFudGluZU9wdGlvbnMsXG4gICAgZ2V0U2NyZWVuc2hvdE9wdGlvbnMsXG4gICAgZ2V0U2tpcEpzRXJyb3JzT3B0aW9ucyxcbiAgICBnZXRWaWRlb09wdGlvbnMsXG4gICAgZ2V0TWV0YU9wdGlvbnMsXG4gICAgZ2V0R3JlcE9wdGlvbnMsXG4gICAgZ2V0Q29tcGlsZXJPcHRpb25zLFxuICAgIGdldERhc2hib2FyZE9wdGlvbnMsXG59IGZyb20gJy4uLy4uL3V0aWxzL2dldC1vcHRpb25zJztcblxuaW1wb3J0IGdldEZpbHRlckZuIGZyb20gJy4uLy4uL3V0aWxzL2dldC1maWx0ZXItZm4nO1xuaW1wb3J0IFNDUkVFTlNIT1RfT1BUSU9OX05BTUVTIGZyb20gJy4uLy4uL2NvbmZpZ3VyYXRpb24vc2NyZWVuc2hvdC1vcHRpb24tbmFtZXMnO1xuaW1wb3J0IFJVTl9PUFRJT05fTkFNRVMgZnJvbSAnLi4vLi4vY29uZmlndXJhdGlvbi9ydW4tb3B0aW9uLW5hbWVzJztcbmltcG9ydCB7XG4gICAgRGljdGlvbmFyeSxcbiAgICBSZXBvcnRlck9wdGlvbixcbiAgICBSdW5uZXJSdW5PcHRpb25zLFxufSBmcm9tICcuLi8uLi9jb25maWd1cmF0aW9uL2ludGVyZmFjZXMnO1xuaW1wb3J0IFFVQVJBTlRJTkVfT1BUSU9OX05BTUVTIGZyb20gJy4uLy4uL2NvbmZpZ3VyYXRpb24vcXVhcmFudGluZS1vcHRpb24tbmFtZXMnO1xuaW1wb3J0IHsgZXh0cmFjdE5vZGVQcm9jZXNzQXJndW1lbnRzIH0gZnJvbSAnLi4vbm9kZS1hcmd1bWVudHMtZmlsdGVyJztcbmltcG9ydCBnZXRUZXN0Y2FmZVZlcnNpb24gZnJvbSAnLi4vLi4vdXRpbHMvZ2V0LXRlc3RjYWZlLXZlcnNpb24nO1xuaW1wb3J0IHsgcGFyc2VQb3J0TnVtYmVyLCBwYXJzZUxpc3QgfSBmcm9tICcuL3BhcnNlLXV0aWxzJztcbmltcG9ydCBDT01NQU5EX05BTUVTIGZyb20gJy4vY29tbWFuZC1uYW1lcyc7XG5pbXBvcnQgeyBTZW5kUmVwb3J0U3RhdGUgfSBmcm9tICcuLi8uLi9kYXNoYm9hcmQvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBTS0lQX0pTX0VSUk9SU19PUFRJT05TX09CSkVDVF9PUFRJT05fTkFNRVMgfSBmcm9tICcuLi8uLi9jb25maWd1cmF0aW9uL3NraXAtanMtZXJyb3JzLW9wdGlvbi1uYW1lcyc7XG5cbmNvbnN0IFJFTU9URV9BTElBU19SRSA9IC9ecmVtb3RlKD86OihcXGQqKSk/JC87XG5cbmNvbnN0IERFU0NSSVBUSU9OID0gZGVkZW50KGBcblxuICAgIFRvIHNlbGVjdCBhIGJyb3dzZXIsIHNwZWNpZnkgYW4gYWxpYXMgKFwiaWVcIiwgXCJjaHJvbWVcIiwgZXRjLikgb3IgdGhlIHBhdGggdG8gdGhlIGJyb3dzZXIgZXhlY3V0YWJsZS4gWW91IGNhbiBzZWxlY3QgbW9yZSB0aGFuIG9uZSBicm93c2VyLlxuICAgIFxuICAgIFVzZSB0aGUgXCJhbGxcIiBhbGlhcyB0byBydW4gdGVzdHMgYWdhaW5zdCBhbGwgYXZhaWxhYmxlIGJyb3dzZXJzLiAgIFxuICAgIFVzZSB0aGUgXCJyZW1vdGVcIiBhbGlhcyB0byBydW4gdGVzdHMgb24gcmVtb3RlIGRldmljZXMsIGxpa2Ugc21hcnRwaG9uZXMgb3IgdGFibGV0cy4gU3BlY2lmeSB0aGUgbnVtYmVyIG9mIHJlbW90ZSBicm93c2VycyBhZnRlciB0aGUgc2VtaWNvbG9uIChcInJlbW90ZTozXCIpLlxuICAgIElmIHlvdSB1c2UgYSBicm93c2VyIHByb3ZpZGVyIHBsdWdpbiwgc3BlY2lmeSBib3RoIHRoZSBuYW1lIG9mIHRoZSBwbHVnaW4gYW5kIHRoZSBuYW1lIG9mIHRoZSBicm93c2VyLiBTZXBhcmF0ZSB0aGUgdHdvIHdpdGggYSBzZW1pY29sb24gKFwic2F1Y2VsYWJzOmNocm9tZUA1MVwiKS5cblxuICAgIFRvIGV4ZWN1dGUgbXVsdGlwbGUgdGVzdCBmaWxlcywgc3BlY2lmeSBtdWx0aXBsZSBmaWxlIHBhdGhzIG9yIGdsb2IgcGF0dGVybnMuXG5cbiAgICBGdWxsIGRvY3VtZW50YXRpb246IGh0dHBzOi8vdGVzdGNhZmUuaW8vZG9jdW1lbnRhdGlvbi80MDI2MzkvcmVmZXJlbmNlL2NvbW1hbmQtbGluZS1pbnRlcmZhY2VcbmApO1xuXG5pbnRlcmZhY2UgQ29tbWFuZExpbmVPcHRpb25zIHtcbiAgICB0ZXN0R3JlcD86IHN0cmluZyB8IFJlZ0V4cDtcbiAgICBmaXh0dXJlR3JlcD86IHN0cmluZyB8IFJlZ0V4cDtcbiAgICBzcmM/OiBzdHJpbmdbXTtcbiAgICBicm93c2Vycz86IHN0cmluZ1tdO1xuICAgIGxpc3RCcm93c2Vycz86IGJvb2xlYW4gfCBzdHJpbmc7XG4gICAgdGVzdE1ldGE/OiBzdHJpbmcgfCBEaWN0aW9uYXJ5PHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4+O1xuICAgIGZpeHR1cmVNZXRhPzogc3RyaW5nIHwgRGljdGlvbmFyeTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPjtcbiAgICBmaWx0ZXI/OiBGdW5jdGlvbjtcbiAgICBhcHBJbml0RGVsYXk/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgYXNzZXJ0aW9uVGltZW91dD86IHN0cmluZyB8IG51bWJlcjtcbiAgICBzZWxlY3RvclRpbWVvdXQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgc3BlZWQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgcGFnZUxvYWRUaW1lb3V0Pzogc3RyaW5nIHwgbnVtYmVyO1xuICAgIHBhZ2VSZXF1ZXN0VGltZW91dD86IHN0cmluZyB8IG51bWJlcjtcbiAgICBhamF4UmVxdWVzdFRpbWVvdXQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgYnJvd3NlckluaXRUaW1lb3V0Pzogc3RyaW5nIHwgbnVtYmVyO1xuICAgIHRlc3RFeGVjdXRpb25UaW1lb3V0Pzogc3RyaW5nIHwgbnVtYmVyO1xuICAgIHJ1bkV4ZWN1dGlvblRpbWVvdXQ/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgY29uY3VycmVuY3k/OiBzdHJpbmcgfCBudW1iZXI7XG4gICAgcXVhcmFudGluZU1vZGU/OiBib29sZWFuIHwgRGljdGlvbmFyeTxzdHJpbmcgfCBudW1iZXI+O1xuICAgIHBvcnRzPzogc3RyaW5nIHwgbnVtYmVyW107XG4gICAgcHJvdmlkZXJOYW1lPzogc3RyaW5nO1xuICAgIHNzbD86IHN0cmluZyB8IERpY3Rpb25hcnk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj47XG4gICAgcmVwb3J0ZXI/OiBzdHJpbmcgfCBSZXBvcnRlck9wdGlvbltdO1xuICAgIHNjcmVlbnNob3RzPzogRGljdGlvbmFyeTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPiB8IHN0cmluZztcbiAgICBzY3JlZW5zaG90UGF0aFBhdHRlcm4/OiBzdHJpbmc7XG4gICAgc2NyZWVuc2hvdHNPbkZhaWxzPzogYm9vbGVhbjtcbiAgICB2aWRlb09wdGlvbnM/OiBzdHJpbmcgfCBEaWN0aW9uYXJ5PG51bWJlciB8IHN0cmluZyB8IGJvb2xlYW4+O1xuICAgIHZpZGVvRW5jb2RpbmdPcHRpb25zPzogc3RyaW5nIHwgRGljdGlvbmFyeTxudW1iZXIgfCBzdHJpbmcgfCBib29sZWFuPjtcbiAgICBjb21waWxlck9wdGlvbnM/OiBzdHJpbmcgfCBEaWN0aW9uYXJ5PG51bWJlciB8IHN0cmluZyB8IGJvb2xlYW4+O1xuICAgIGNvbmZpZ0ZpbGU/OiBzdHJpbmc7XG4gICAgcHJveHlsZXNzPzogYm9vbGVhbjtcbiAgICB2OEZsYWdzPzogc3RyaW5nW107XG4gICAgZGFzaGJvYXJkT3B0aW9ucz86IHN0cmluZyB8IERpY3Rpb25hcnk8c3RyaW5nIHwgYm9vbGVhbiB8IG51bWJlcj47XG4gICAgYmFzZVVybD86IHN0cmluZztcbiAgICBza2lwSnNFcnJvcnM/OiBib29sZWFuIHwgRGljdGlvbmFyeTxSZWdFeHAgfCBzdHJpbmc+O1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDTElBcmd1bWVudFBhcnNlciB7XG4gICAgcHJpdmF0ZSBjd2Q6IHN0cmluZztcbiAgICBwcml2YXRlIHJlbW90ZUNvdW50OiBudW1iZXI7XG4gICAgcHVibGljIGlzRGFzaGJvYXJkQ29tbWFuZDogYm9vbGVhbjtcbiAgICBwdWJsaWMgc2VuZFJlcG9ydFN0YXRlOiBTZW5kUmVwb3J0U3RhdGU7XG4gICAgcHVibGljIG9wdHM6IENvbW1hbmRMaW5lT3B0aW9ucztcbiAgICBwdWJsaWMgYXJnczogc3RyaW5nW107XG4gICAgcHJpdmF0ZSByZWFkb25seSB0ZXN0Q2FmZUNvbW1hbmQ6IENvbW1hbmQ7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKGN3ZD86IHN0cmluZykge1xuICAgICAgICB0aGlzLmN3ZCAgICAgICAgID0gY3dkIHx8IHByb2Nlc3MuY3dkKCk7XG4gICAgICAgIHRoaXMucmVtb3RlQ291bnQgPSAwO1xuICAgICAgICB0aGlzLm9wdHMgICAgICAgID0ge307XG4gICAgICAgIHRoaXMuYXJncyAgICAgICAgPSBbXTtcblxuICAgICAgICB0aGlzLmlzRGFzaGJvYXJkQ29tbWFuZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnRlc3RDYWZlQ29tbWFuZCAgICA9IHRoaXMuX2FkZFRlc3RDYWZlQ29tbWFuZCgpO1xuXG4gICAgICAgIHRoaXMuX3BhdGNoSGVscE91dHB1dCh0aGlzLnRlc3RDYWZlQ29tbWFuZCk7XG4gICAgICAgIENMSUFyZ3VtZW50UGFyc2VyLl9zZXR1cFJvb3RDb21tYW5kKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgX3NldHVwUm9vdENvbW1hbmQgKCk6IHZvaWQge1xuICAgICAgICAvLyBOT1RFOiBXZSBhcmUgZm9yY2VkIHRvIHNldCB0aGUgbmFtZSBvZiB0aGUgcm9vdCBjb21tYW5kIHRvICd0ZXN0Y2FmZSdcbiAgICAgICAgLy8gdG8gYXZvaWQgdGhlIGF1dG9tYXRpYyBjb21tYW5kIG5hbWUgY2FsY3VsYXRpb24gdXNpbmcgdGhlIGV4ZWN1dGVkIGZpbGUgcGF0aC5cbiAgICAgICAgLy8gSXQncyBuZWNlc3NhcnkgdG8gY29ycmVjdCBjb21tYW5kIGRlc2NyaXB0aW9uIGZvciBuZXN0ZWQgY29tbWFuZHMuXG4gICAgICAgIChwcm9ncmFtIGFzIHVua25vd24gYXMgQ29tbWFuZCkubmFtZShDT01NQU5EX05BTUVTLlRlc3RDYWZlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfcmVtb3ZlQ29tbWFuZElmRXhpc3RzIChuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgLy8gTk9URTogQnVnIGluIHRoZSAnY29tbWFuZGVyJyBtb2R1bGUuXG4gICAgICAgIC8vIEl0J3MgcG9zc2libGUgdG8gYWRkIGEgZmV3IGNvbW1hbmRzIHdpdGggdGhlIHNhbWUgbmFtZS5cbiAgICAgICAgLy8gQWxzbywgcmVtb3ZpbmcgaXMgYSBiZXR0ZXIgdGhhbiBjb25kaXRpb25hbGx5IGFkZGluZ1xuICAgICAgICAvLyBiZWNhdXNlIGl0IGFsbG93cyBhdm9pZGluZyB0aGUgcGFyc2VkIG9wdGlvbiBkdXBsaWNhdGVzLlxuICAgICAgICBjb25zdCBpbmRleCA9IChwcm9ncmFtIGFzIHVua25vd24gYXMgQ29tbWFuZCkuY29tbWFuZHMuZmluZEluZGV4KGNtZCA9PiBjbWQubmFtZSgpID09PSBuYW1lKTtcblxuICAgICAgICBpZiAoaW5kZXggPiAtMSlcbiAgICAgICAgICAgIChwcm9ncmFtIGFzIHVua25vd24gYXMgQ29tbWFuZCkuY29tbWFuZHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfZ2V0RGVzY3JpcHRpb24gKCk6IHN0cmluZyB7XG4gICAgICAgIC8vIE5PVEU6IGFkZCBlbXB0eSBsaW5lIHRvIHdvcmthcm91bmQgY29tbWFuZGVyLWZvcmNlZCBpbmRlbnRhdGlvbiBvbiB0aGUgZmlyc3QgbGluZS5cbiAgICAgICAgcmV0dXJuICdcXG4nICsgd29yZFdyYXAoREVTQ1JJUFRJT04sIDIsIGdldFZpZXdQb3J0V2lkdGgocHJvY2Vzcy5zdGRvdXQpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9hZGRUZXN0Q2FmZUNvbW1hbmQgKCk6IENvbW1hbmQge1xuICAgICAgICBDTElBcmd1bWVudFBhcnNlci5fcmVtb3ZlQ29tbWFuZElmRXhpc3RzKENPTU1BTkRfTkFNRVMuVGVzdENhZmUpO1xuXG4gICAgICAgIHJldHVybiAocHJvZ3JhbSBhcyB1bmtub3duIGFzIENvbW1hbmQpXG4gICAgICAgICAgICAuY29tbWFuZChDT01NQU5EX05BTUVTLlRlc3RDYWZlLCB7IGlzRGVmYXVsdDogdHJ1ZSB9KVxuICAgICAgICAgICAgLnZlcnNpb24oZ2V0VGVzdGNhZmVWZXJzaW9uKCksICctdiwgLS12ZXJzaW9uJylcbiAgICAgICAgICAgIC51c2FnZSgnW29wdGlvbnNdIDxjb21tYS1zZXBhcmF0ZWQtYnJvd3Nlci1saXN0PiA8ZmlsZS1vci1nbG9iIC4uLj4nKVxuICAgICAgICAgICAgLmRlc2NyaXB0aW9uKENMSUFyZ3VtZW50UGFyc2VyLl9nZXREZXNjcmlwdGlvbigpKVxuXG4gICAgICAgICAgICAuYWxsb3dVbmtub3duT3B0aW9uKClcbiAgICAgICAgICAgIC5vcHRpb24oJy1iLCAtLWxpc3QtYnJvd3NlcnMgW3Byb3ZpZGVyXScsICdkaXNwbGF5IHRoZSBsaXN0IG9mIGFsaWFzZXMgZm9yIGF2YWlsYWJsZSBicm93c2VycyBhbmQgYnJvd3NlciBwcm92aWRlcnMnKVxuICAgICAgICAgICAgLm9wdGlvbignLXIsIC0tcmVwb3J0ZXIgPG5hbWVbOm91dHB1dEZpbGVdWywuLi5dPicsICdzcGVjaWZ5IHJlcG9ydGVycyBhbmQgcmVwb3J0IGZpbGVuYW1lcycpXG4gICAgICAgICAgICAub3B0aW9uKCctcywgLS1zY3JlZW5zaG90cyA8b3B0aW9uPXZhbHVlWywuLi5dPicsICdzcGVjaWZ5IHNjcmVlbnNob3Qgb3B0aW9ucycpXG4gICAgICAgICAgICAub3B0aW9uKCctUywgLS1zY3JlZW5zaG90cy1vbi1mYWlscycsICd0YWtlIGEgc2NyZWVuc2hvdCBvbiB0ZXN0IGZhaWx1cmUnKVxuICAgICAgICAgICAgLm9wdGlvbignLXAsIC0tc2NyZWVuc2hvdC1wYXRoLXBhdHRlcm4gPHBhdHRlcm4+JywgJ3NwZWNpZnkgdGhlIG5hbWluZyBzY2hlbWEgZm9yIHNjcmVlbnNob3QgZmlsZW5hbWVzIGFuZCBwYXRoczogJHtCUk9XU0VSfSwgJHtCUk9XU0VSX1ZFUlNJT059LCAke09TfSwgZXRjLicpXG4gICAgICAgICAgICAub3B0aW9uKCctcSwgLS1xdWFyYW50aW5lLW1vZGUgW29wdGlvbj12YWx1ZSwuLi5dJywgJ2VuYWJsZSBhbmQgY29uZmlndXJlIHF1YXJhbnRpbmUgbW9kZScpXG4gICAgICAgICAgICAub3B0aW9uKCctZCwgLS1kZWJ1Zy1tb2RlJywgJ2VuYWJsZSBkZWJ1ZyBtb2RlLiBXaGVuIHlvdSBydW4gVGVzdENhZmUgaW4gZGVidWcgbW9kZSwgaXQgZXhlY3V0ZXMgdGVzdCBzdGVwcyBvbmUgYnkgb25lLCBhbmQgcGF1c2VzIHRoZSB0ZXN0IGFmdGVyIGVhY2ggc3RlcC4nKVxuICAgICAgICAgICAgLm9wdGlvbignLWUsIC0tc2tpcC1qcy1lcnJvcnMgW29wdGlvbj12YWx1ZSwuLi5dJywgJ2lnbm9yZSBKYXZhU2NyaXB0IGVycm9ycyB0aGF0IG1hdGNoIHRoZSBzcGVjaWZpZWQgY3JpdGVyaWEnKVxuICAgICAgICAgICAgLm9wdGlvbignLXUsIC0tc2tpcC11bmNhdWdodC1lcnJvcnMnLCAnaWdub3JlIHVuY2F1Z2h0IGVycm9ycyBhbmQgdW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9ucycpXG4gICAgICAgICAgICAub3B0aW9uKCctdCwgLS10ZXN0IDxuYW1lPicsICdmaWx0ZXIgdGVzdHMgYnkgbmFtZScpXG4gICAgICAgICAgICAub3B0aW9uKCctVCwgLS10ZXN0LWdyZXAgPHBhdHRlcm4+JywgJ2ZpbHRlciB0ZXN0cyBieSByZWd1bGFyIGV4cHJlc3Npb24nKVxuICAgICAgICAgICAgLm9wdGlvbignLWYsIC0tZml4dHVyZSA8bmFtZT4nLCAnZmlsdGVyIGZpeHR1cmVzIGJ5IG5hbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLUYsIC0tZml4dHVyZS1ncmVwIDxwYXR0ZXJuPicsICdmaWx0ZXIgZml4dHVyZXMgYnkgcmVndWxhciBleHByZXNzaW9uJylcbiAgICAgICAgICAgIC5vcHRpb24oJy1hLCAtLWFwcCA8Y29tbWFuZD4nLCAnZXhlY3V0ZSBhIHNoZWxsIGNvbW1hbmQgb24gc3RhcnR1cCB0byBsYXVuY2ggYSB3ZWIgYXBwbGljYXRpb24gb3IgcGVyZm9ybSBvdGhlciBwcmVwYXJhdG9yeSB0YXNrcycpXG4gICAgICAgICAgICAub3B0aW9uKCctYywgLS1jb25jdXJyZW5jeSA8bnVtYmVyPicsICdydW4gdGVzdHMgY29uY3VycmVudGx5JylcbiAgICAgICAgICAgIC5vcHRpb24oJy1MLCAtLWxpdmUnLCAnZW5hYmxlIGxpdmUgbW9kZS4gTGl2ZSBtb2RlIHJlc3RhcnRzIHRlc3RzIHdoZW4geW91IG1ha2UgY2hhbmdlcyB0byB0ZXN0IGZpbGVzLicpXG4gICAgICAgICAgICAub3B0aW9uKCctLXRlc3QtbWV0YSA8a2V5PXZhbHVlWyxrZXkyPXZhbHVlMiwuLi5dPicsICdmaWx0ZXIgdGVzdHMgYnkgbWV0YWRhdGEnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1maXh0dXJlLW1ldGEgPGtleT12YWx1ZVssa2V5Mj12YWx1ZTIsLi4uXT4nLCAnZmlsdGVyIGZpeHR1cmVzIGJ5IG1ldGFkYXRhJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tZGVidWctb24tZmFpbCcsICdwYXVzZSB0ZXN0cyBvbiBmYWlsdXJlJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tZXhwZXJpbWVudGFsLXByb3h5bGVzcycsICdlbmFibGUgcHJveHlsZXNzIG1vZGU6IGh0dHBzOi8vdGVzdGNhZmUuaW8vZG9jdW1lbnRhdGlvbi80MDQyMzcvZ3VpZGVzL2V4cGVyaW1lbnRhbC1jYXBhYmlsaXRpZXMvcHJveHlsZXNzLW1vZGUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1hcHAtaW5pdC1kZWxheSA8bXM+JywgJ3NwZWNpZnkgeW91ciBhcHBsaWNhdGlvbmBzIGluaXRpYWxpemF0aW9uIHRpbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1zZWxlY3Rvci10aW1lb3V0IDxtcz4nLCAnc3BlY2lmeSB0aGUgbWF4aW11bSBTZWxlY3RvciByZXNvbHV0aW9uIHRpbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1hc3NlcnRpb24tdGltZW91dCA8bXM+JywgJ3NwZWNpZnkgdGhlIG1heGltdW0gQXNzZXJ0aW9uIHJlc29sdXRpb24gdGltZScpXG4gICAgICAgICAgICAub3B0aW9uKCctLXBhZ2UtbG9hZC10aW1lb3V0IDxtcz4nLCAnc3BlY2lmeSB0aGUgbWF4aW11bSB0aW1lIGJldHdlZW4gdGhlIHdpbmRvdy5sb2FkIGV2ZW50IGFuZCB0aGUgRE9NQ29udGVudExvYWRlZCBldmVudCAobXMpJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tcGFnZS1yZXF1ZXN0LXRpbWVvdXQgPG1zPicsICdzcGVjaWZ5IHRoZSBtYXhpbXVtIHBhZ2UgcmVxdWVzdCByZXNvbHV0aW9uIHRpbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1hamF4LXJlcXVlc3QtdGltZW91dCA8bXM+JywgJ3NwZWNpZnkgdGhlIG1heGltdW0gQUpBWCByZXF1ZXN0IHJlc29sdXRpb24gdGltZScpXG4gICAgICAgICAgICAub3B0aW9uKCctLWJyb3dzZXItaW5pdC10aW1lb3V0IDxtcz4nLCAnc3BlY2lmeSB0aGUgbWF4aW11bSBicm93c2VyIHN0YXJ0dXAgdGltZScpXG4gICAgICAgICAgICAub3B0aW9uKCctLXRlc3QtZXhlY3V0aW9uLXRpbWVvdXQgPG1zPicsICdzcGVjaWZ5IHRoZSBtYXhpbXVtIHRlc3QgZXhlY3V0aW9uIHRpbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1ydW4tZXhlY3V0aW9uLXRpbWVvdXQgPG1zPicsICdzcGVjaWZ5IHRoZSBtYXhpbXVtIHRlc3QgcnVuIHRpbWUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1zcGVlZCA8ZmFjdG9yPicsICdzZXQgdGVzdCBleGVjdXRpb24gc3BlZWQgKDAuMDEgLi4uIDEpJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tcG9ydHMgPHBvcnQxLHBvcnQyPicsICdzcGVjaWZ5IG5ldHdvcmsgcG9ydHMgdG8gdXNlIGR1cmluZyB0aGUgdGVzdCBydW4uIFRoZSBzZWNvbmQgcG9ydCBpcyBuZWNlc3NhcnkgdG8gYWNjZXNzIGNyb3NzLWRvbWFpbiByZXNvdXJjZXMuJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0taG9zdG5hbWUgPG5hbWU+JywgYHNwZWNpZnkgeW91ciBob3N0bmFtZS4gTmVjZXNzYXJ5IHRvIHJ1biB0ZXN0cyBpbiByZW1vdGUgYnJvd3NlcnMuYClcbiAgICAgICAgICAgIC5vcHRpb24oJy0tcHJveHkgPGhvc3Q+JywgJ3NwZWNpZnkgdGhlIHByb3h5IHNlcnZlciBob3N0bmFtZSBvciBJUCBhZGRyZXNzJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tcHJveHktYnlwYXNzIDxydWxlcz4nLCAnc3BlY2lmeSBVUkxzIHRoYXQgYnlwYXNzIHRoZSBwcm94eSBzZXJ2ZXInKVxuICAgICAgICAgICAgLm9wdGlvbignLS1zc2wgPG9wdGlvbnM+JywgJ3NwZWNpZnkgU1NMIG9wdGlvbnMgdG8gcnVuIFRlc3RDYWZlIG92ZXIgSFRUUFMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS12aWRlbyA8cGF0aD4nLCAncmVjb3JkIHZpZGVvcyBvZiB0ZXN0IHJ1bnMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS12aWRlby1vcHRpb25zIDxvcHRpb249dmFsdWVbLC4uLl0+JywgJ3NwZWNpZnkgdmlkZW8gcmVjb3JkaW5nIG9wdGlvbnMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS12aWRlby1lbmNvZGluZy1vcHRpb25zIDxvcHRpb249dmFsdWVbLC4uLl0+JywgJ3NwZWNpZnkgdmlkZW8gZW5jb2Rpbmcgb3B0aW9ucycpXG4gICAgICAgICAgICAub3B0aW9uKCctLWRldicsICdsb2cgYW5kIGRpYWdub3NlIFRlc3RDYWZlIGVycm9ycycpXG4gICAgICAgICAgICAub3B0aW9uKCctLXFyLWNvZGUnLCAnb3V0cHV0IFFSIGNvZGVzIHdpdGggVVJMcyBmb3IgcmVtb3RlIGJyb3dzZXIgY29ubmVjdGlvbnMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1zZiwgLS1zdG9wLW9uLWZpcnN0LWZhaWwnLCAnc3RvcCB0aGUgdGVzdCBydW4gaWYgYW55IHRlc3QgZmFpbHMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1jb25maWctZmlsZSA8cGF0aD4nLCAnc3BlY2lmeSBhIGN1c3RvbSBwYXRoIHRvIHRoZSB0ZXN0Y2FmZSBjb25maWd1cmF0aW9uIGZpbGUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS10cy1jb25maWctcGF0aCA8cGF0aD4nLCAnc3BlY2lmeSB0aGUgcGF0aCB0byBhIGN1c3RvbSBUeXBlU2NyaXB0IGNvbmZpZ3VyYXRpb24gZmlsZScpXG4gICAgICAgICAgICAub3B0aW9uKCctLWNzLCAtLWNsaWVudC1zY3JpcHRzIDxwYXRocz4nLCAnaW5qZWN0IGNsaWVudC1zaWRlIHNjcmlwdHMgaW50byB0aGUgcGFnZScsIHBhcnNlTGlzdCwgW10pXG4gICAgICAgICAgICAub3B0aW9uKCctLWRpc2FibGUtcGFnZS1jYWNoaW5nJywgJ2RvIG5vdCBjYWNoZSBwYWdlcycpXG4gICAgICAgICAgICAub3B0aW9uKCctLWRpc2FibGUtcGFnZS1yZWxvYWRzJywgJ2RvIG5vdCByZWxvYWQgcGFnZXMgYmV0d2VlbiB0ZXN0cycpXG4gICAgICAgICAgICAub3B0aW9uKCctLXJldHJ5LXRlc3QtcGFnZXMnLCAncmV0cnkgcGFnZSByZXF1ZXN0cyBpbiBjYXNlIG9mIGZhaWx1cmUnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1kaXNhYmxlLXNjcmVlbnNob3RzJywgJ2Rpc2FibGUgc2NyZWVuc2hvdHMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1zY3JlZW5zaG90cy1mdWxsLXBhZ2UnLCAnZW5hYmxlIGZ1bGwtcGFnZSBzY3JlZW5zaG90cycpXG4gICAgICAgICAgICAub3B0aW9uKCctLWNvbXBpbGVyLW9wdGlvbnMgPG9wdGlvbj12YWx1ZVssLi4uXT4nLCAnc3BlY2lmeSB0ZXN0IGNvbXBpbGF0aW9uIHNldHRpbmdzJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tZGlzYWJsZS1tdWx0aXBsZS13aW5kb3dzJywgJ2Rpc2FibGUgdGhlIG11bHRpLXdpbmRvdyBtb2RlJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tZGlzYWJsZS1odHRwMicsICdmb3JjZSB0aGUgcHJveHkgdG8gaXNzdWUgSFRUUC8xLjEgcmVxdWVzdHMnKVxuICAgICAgICAgICAgLm9wdGlvbignLS1jYWNoZScsICdjYWNoZSB3ZWIgYXNzZXRzIGJldHdlZW4gdGVzdCBydW5zJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tYmFzZS11cmwgPHVybD4nLCAnc2V0IHRoZSBiYXNlIHVybCBmb3IgdGhlIHRlc3QgcnVuJylcblxuICAgICAgICAgICAgLy8gTk9URTogdGhlc2Ugb3B0aW9ucyB3aWxsIGJlIGhhbmRsZWQgYnkgY2hhbGsgaW50ZXJuYWxseVxuICAgICAgICAgICAgLm9wdGlvbignLS1jb2xvcicsICdmb3JjZSBUZXN0Q2FmZSB0byBmb3JtYXQgQ0xJIG91dHB1dCB3aXRoIGNvbG9yJylcbiAgICAgICAgICAgIC5vcHRpb24oJy0tbm8tY29sb3InLCAnZGlzYWJsZSB0ZXh0IGNvbG9yIGZvcm1hdHRpbmcgaW4gdGhlIENMSScpXG5cbiAgICAgICAgICAgIC8vIE5PVEU6IFRlbXBvcmFyaWx5IGV4Y2x1ZGUgZXhwZXJpbWVudGFsIG9wdGlvbnMgZnJvbSAtLWhlbHAgb3V0cHV0XG4gICAgICAgICAgICAuYWRkT3B0aW9uKG5ldyBPcHRpb24oJy0tZXhwZXJpbWVudGFsLWRlYnVnJywgJ2VuYWJsZSBleHBlcmltZW50YWwgdGhlIGRlYnVnIG1vZGUnKS5oaWRlSGVscCgpKVxuICAgICAgICAgICAgLmFkZE9wdGlvbihuZXcgT3B0aW9uKCctLWV4cGVyaW1lbnRhbC1lc20nLCAnZW5hYmxlIGV4cGVyaW1lbnRhbCB0aGUgZXNtIG1vZGUnKS5oaWRlSGVscCgpKVxuICAgICAgICAgICAgLmFkZE9wdGlvbihuZXcgT3B0aW9uKCctLWRpc2FibGUtY3Jvc3MtZG9tYWluJywgJ2V4cGVyaW1lbnRhbCcpLmhpZGVIZWxwKCkpXG4gICAgICAgICAgICAuYWN0aW9uKChvcHRzOiBDb21tYW5kTGluZU9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9wdHMgPSBvcHRzO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGF0Y2hIZWxwT3V0cHV0IChkZWZhdWx0U3ViQ29tbWFuZDogQ29tbWFuZCk6IHZvaWQge1xuICAgICAgICAvLyBOT1RFOiBJbiB0aGUgZnV0dXJlIHZlcnNpb25zIG9mIHRoZSAnY29tbWFuZGVyJyBtb2R1bGVcbiAgICAgICAgLy8gbmVlZCB0byBpbnZlc3RpZ2F0ZSBob3cgdG8gcmVtb3ZlIHRoaXMgaGFjay5cbiAgICAgICAgKHByb2dyYW0gYXMgdW5rbm93biBhcyBDb21tYW5kKS5vdXRwdXRIZWxwID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3Qgc3RvcmVkUGFyZW50ID0gZGVmYXVsdFN1YkNvbW1hbmQucGFyZW50O1xuXG4gICAgICAgICAgICBkZWZhdWx0U3ViQ29tbWFuZC5wYXJlbnQgPSBudWxsO1xuXG4gICAgICAgICAgICBkZWZhdWx0U3ViQ29tbWFuZC5vdXRwdXRIZWxwKCk7XG5cbiAgICAgICAgICAgIGRlZmF1bHRTdWJDb21tYW5kLnBhcmVudCA9IHN0b3JlZFBhcmVudDtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jaGVja0FuZENvdW50UmVtb3RlcyAoYnJvd3Nlcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IHJlbW90ZU1hdGNoID0gYnJvd3Nlci5tYXRjaChSRU1PVEVfQUxJQVNfUkUpO1xuXG4gICAgICAgIGlmIChyZW1vdGVNYXRjaCkge1xuICAgICAgICAgICAgdGhpcy5yZW1vdGVDb3VudCArPSBwYXJzZUludChyZW1vdGVNYXRjaFsxXSwgMTApIHx8IDE7XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBfcGFyc2VGaWx0ZXJpbmdPcHRpb25zICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy50ZXN0R3JlcClcbiAgICAgICAgICAgIHRoaXMub3B0cy50ZXN0R3JlcCA9IGdldEdyZXBPcHRpb25zKCctLXRlc3QtZ3JlcCcsIHRoaXMub3B0cy50ZXN0R3JlcCBhcyBzdHJpbmcpO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdHMuZml4dHVyZUdyZXApXG4gICAgICAgICAgICB0aGlzLm9wdHMuZml4dHVyZUdyZXAgPSBnZXRHcmVwT3B0aW9ucygnLS1maXh0dXJlLWdyZXAnLCB0aGlzLm9wdHMuZml4dHVyZUdyZXAgYXMgc3RyaW5nKTtcblxuICAgICAgICBpZiAodGhpcy5vcHRzLnRlc3RNZXRhKVxuICAgICAgICAgICAgdGhpcy5vcHRzLnRlc3RNZXRhID0gYXdhaXQgZ2V0TWV0YU9wdGlvbnMoJy0tdGVzdC1tZXRhJywgdGhpcy5vcHRzLnRlc3RNZXRhIGFzIHN0cmluZyk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0cy5maXh0dXJlTWV0YSlcbiAgICAgICAgICAgIHRoaXMub3B0cy5maXh0dXJlTWV0YSA9IGF3YWl0IGdldE1ldGFPcHRpb25zKCctLWZpeHR1cmUtbWV0YScsIHRoaXMub3B0cy5maXh0dXJlTWV0YSBhcyBzdHJpbmcpO1xuXG4gICAgICAgIHRoaXMub3B0cy5maWx0ZXIgPSBnZXRGaWx0ZXJGbih0aGlzLm9wdHMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlQXBwSW5pdERlbGF5ICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5hcHBJbml0RGVsYXkpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMubm9uTmVnYXRpdmVOdW1iZXJTdHJpbmcsIG51bGwsICdUaGUgdGVzdGVkIGFwcCBpbml0aWFsaXphdGlvbiBkZWxheScsIHRoaXMub3B0cy5hcHBJbml0RGVsYXkpO1xuXG4gICAgICAgICAgICB0aGlzLm9wdHMuYXBwSW5pdERlbGF5ID0gcGFyc2VJbnQodGhpcy5vcHRzLmFwcEluaXREZWxheSBhcyBzdHJpbmcsIDEwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlU2VsZWN0b3JUaW1lb3V0ICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zZWxlY3RvclRpbWVvdXQpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMubm9uTmVnYXRpdmVOdW1iZXJTdHJpbmcsIG51bGwsICdUaGUgU2VsZWN0b3IgdGltZW91dCcsIHRoaXMub3B0cy5zZWxlY3RvclRpbWVvdXQpO1xuXG4gICAgICAgICAgICB0aGlzLm9wdHMuc2VsZWN0b3JUaW1lb3V0ID0gcGFyc2VJbnQodGhpcy5vcHRzLnNlbGVjdG9yVGltZW91dCBhcyBzdHJpbmcsIDEwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlQXNzZXJ0aW9uVGltZW91dCAoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuYXNzZXJ0aW9uVGltZW91dCkge1xuICAgICAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OZWdhdGl2ZU51bWJlclN0cmluZywgbnVsbCwgJ1RoZSBhc3NlcnRpb24gdGltZW91dCcsIHRoaXMub3B0cy5hc3NlcnRpb25UaW1lb3V0KTtcblxuICAgICAgICAgICAgdGhpcy5vcHRzLmFzc2VydGlvblRpbWVvdXQgPSBwYXJzZUludCh0aGlzLm9wdHMuYXNzZXJ0aW9uVGltZW91dCBhcyBzdHJpbmcsIDEwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlUGFnZUxvYWRUaW1lb3V0ICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5wYWdlTG9hZFRpbWVvdXQpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMubm9uTmVnYXRpdmVOdW1iZXJTdHJpbmcsIG51bGwsICdUaGUgcGFnZSBsb2FkIHRpbWVvdXQnLCB0aGlzLm9wdHMucGFnZUxvYWRUaW1lb3V0KTtcblxuICAgICAgICAgICAgdGhpcy5vcHRzLnBhZ2VMb2FkVGltZW91dCA9IHBhcnNlSW50KHRoaXMub3B0cy5wYWdlTG9hZFRpbWVvdXQgYXMgc3RyaW5nLCAxMCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIF9wYXJzZVBhZ2VSZXF1ZXN0VGltZW91dCAoKTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy5vcHRzLnBhZ2VSZXF1ZXN0VGltZW91dClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhc3NlcnRUeXBlKGlzLm5vbk5lZ2F0aXZlTnVtYmVyU3RyaW5nLCBudWxsLCAnVGhlIHBhZ2UgcmVxdWVzdCB0aW1lb3V0JywgdGhpcy5vcHRzLnBhZ2VSZXF1ZXN0VGltZW91dCk7XG5cbiAgICAgICAgdGhpcy5vcHRzLnBhZ2VSZXF1ZXN0VGltZW91dCA9IHBhcnNlSW50KHRoaXMub3B0cy5wYWdlUmVxdWVzdFRpbWVvdXQgYXMgc3RyaW5nLCAxMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGFyc2VBamF4UmVxdWVzdFRpbWVvdXQgKCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMub3B0cy5hamF4UmVxdWVzdFRpbWVvdXQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OZWdhdGl2ZU51bWJlclN0cmluZywgbnVsbCwgJ1RoZSBBSkFYIHJlcXVlc3QgdGltZW91dCcsIHRoaXMub3B0cy5hamF4UmVxdWVzdFRpbWVvdXQpO1xuXG4gICAgICAgIHRoaXMub3B0cy5hamF4UmVxdWVzdFRpbWVvdXQgPSBwYXJzZUludCh0aGlzLm9wdHMuYWpheFJlcXVlc3RUaW1lb3V0IGFzIHN0cmluZywgMTApO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlQnJvd3NlckluaXRUaW1lb3V0ICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLm9wdHMuYnJvd3NlckluaXRUaW1lb3V0KVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGFzc2VydFR5cGUoaXMubm9uTmVnYXRpdmVOdW1iZXJTdHJpbmcsIG51bGwsICdUaGUgYnJvd3NlciBpbml0aWFsaXphdGlvbiB0aW1lb3V0JywgdGhpcy5vcHRzLmJyb3dzZXJJbml0VGltZW91dCk7XG5cbiAgICAgICAgdGhpcy5vcHRzLmJyb3dzZXJJbml0VGltZW91dCA9IHBhcnNlSW50KHRoaXMub3B0cy5icm93c2VySW5pdFRpbWVvdXQgYXMgc3RyaW5nLCAxMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGFyc2VUZXN0RXhlY3V0aW9uVGltZW91dCAoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMudGVzdEV4ZWN1dGlvblRpbWVvdXQpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMubm9uTmVnYXRpdmVOdW1iZXJTdHJpbmcsIG51bGwsICdUaGUgdGVzdCBleGVjdXRpb24gdGltZW91dCcsIHRoaXMub3B0cy50ZXN0RXhlY3V0aW9uVGltZW91dCk7XG5cbiAgICAgICAgICAgIHRoaXMub3B0cy50ZXN0RXhlY3V0aW9uVGltZW91dCA9IHBhcnNlSW50KHRoaXMub3B0cy50ZXN0RXhlY3V0aW9uVGltZW91dCBhcyBzdHJpbmcsIDEwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlUnVuRXhlY3V0aW9uVGltZW91dCAoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMucnVuRXhlY3V0aW9uVGltZW91dCkge1xuICAgICAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OZWdhdGl2ZU51bWJlclN0cmluZywgbnVsbCwgJ1RoZSBydW4gZXhlY3V0aW9uIHRpbWVvdXQnLCB0aGlzLm9wdHMucnVuRXhlY3V0aW9uVGltZW91dCk7XG5cbiAgICAgICAgICAgIHRoaXMub3B0cy5ydW5FeGVjdXRpb25UaW1lb3V0ID0gcGFyc2VJbnQodGhpcy5vcHRzLnJ1bkV4ZWN1dGlvblRpbWVvdXQgYXMgc3RyaW5nLCAxMCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIF9wYXJzZVNwZWVkICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zcGVlZClcbiAgICAgICAgICAgIHRoaXMub3B0cy5zcGVlZCA9IHBhcnNlRmxvYXQodGhpcy5vcHRzLnNwZWVkIGFzIHN0cmluZyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGFyc2VDb25jdXJyZW5jeSAoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuY29uY3VycmVuY3kpXG4gICAgICAgICAgICB0aGlzLm9wdHMuY29uY3VycmVuY3kgPSBwYXJzZUludCh0aGlzLm9wdHMuY29uY3VycmVuY3kgYXMgc3RyaW5nLCAxMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfcGFyc2VRdWFyYW50aW5lT3B0aW9ucyAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMucXVhcmFudGluZU1vZGUpXG4gICAgICAgICAgICB0aGlzLm9wdHMucXVhcmFudGluZU1vZGUgPSBhd2FpdCBnZXRRdWFyYW50aW5lT3B0aW9ucygnLS1xdWFyYW50aW5lLW1vZGUnLCB0aGlzLm9wdHMucXVhcmFudGluZU1vZGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3BhcnNlU2tpcEpzRXJyb3JzT3B0aW9ucyAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuc2tpcEpzRXJyb3JzKVxuICAgICAgICAgICAgdGhpcy5vcHRzLnNraXBKc0Vycm9ycyA9IGF3YWl0IGdldFNraXBKc0Vycm9yc09wdGlvbnMoJy0tc2tpcC1qcy1lcnJvcnMnLCB0aGlzLm9wdHMuc2tpcEpzRXJyb3JzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9wYXJzZVBvcnRzICgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5wb3J0cykge1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkUG9ydHMgPSAodGhpcy5vcHRzLnBvcnRzIGFzIHN0cmluZykgLyogZXNsaW50LWRpc2FibGUtbGluZSBuby1leHRyYS1wYXJlbnMgKi9cbiAgICAgICAgICAgICAgICAuc3BsaXQoJywnKVxuICAgICAgICAgICAgICAgIC5tYXAocGFyc2VQb3J0TnVtYmVyKTtcblxuICAgICAgICAgICAgaWYgKHBhcnNlZFBvcnRzLmxlbmd0aCA8IDIpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5wb3J0c09wdGlvblJlcXVpcmVzVHdvTnVtYmVycyk7XG5cbiAgICAgICAgICAgIHRoaXMub3B0cy5wb3J0cyA9IHBhcnNlZFBvcnRzIGFzIG51bWJlcltdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGFyc2VCcm93c2Vyc0Zyb21BcmdzICgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgYnJvd3NlcnNBcmcgPSB0aGlzLnRlc3RDYWZlQ29tbWFuZC5hcmdzWzBdIHx8ICcnO1xuXG4gICAgICAgIHRoaXMub3B0cy5icm93c2VycyA9IHNwbGl0UXVvdGVkVGV4dChicm93c2Vyc0FyZywgJywnKVxuICAgICAgICAgICAgLmZpbHRlcihicm93c2VyID0+IGJyb3dzZXIgJiYgdGhpcy5fY2hlY2tBbmRDb3VudFJlbW90ZXMoYnJvd3NlcikpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBfcGFyc2VTc2xPcHRpb25zICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgaWYgKHRoaXMub3B0cy5zc2wpXG4gICAgICAgICAgICB0aGlzLm9wdHMuc3NsID0gYXdhaXQgZ2V0U1NMT3B0aW9ucyh0aGlzLm9wdHMuc3NsIGFzIHN0cmluZyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfcGFyc2VSZXBvcnRlcnMgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCByZXBvcnRlcnMgPSB0aGlzLm9wdHMucmVwb3J0ZXIgPyAodGhpcy5vcHRzLnJlcG9ydGVyIGFzIHN0cmluZykuc3BsaXQoJywnKSA6IFtdOyAvKiBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWV4dHJhLXBhcmVucyovXG5cbiAgICAgICAgdGhpcy5vcHRzLnJlcG9ydGVyID0gcmVwb3J0ZXJzLm1hcCgocmVwb3J0ZXI6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2VwYXJhdG9ySW5kZXggPSByZXBvcnRlci5pbmRleE9mKCc6Jyk7XG5cbiAgICAgICAgICAgIGlmIChzZXBhcmF0b3JJbmRleCA8IDApXG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgbmFtZTogcmVwb3J0ZXIgfTtcblxuICAgICAgICAgICAgY29uc3QgbmFtZSAgID0gcmVwb3J0ZXIuc3Vic3RyaW5nKDAsIHNlcGFyYXRvckluZGV4KTtcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IHJlcG9ydGVyLnN1YnN0cmluZyhzZXBhcmF0b3JJbmRleCArIDEpO1xuXG4gICAgICAgICAgICByZXR1cm4geyBuYW1lLCBvdXRwdXQgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcGFyc2VGaWxlTGlzdCAoKTogdm9pZCB7XG4gICAgICAgIHRoaXMub3B0cy5zcmMgPSB0aGlzLnRlc3RDYWZlQ29tbWFuZC5hcmdzLnNsaWNlKDEpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3BhcnNlU2NyZWVuc2hvdE9wdGlvbnMgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAodGhpcy5vcHRzLnNjcmVlbnNob3RzKVxuICAgICAgICAgICAgdGhpcy5vcHRzLnNjcmVlbnNob3RzID0gYXdhaXQgZ2V0U2NyZWVuc2hvdE9wdGlvbnModGhpcy5vcHRzLnNjcmVlbnNob3RzKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5vcHRzLnNjcmVlbnNob3RzID0ge307XG5cbiAgICAgICAgaWYgKCFoYXModGhpcy5vcHRzLnNjcmVlbnNob3RzLCBTQ1JFRU5TSE9UX09QVElPTl9OQU1FUy5wYXRoUGF0dGVybikgJiYgdGhpcy5vcHRzLnNjcmVlbnNob3RQYXRoUGF0dGVybilcbiAgICAgICAgICAgIHRoaXMub3B0cy5zY3JlZW5zaG90c1tTQ1JFRU5TSE9UX09QVElPTl9OQU1FUy5wYXRoUGF0dGVybl0gPSB0aGlzLm9wdHMuc2NyZWVuc2hvdFBhdGhQYXR0ZXJuO1xuXG4gICAgICAgIGlmICghaGFzKHRoaXMub3B0cy5zY3JlZW5zaG90cywgU0NSRUVOU0hPVF9PUFRJT05fTkFNRVMudGFrZU9uRmFpbHMpICYmIHRoaXMub3B0cy5zY3JlZW5zaG90c09uRmFpbHMpXG4gICAgICAgICAgICB0aGlzLm9wdHMuc2NyZWVuc2hvdHNbU0NSRUVOU0hPVF9PUFRJT05fTkFNRVMudGFrZU9uRmFpbHNdID0gdGhpcy5vcHRzLnNjcmVlbnNob3RzT25GYWlscztcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9wYXJzZVZpZGVvT3B0aW9ucyAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMudmlkZW9PcHRpb25zKVxuICAgICAgICAgICAgdGhpcy5vcHRzLnZpZGVvT3B0aW9ucyA9IGF3YWl0IGdldFZpZGVvT3B0aW9ucyh0aGlzLm9wdHMudmlkZW9PcHRpb25zIGFzIHN0cmluZyk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0cy52aWRlb0VuY29kaW5nT3B0aW9ucylcbiAgICAgICAgICAgIHRoaXMub3B0cy52aWRlb0VuY29kaW5nT3B0aW9ucyA9IGF3YWl0IGdldFZpZGVvT3B0aW9ucyh0aGlzLm9wdHMudmlkZW9FbmNvZGluZ09wdGlvbnMgYXMgc3RyaW5nKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9wYXJzZUNvbXBpbGVyT3B0aW9ucyAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghdGhpcy5vcHRzLmNvbXBpbGVyT3B0aW9ucylcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBwYXJzZWRDb21waWxlck9wdGlvbnMgPSBhd2FpdCBnZXRDb21waWxlck9wdGlvbnModGhpcy5vcHRzLmNvbXBpbGVyT3B0aW9ucyBhcyBzdHJpbmcpO1xuICAgICAgICBjb25zdCByZXN1bHRDb21waWxlck9wdGlvbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuXG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhcnNlZENvbXBpbGVyT3B0aW9ucykpXG4gICAgICAgICAgICBzZXQocmVzdWx0Q29tcGlsZXJPcHRpb25zLCBrZXksIHZhbHVlKTtcblxuICAgICAgICB0aGlzLm9wdHMuY29tcGlsZXJPcHRpb25zID0gcmVzdWx0Q29tcGlsZXJPcHRpb25zO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3BhcnNlRGFzaGJvYXJkT3B0aW9ucyAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLm9wdHMuZGFzaGJvYXJkT3B0aW9ucylcbiAgICAgICAgICAgIHRoaXMub3B0cy5kYXNoYm9hcmRPcHRpb25zID0gYXdhaXQgZ2V0RGFzaGJvYXJkT3B0aW9ucyh0aGlzLm9wdHMuZGFzaGJvYXJkT3B0aW9ucyBhcyBzdHJpbmcpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3BhcnNlTGlzdEJyb3dzZXJzICgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgbGlzdEJyb3dzZXJPcHRpb24gPSB0aGlzLm9wdHMubGlzdEJyb3dzZXJzO1xuXG4gICAgICAgIHRoaXMub3B0cy5saXN0QnJvd3NlcnMgPSAhIXRoaXMub3B0cy5saXN0QnJvd3NlcnM7XG5cbiAgICAgICAgaWYgKCF0aGlzLm9wdHMubGlzdEJyb3dzZXJzKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMub3B0cy5wcm92aWRlck5hbWUgPSB0eXBlb2YgbGlzdEJyb3dzZXJPcHRpb24gPT09ICdzdHJpbmcnID8gbGlzdEJyb3dzZXJPcHRpb24gOiAnbG9jYWxseS1pbnN0YWxsZWQnO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9wcmVwYXJlQm9vbGVhbk9yT2JqZWN0T3B0aW9uIChhcmd2OiBzdHJpbmdbXSwgb3B0aW9uTmFtZXM6IHN0cmluZ1tdLCBzdWJPcHRpb25zTmFtZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgICAgIC8vIE5PVEU6IG1vdmUgb3B0aW9ucyB0byB0aGUgZW5kIG9mIHRoZSBhcnJheSB0byBjb3JyZWN0bHkgcGFyc2UgYm90aCBCb29sZWFuIGFuZCBPYmplY3QgdHlwZSBhcmd1bWVudHMgKEdILTYyMzEpXG4gICAgICAgIGNvbnN0IG9wdGlvbkluZGV4ID0gYXJndi5maW5kSW5kZXgoXG4gICAgICAgICAgICBlbCA9PiBvcHRpb25OYW1lcy5zb21lKG9wdCA9PiBlbC5zdGFydHNXaXRoKG9wdCkpKTtcblxuICAgICAgICBpZiAob3B0aW9uSW5kZXggPiAtMSkge1xuICAgICAgICAgICAgY29uc3QgaXNOb3RMYXN0T3B0aW9uICAgICAgID0gb3B0aW9uSW5kZXggPCBhcmd2Lmxlbmd0aCAtIDE7XG4gICAgICAgICAgICBjb25zdCBzaG91bGRNb3ZlT3B0aW9uVG9FbmQgPSBpc05vdExhc3RPcHRpb24gJiZcbiAgICAgICAgICAgICAgICAhc3ViT3B0aW9uc05hbWVzLnNvbWUob3B0ID0+IGFyZ3Zbb3B0aW9uSW5kZXggKyAxXS5zdGFydHNXaXRoKG9wdCkpO1xuXG4gICAgICAgICAgICBpZiAoc2hvdWxkTW92ZU9wdGlvblRvRW5kKVxuICAgICAgICAgICAgICAgIGFyZ3YucHVzaChhcmd2LnNwbGljZShvcHRpb25JbmRleCwgMSlbMF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHBhcnNlIChhcmd2OiBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBDTElBcmd1bWVudFBhcnNlci5fcHJlcGFyZUJvb2xlYW5Pck9iamVjdE9wdGlvbihhcmd2LCBbJy1xJywgJy0tcXVhcmFudGluZS1tb2RlJ10sIE9iamVjdC52YWx1ZXMoUVVBUkFOVElORV9PUFRJT05fTkFNRVMpKTtcbiAgICAgICAgQ0xJQXJndW1lbnRQYXJzZXIuX3ByZXBhcmVCb29sZWFuT3JPYmplY3RPcHRpb24oYXJndiwgWyctZScsICctLXNraXAtanMtZXJyb3JzJ10sIE9iamVjdC52YWx1ZXMoU0tJUF9KU19FUlJPUlNfT1BUSU9OU19PQkpFQ1RfT1BUSU9OX05BTUVTKSk7XG5cbiAgICAgICAgY29uc3QgeyBhcmdzLCB2OEZsYWdzIH0gPSBleHRyYWN0Tm9kZVByb2Nlc3NBcmd1bWVudHMoYXJndik7XG5cbiAgICAgICAgKHByb2dyYW0gYXMgdW5rbm93biBhcyBDb21tYW5kKS5wYXJzZShhcmdzKTtcblxuICAgICAgICB0aGlzLmFyZ3MgPSAocHJvZ3JhbSBhcyB1bmtub3duIGFzIENvbW1hbmQpLmFyZ3M7XG4gICAgICAgIHRoaXMub3B0cyA9IE9iamVjdC5hc3NpZ24odGhpcy5vcHRzLCB7IHY4RmxhZ3MgfSk7XG5cbiAgICAgICAgdGhpcy5fcGFyc2VMaXN0QnJvd3NlcnMoKTtcblxuICAgICAgICAvLyBOT1RFOiB0aGUgJy0tbGlzdC1icm93c2Vycycgb3B0aW9uIG9ubHkgbGlzdHMgYnJvd3NlcnMgYW5kIGltbWVkaWF0ZWx5IGV4aXRzIHRoZSBhcHAuXG4gICAgICAgIC8vIFRoZXJlZm9yZSwgd2UgZG9uJ3QgbmVlZCB0byBwcm9jZXNzIG90aGVyIGFyZ3VtZW50cy5cbiAgICAgICAgaWYgKHRoaXMub3B0cy5saXN0QnJvd3NlcnMpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5fcGFyc2VTZWxlY3RvclRpbWVvdXQoKTtcbiAgICAgICAgdGhpcy5fcGFyc2VBc3NlcnRpb25UaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlUGFnZUxvYWRUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlUGFnZVJlcXVlc3RUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlQWpheFJlcXVlc3RUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlQnJvd3NlckluaXRUaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlVGVzdEV4ZWN1dGlvblRpbWVvdXQoKTtcbiAgICAgICAgdGhpcy5fcGFyc2VSdW5FeGVjdXRpb25UaW1lb3V0KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlQXBwSW5pdERlbGF5KCk7XG4gICAgICAgIHRoaXMuX3BhcnNlU3BlZWQoKTtcbiAgICAgICAgdGhpcy5fcGFyc2VQb3J0cygpO1xuICAgICAgICB0aGlzLl9wYXJzZUJyb3dzZXJzRnJvbUFyZ3MoKTtcbiAgICAgICAgdGhpcy5fcGFyc2VDb25jdXJyZW5jeSgpO1xuICAgICAgICB0aGlzLl9wYXJzZUZpbGVMaXN0KCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fcGFyc2VGaWx0ZXJpbmdPcHRpb25zKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3BhcnNlUXVhcmFudGluZU9wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fcGFyc2VTa2lwSnNFcnJvcnNPcHRpb25zKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3BhcnNlU2NyZWVuc2hvdE9wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fcGFyc2VWaWRlb09wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fcGFyc2VDb21waWxlck9wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fcGFyc2VTc2xPcHRpb25zKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3BhcnNlUmVwb3J0ZXJzKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3BhcnNlRGFzaGJvYXJkT3B0aW9ucygpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRSdW5PcHRpb25zICgpOiBSdW5uZXJSdW5PcHRpb25zIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuICAgICAgICBSVU5fT1BUSU9OX05BTUVTLmZvckVhY2gob3B0aW9uTmFtZSA9PiB7XG4gICAgICAgICAgICBpZiAob3B0aW9uTmFtZSBpbiB0aGlzLm9wdHMpXG4gICAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZSBhIGhhY2sgdG8gYWRkIGFuIGluZGV4IHNpZ25hdHVyZSB0byBpbnRlcmZhY2VcbiAgICAgICAgICAgICAgICByZXN1bHRbb3B0aW9uTmFtZV0gPSB0aGlzLm9wdHNbb3B0aW9uTmFtZV07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQgYXMgUnVubmVyUnVuT3B0aW9ucztcbiAgICB9XG59XG4iXX0=
|