@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
283 lines • 40.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-console */
const path = require("path");
const jest = require("jest");
const yargs = require("yargs");
const cli_npm_source_1 = require("../package-sources/cli-npm-source");
const cli_repo_source_1 = require("../package-sources/cli-repo-source");
const find_root_1 = require("../package-sources/find-root");
const library_globalinstall_source_1 = require("../package-sources/library-globalinstall-source");
const library_npm_source_1 = require("../package-sources/library-npm-source");
const library_preinstalled_source_1 = require("../package-sources/library-preinstalled-source");
const subprocess_1 = require("../package-sources/subprocess");
const CLI_PACKAGE_NAME = 'aws-cdk';
const CDK_ASSETS_PACKAGE_NAME = 'cdk-assets';
async function main() {
const args = await yargs
.command('* <SUITENAME>', 'default command', y => y
.positional('SUITENAME', {
describe: 'Name of the test suite to run',
type: 'string',
demandOption: true,
})
/////////////////////////////////////////////////////////////////////////////
// Sources and versions
.options('cli-version', {
describe: 'CLI version to use.',
alias: 'c',
type: 'string',
})
.options('cli-source', {
describe: 'Root of aws-cdk-cli repository, or "auto".',
alias: 's',
type: 'string',
})
.options('framework-version', {
describe: 'Framework version to use',
alias: 'f',
type: 'string',
})
.options('toolkit-lib-version', {
describe: 'Toolkit lib version to use',
alias: 'l',
type: 'string',
})
.options('cdk-assets-version', {
describe: 'cdk-assets version to use.',
alias: 'a',
type: 'string',
})
.option('use-source', {
descripton: 'Use TypeScript packages from the given source repository (or "auto")',
type: 'string',
requiresArg: true,
deprecated: 'Use --cli-source instead',
})
.option('use-cli-release', {
descripton: 'Run the current tests against the CLI at the given version',
alias: 'u',
type: 'string',
requiresArg: true,
deprecated: 'Use --cli-version instead',
})
.option('auto-source', {
alias: 'a',
describe: 'Automatically find the source tree from the current working directory',
type: 'boolean',
requiresArg: false,
deprecated: 'Use --use-source=auto instead',
})
/////////////////////////////////////////////////////////////////////////////
// Test running flags
.option('runInBand', {
descripton: 'Run all tests in one Node process',
alias: 'i',
type: 'boolean',
})
.option('test', {
descripton: 'Test pattern to selectively run tests',
alias: 't',
type: 'string',
requiresArg: true,
})
.option('test-file', {
describe: 'The specific test file to run',
alias: 'F',
type: 'string',
requiresArg: true,
})
.options('seed', {
describe: 'Set the seed value to replicate a test run',
type: 'string',
requiresArg: true,
})
.options('verbose', {
alias: 'v',
describe: 'Run in verbose mode',
type: 'boolean',
requiresArg: false,
})
.options('passWithNoTests', {
describe: 'Allow passing if the test suite is not found (default true when IS_CANARY mode, false otherwise)',
type: 'boolean',
requiresArg: false,
})
.options('maxWorkers', {
alias: 'w',
describe: 'Specifies the maximum number of workers the worker-pool will spawn for running tests. We use a sensible default for running cli integ tests.',
type: 'string',
requiresArg: true,
})
.options('shard', {
describe: 'The test suite shard to execute in a format of (?<shardIndex>\d+)/(?<shardCount>\d+). `shardIndex` describes which shard to select while `shardCount` controls the number of shards the suite should be split into. `shardIndex` and `shardCount` have to be 1-based, positive numbers, and `shardIndex` has to be lower than or equal to `shardCount`.',
type: 'string',
requiresArg: true,
})
.options('retry', {
describe: 'Number of times to retry failed tests.',
type: 'number',
requiresArg: true,
default: !!(process.env.CI || process.env.CODEBUILD_BUILD_ID) ? 2 : 0,
defaultDescription: '2 in CI/CodeBuild, 0 otherwise',
}), () => {
})
.strict()
.parse();
const suiteName = args.SUITENAME;
// So many ways to specify this, and with various ways to spell the same flag (o_O)
// Also, some of them depend on each other for convenience.
const cliSource = new UniqueOption('CLI version');
const cdkAssetsSource = new UniqueOption('cdk-assets version');
// Specific CLI version
for (const flagAlias of ['cli-version', 'use-cli-release']) {
if (args[flagAlias]) {
cliSource.set(new cli_npm_source_1.RunnerCliNpmSource(CLI_PACKAGE_NAME, args[flagAlias]), `--${flagAlias}`);
}
}
// Specific cdk-assets version
if (args['cdk-assets-version']) {
cdkAssetsSource.set(new cli_npm_source_1.RunnerCliNpmSource(CDK_ASSETS_PACKAGE_NAME, args['cdk-assets-version']), '--cdk-assets-version');
}
// Specifically use a source location
for (const flagAlias of ['cli-source', 'use-source']) {
if (args[flagAlias]) {
const root = args[flagAlias] === 'auto' ? await (0, find_root_1.autoFindRepoRoot)() : args[flagAlias];
cliSource.set(new cli_repo_source_1.RunnerCliRepoSource(CLI_PACKAGE_NAME, root), `--${flagAlias}`);
cdkAssetsSource.set(new cli_repo_source_1.RunnerCliRepoSource(CDK_ASSETS_PACKAGE_NAME, root), `--${flagAlias}`);
}
}
// Specifically request that a source location is given, or we didn't find a CLI yet.
// A CLI source is required, so if this fails that's alright.
if (args['auto-source'] || !cliSource.isSet()) {
cliSource.set(new cli_repo_source_1.RunnerCliRepoSource(CLI_PACKAGE_NAME, await (0, find_root_1.autoFindRepoRoot)()), '--auto-source');
}
// If the CLI is taken from the source, and cdk-assets is not set, we can copy the cdk-assets source from the CLI source.
if (!cdkAssetsSource.isSet()) {
const cliSrc = cliSource.assert();
if (cliSrc instanceof cli_repo_source_1.RunnerCliRepoSource) {
cdkAssetsSource.set(new cli_repo_source_1.RunnerCliRepoSource(CDK_ASSETS_PACKAGE_NAME, cliSrc.repoRoot), 'copied from CLI source');
}
}
// If cdk-assets is still not configured, fall back to the latest version that is available
if (!cdkAssetsSource.isSet()) {
cdkAssetsSource.set(new cli_npm_source_1.RunnerCliNpmSource(CDK_ASSETS_PACKAGE_NAME, 'latest'), '--cdk-assets-version not set');
}
// Library source is either the given one, or 'latest' (nice and simple)
const librarySource = new library_npm_source_1.RunnerLibraryNpmSource('aws-cdk-lib', args['framework-version'] ? args['framework-version'] : 'latest');
// Toolkit lib source is either the given one, or the one that's being brought by 'package.json' already, or 'latest'
const toolkitLibPackage = '@aws-cdk/toolkit-lib';
let toolkitSource;
if (args['toolkit-lib-version']) {
toolkitSource = new library_globalinstall_source_1.RunnerLibraryGlobalInstallSource(toolkitLibPackage, args['toolkit-lib-version']);
}
if (!toolkitSource) {
toolkitSource = await library_preinstalled_source_1.RunnerLibraryPreinstalledSource.isPreinstalled(toolkitLibPackage)
? new library_preinstalled_source_1.RunnerLibraryPreinstalledSource(toolkitLibPackage)
: new library_globalinstall_source_1.RunnerLibraryGlobalInstallSource(toolkitLibPackage, 'latest');
}
process.env.JEST_RETRY_TIMES = String(args.retry);
console.log('------> Configuration');
console.log(` Test suite: ${suiteName}`);
console.log(` Test version: ${thisPackageVersion()}`);
console.log(` CLI source: ${cliSource.assert().sourceDescription}`);
console.log(` Library source: ${librarySource.sourceDescription}`);
console.log(` Toolkit lib source: ${toolkitSource.sourceDescription}`);
console.log(` cdk-assets source: ${cdkAssetsSource.assert().sourceDescription}`);
console.log(` Retry: ${args.retry}`);
if (args.verbose) {
process.env.VERBOSE = '1';
}
// Motivation behind this behavior: when adding a new test suite to the pipeline, because of the way our
// Pipeline package works, the suite would be added to the pipeline AND as a canary immediately. The canary
// would fail until the package was actually released, so for canaries we make an exception so that the initial
// canary would succeed even if the suite wasn't yet available. The fact that the suite is not optional in
// the pipeline protects us from typos.
const passWithNoTests = args.passWithNoTests ?? !!process.env.IS_CANARY;
// Communicate with the config file (integ.jest.config.js)
process.env.TEST_SUITE_NAME = suiteName;
const disposables = new Array();
try {
console.log('------> Resolved versions');
const cli = await cliSource.assert().runnerPrepare();
disposables.push(cli);
console.log(` CLI: ${cli.version}`);
const library = await librarySource.runnerPrepare();
disposables.push(library);
console.log(` Library: ${library.version}`);
const toolkitLib = await toolkitSource.runnerPrepare();
disposables.push(toolkitLib);
console.log(` Toolkit library: ${toolkitLib.version}`);
const cdkAssets = await cdkAssetsSource.assert().runnerPrepare();
disposables.push(cdkAssets);
console.log(` cdk-assets: ${cdkAssets.version}`);
(0, subprocess_1.serializeSources)({
cli,
library,
toolkitLib,
cdkAssets,
});
const jestConfig = path.resolve(__dirname, '..', '..', 'resources', 'integ.jest.config.js');
// Flip a flag to indicate we're testing CDK itself. Some parts of CDK behave more thoroughly
// (but slowly) if this flag is set.
process.env.TESTING_CDK = '1';
// jest-junit reporter configuration
process.env.JEST_SUITE_NAME = 'jest tests';
process.env.JEST_JUNIT_OUTPUT_DIR = 'coverage';
await jest.run([
'--reporters=default',
'--reporters=jest-junit',
// Override Jest's default 5s timeout which is too low for integ tests.
// Tests using withAws() will further override this to 2 hours to account for region lock wait times.
'--testTimeout=60000',
'--randomize',
...args.seed ? [`--seed=${args.seed}`] : [],
...args.runInBand ? ['-i'] : [],
...args.test ? ['-t', args.test] : [],
...args.verbose ? ['--verbose'] : [],
...args.maxWorkers ? [`--maxWorkers=${args.maxWorkers}`] : [],
...passWithNoTests ? ['--passWithNoTests'] : [],
...args['test-file'] ? [args['test-file']] : [],
...args.shard ? [`--shard=${args.shard}`] : [],
], jestConfig);
}
finally {
for (const disp of disposables) {
await disp.dispose();
}
}
}
class UniqueOption {
what;
value;
source;
constructor(what) {
this.what = what;
}
isSet() {
return this.value !== undefined;
}
assert() {
if (!this.value) {
throw new Error(`${this.what} not configured`);
}
return this.value;
}
set(x, source) {
if (this.value) {
throw new Error(`${this.what}: ${source} already configured via ${this.source}`);
}
this.value = x;
this.source = source;
}
}
function thisPackageVersion() {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return require('../../package.json').version;
}
main().catch(e => {
// eslint-disable-next-line no-console
console.error(e);
process.exitCode = 1;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLXN1aXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicnVuLXN1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsK0JBQStCO0FBQy9CLDZCQUE2QjtBQUM3Qiw2QkFBNkI7QUFDN0IsK0JBQStCO0FBQy9CLHNFQUF1RTtBQUN2RSx3RUFBeUU7QUFDekUsNERBQWdFO0FBQ2hFLGtHQUFtRztBQUNuRyw4RUFBK0U7QUFDL0UsZ0dBQWlHO0FBRWpHLDhEQUFpRTtBQUVqRSxNQUFNLGdCQUFnQixHQUFHLFNBQVMsQ0FBQztBQUNuQyxNQUFNLHVCQUF1QixHQUFHLFlBQVksQ0FBQztBQUU3QyxLQUFLLFVBQVUsSUFBSTtJQUNqQixNQUFNLElBQUksR0FBRyxNQUFNLEtBQUs7U0FDckIsT0FBTyxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDaEQsVUFBVSxDQUFDLFdBQVcsRUFBRTtRQUN2QixRQUFRLEVBQUUsK0JBQStCO1FBQ3pDLElBQUksRUFBRSxRQUFRO1FBQ2QsWUFBWSxFQUFFLElBQUk7S0FDbkIsQ0FBQztRQUNGLDZFQUE2RTtRQUM3RSx3QkFBd0I7U0FDdkIsT0FBTyxDQUFDLGFBQWEsRUFBRTtRQUN0QixRQUFRLEVBQUUscUJBQXFCO1FBQy9CLEtBQUssRUFBRSxHQUFHO1FBQ1YsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDO1NBQ0QsT0FBTyxDQUFDLFlBQVksRUFBRTtRQUNyQixRQUFRLEVBQUUsNENBQTRDO1FBQ3RELEtBQUssRUFBRSxHQUFHO1FBQ1YsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDO1NBQ0QsT0FBTyxDQUFDLG1CQUFtQixFQUFFO1FBQzVCLFFBQVEsRUFBRSwwQkFBMEI7UUFDcEMsS0FBSyxFQUFFLEdBQUc7UUFDVixJQUFJLEVBQUUsUUFBUTtLQUNmLENBQUM7U0FDRCxPQUFPLENBQUMscUJBQXFCLEVBQUU7UUFDOUIsUUFBUSxFQUFFLDRCQUE0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R0FBRyxJQUFJLENBQUMsSUFBSSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVNLEdBQUcsQ0FBQyxDQUFJLEVBQUUsTUFBYztRQUM3QixJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU0sMkJBQTJCLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ25GLENBQUM7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7Q0FDRjtBQUVELFNBQVMsa0JBQWtCO0lBQ3pCLGlFQUFpRTtJQUNqRSxPQUFPLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztBQUMvQyxDQUFDO0FBRUQsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO0lBQ2Ysc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakIsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7QUFDdkIsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgamVzdCBmcm9tICdqZXN0JztcbmltcG9ydCAqIGFzIHlhcmdzIGZyb20gJ3lhcmdzJztcbmltcG9ydCB7IFJ1bm5lckNsaU5wbVNvdXJjZSB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9jbGktbnBtLXNvdXJjZSc7XG5pbXBvcnQgeyBSdW5uZXJDbGlSZXBvU291cmNlIH0gZnJvbSAnLi4vcGFja2FnZS1zb3VyY2VzL2NsaS1yZXBvLXNvdXJjZSc7XG5pbXBvcnQgeyBhdXRvRmluZFJlcG9Sb290IH0gZnJvbSAnLi4vcGFja2FnZS1zb3VyY2VzL2ZpbmQtcm9vdCc7XG5pbXBvcnQgeyBSdW5uZXJMaWJyYXJ5R2xvYmFsSW5zdGFsbFNvdXJjZSB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9saWJyYXJ5LWdsb2JhbGluc3RhbGwtc291cmNlJztcbmltcG9ydCB7IFJ1bm5lckxpYnJhcnlOcG1Tb3VyY2UgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvbGlicmFyeS1ucG0tc291cmNlJztcbmltcG9ydCB7IFJ1bm5lckxpYnJhcnlQcmVpbnN0YWxsZWRTb3VyY2UgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvbGlicmFyeS1wcmVpbnN0YWxsZWQtc291cmNlJztcbmltcG9ydCB0eXBlIHsgSVJ1bm5lclNvdXJjZSwgSVRlc3RDbGlTb3VyY2UsIElUZXN0TGlicmFyeVNvdXJjZSB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9zb3VyY2UnO1xuaW1wb3J0IHsgc2VyaWFsaXplU291cmNlcyB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9zdWJwcm9jZXNzJztcblxuY29uc3QgQ0xJX1BBQ0tBR0VfTkFNRSA9ICdhd3MtY2RrJztcbmNvbnN0IENES19BU1NFVFNfUEFDS0FHRV9OQU1FID0gJ2Nkay1hc3NldHMnO1xuXG5hc3luYyBmdW5jdGlvbiBtYWluKCkge1xuICBjb25zdCBhcmdzID0gYXdhaXQgeWFyZ3NcbiAgICAuY29tbWFuZCgnKiA8U1VJVEVOQU1FPicsICdkZWZhdWx0IGNvbW1hbmQnLCB5ID0+IHlcbiAgICAgIC5wb3NpdGlvbmFsKCdTVUlURU5BTUUnLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnTmFtZSBvZiB0aGUgdGVzdCBzdWl0ZSB0byBydW4nLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgZGVtYW5kT3B0aW9uOiB0cnVlLFxuICAgICAgfSlcbiAgICAgIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgICAvLyAgU291cmNlcyBhbmQgdmVyc2lvbnNcbiAgICAgIC5vcHRpb25zKCdjbGktdmVyc2lvbicsIHtcbiAgICAgICAgZGVzY3JpYmU6ICdDTEkgdmVyc2lvbiB0byB1c2UuJyxcbiAgICAgICAgYWxpYXM6ICdjJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ2NsaS1zb3VyY2UnLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnUm9vdCBvZiBhd3MtY2RrLWNsaSByZXBvc2l0b3J5LCBvciBcImF1dG9cIi4nLFxuICAgICAgICBhbGlhczogJ3MnLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9ucygnZnJhbWV3b3JrLXZlcnNpb24nLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnRnJhbWV3b3JrIHZlcnNpb24gdG8gdXNlJyxcbiAgICAgICAgYWxpYXM6ICdmJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3Rvb2xraXQtbGliLXZlcnNpb24nLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnVG9vbGtpdCBsaWIgdmVyc2lvbiB0byB1c2UnLFxuICAgICAgICBhbGlhczogJ2wnLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9ucygnY2RrLWFzc2V0cy12ZXJzaW9uJywge1xuICAgICAgICBkZXNjcmliZTogJ2Nkay1hc3NldHMgdmVyc2lvbiB0byB1c2UuJyxcbiAgICAgICAgYWxpYXM6ICdhJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbigndXNlLXNvdXJjZScsIHtcbiAgICAgICAgZGVzY3JpcHRvbjogJ1VzZSBUeXBlU2NyaXB0IHBhY2thZ2VzIGZyb20gdGhlIGdpdmVuIHNvdXJjZSByZXBvc2l0b3J5IChvciBcImF1dG9cIiknLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICAgIGRlcHJlY2F0ZWQ6ICdVc2UgLS1jbGktc291cmNlIGluc3RlYWQnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3VzZS1jbGktcmVsZWFzZScsIHtcbiAgICAgICAgZGVzY3JpcHRvbjogJ1J1biB0aGUgY3VycmVudCB0ZXN0cyBhZ2FpbnN0IHRoZSBDTEkgYXQgdGhlIGdpdmVuIHZlcnNpb24nLFxuICAgICAgICBhbGlhczogJ3UnLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICAgIGRlcHJlY2F0ZWQ6ICdVc2UgLS1jbGktdmVyc2lvbiBpbnN0ZWFkJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCdhdXRvLXNvdXJjZScsIHtcbiAgICAgICAgYWxpYXM6ICdhJyxcbiAgICAgICAgZGVzY3JpYmU6ICdBdXRvbWF0aWNhbGx5IGZpbmQgdGhlIHNvdXJjZSB0cmVlIGZyb20gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnknLFxuICAgICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICAgIHJlcXVpcmVzQXJnOiBmYWxzZSxcbiAgICAgICAgZGVwcmVjYXRlZDogJ1VzZSAtLXVzZS1zb3VyY2U9YXV0byBpbnN0ZWFkJyxcbiAgICAgIH0pXG4gICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgLy8gIFRlc3QgcnVubmluZyBmbGFnc1xuICAgICAgLm9wdGlvbigncnVuSW5CYW5kJywge1xuICAgICAgICBkZXNjcmlwdG9uOiAnUnVuIGFsbCB0ZXN0cyBpbiBvbmUgTm9kZSBwcm9jZXNzJyxcbiAgICAgICAgYWxpYXM6ICdpJyxcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3Rlc3QnLCB7XG4gICAgICAgIGRlc2NyaXB0b246ICdUZXN0IHBhdHRlcm4gdG8gc2VsZWN0aXZlbHkgcnVuIHRlc3RzJyxcbiAgICAgICAgYWxpYXM6ICd0JyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3Rlc3QtZmlsZScsIHtcbiAgICAgICAgZGVzY3JpYmU6ICdUaGUgc3BlY2lmaWMgdGVzdCBmaWxlIHRvIHJ1bicsXG4gICAgICAgIGFsaWFzOiAnRicsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICByZXF1aXJlc0FyZzogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9ucygnc2VlZCcsIHtcbiAgICAgICAgZGVzY3JpYmU6ICdTZXQgdGhlIHNlZWQgdmFsdWUgdG8gcmVwbGljYXRlIGEgdGVzdCBydW4nLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3ZlcmJvc2UnLCB7XG4gICAgICAgIGFsaWFzOiAndicsXG4gICAgICAgIGRlc2NyaWJlOiAnUnVuIGluIHZlcmJvc2UgbW9kZScsXG4gICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IGZhbHNlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCdwYXNzV2l0aE5vVGVzdHMnLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnQWxsb3cgcGFzc2luZyBpZiB0aGUgdGVzdCBzdWl0ZSBpcyBub3QgZm91bmQgKGRlZmF1bHQgdHJ1ZSB3aGVuIElTX0NBTkFSWSBtb2RlLCBmYWxzZSBvdGhlcndpc2UpJyxcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICByZXF1aXJlc0FyZzogZmFsc2UsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ21heFdvcmtlcnMnLCB7XG4gICAgICAgIGFsaWFzOiAndycsXG4gICAgICAgIGRlc2NyaWJlOiAnU3BlY2lmaWVzIHRoZSBtYXhpbXVtIG51bWJlciBvZiB3b3JrZXJzIHRoZSB3b3JrZXItcG9vbCB3aWxsIHNwYXduIGZvciBydW5uaW5nIHRlc3RzLiBXZSB1c2UgYSBzZW5zaWJsZSBkZWZhdWx0IGZvciBydW5uaW5nIGNsaSBpbnRlZyB0ZXN0cy4nLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3NoYXJkJywge1xuICAgICAgICBkZXNjcmliZTogJ1RoZSB0ZXN0IHN1aXRlIHNoYXJkIHRvIGV4ZWN1dGUgaW4gYSBmb3JtYXQgb2YgKD88c2hhcmRJbmRleD5cXGQrKS8oPzxzaGFyZENvdW50PlxcZCspLiBgc2hhcmRJbmRleGAgZGVzY3JpYmVzIHdoaWNoIHNoYXJkIHRvIHNlbGVjdCB3aGlsZSBgc2hhcmRDb3VudGAgY29udHJvbHMgdGhlIG51bWJlciBvZiBzaGFyZHMgdGhlIHN1aXRlIHNob3VsZCBiZSBzcGxpdCBpbnRvLiBgc2hhcmRJbmRleGAgYW5kIGBzaGFyZENvdW50YCBoYXZlIHRvIGJlIDEtYmFzZWQsIHBvc2l0aXZlIG51bWJlcnMsIGFuZCBgc2hhcmRJbmRleGAgaGFzIHRvIGJlIGxvd2VyIHRoYW4gb3IgZXF1YWwgdG8gYHNoYXJkQ291bnRgLicsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICByZXF1aXJlc0FyZzogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9ucygncmV0cnknLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnTnVtYmVyIG9mIHRpbWVzIHRvIHJldHJ5IGZhaWxlZCB0ZXN0cy4nLFxuICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICAgIGRlZmF1bHQ6ICEhKHByb2Nlc3MuZW52LkNJIHx8IHByb2Nlc3MuZW52LkNPREVCVUlMRF9CVUlMRF9JRCkgPyAyIDogMCxcbiAgICAgICAgZGVmYXVsdERlc2NyaXB0aW9uOiAnMiBpbiBDSS9Db2RlQnVpbGQsIDAgb3RoZXJ3aXNlJyxcbiAgICAgIH0pLCAoKSA9PiB7XG4gICAgfSxcbiAgICApXG4gICAgLnN0cmljdCgpXG4gICAgLnBhcnNlKCk7XG5cbiAgY29uc3Qgc3VpdGVOYW1lID0gYXJncy5TVUlURU5BTUU7XG5cbiAgLy8gU28gbWFueSB3YXlzIHRvIHNwZWNpZnkgdGhpcywgYW5kIHdpdGggdmFyaW91cyB3YXlzIHRvIHNwZWxsIHRoZSBzYW1lIGZsYWcgKG9fTylcbiAgLy8gQWxzbywgc29tZSBvZiB0aGVtIGRlcGVuZCBvbiBlYWNoIG90aGVyIGZvciBjb252ZW5pZW5jZS5cbiAgY29uc3QgY2xpU291cmNlID0gbmV3IFVuaXF1ZU9wdGlvbjxJUnVubmVyU291cmNlPElUZXN0Q2xpU291cmNlPj4oJ0NMSSB2ZXJzaW9uJyk7XG4gIGNvbnN0IGNka0Fzc2V0c1NvdXJjZSA9IG5ldyBVbmlxdWVPcHRpb248SVJ1bm5lclNvdXJjZTxJVGVzdENsaVNvdXJjZT4+KCdjZGstYXNzZXRzIHZlcnNpb24nKTtcblxuICAvLyBTcGVjaWZpYyBDTEkgdmVyc2lvblxuICBmb3IgKGNvbnN0IGZsYWdBbGlhcyBvZiBbJ2NsaS12ZXJzaW9uJywgJ3VzZS1jbGktcmVsZWFzZSddIGFzIGNvbnN0KSB7XG4gICAgaWYgKGFyZ3NbZmxhZ0FsaWFzXSkge1xuICAgICAgY2xpU291cmNlLnNldChuZXcgUnVubmVyQ2xpTnBtU291cmNlKENMSV9QQUNLQUdFX05BTUUsIGFyZ3NbZmxhZ0FsaWFzXSksIGAtLSR7ZmxhZ0FsaWFzfWApO1xuICAgIH1cbiAgfVxuXG4gIC8vIFNwZWNpZmljIGNkay1hc3NldHMgdmVyc2lvblxuICBpZiAoYXJnc1snY2RrLWFzc2V0cy12ZXJzaW9uJ10pIHtcbiAgICBjZGtBc3NldHNTb3VyY2Uuc2V0KG5ldyBSdW5uZXJDbGlOcG1Tb3VyY2UoQ0RLX0FTU0VUU19QQUNLQUdFX05BTUUsIGFyZ3NbJ2Nkay1hc3NldHMtdmVyc2lvbiddKSwgJy0tY2RrLWFzc2V0cy12ZXJzaW9uJyk7XG4gIH1cblxuICAvLyBTcGVjaWZpY2FsbHkgdXNlIGEgc291cmNlIGxvY2F0aW9uXG4gIGZvciAoY29uc3QgZmxhZ0FsaWFzIG9mIFsnY2xpLXNvdXJjZScsICd1c2Utc291cmNlJ10gYXMgY29uc3QpIHtcbiAgICBpZiAoYXJnc1tmbGFnQWxpYXNdKSB7XG4gICAgICBjb25zdCByb290ID0gYXJnc1tmbGFnQWxpYXNdID09PSAnYXV0bycgPyBhd2FpdCBhdXRvRmluZFJlcG9Sb290KCkgOiBhcmdzW2ZsYWdBbGlhc107XG4gICAgICBjbGlTb3VyY2Uuc2V0KG5ldyBSdW5uZXJDbGlSZXBvU291cmNlKENMSV9QQUNLQUdFX05BTUUsIHJvb3QpLCBgLS0ke2ZsYWdBbGlhc31gKTtcbiAgICAgIGNka0Fzc2V0c1NvdXJjZS5zZXQobmV3IFJ1bm5lckNsaVJlcG9Tb3VyY2UoQ0RLX0FTU0VUU19QQUNLQUdFX05BTUUsIHJvb3QpLCBgLS0ke2ZsYWdBbGlhc31gKTtcbiAgICB9XG4gIH1cblxuICAvLyBTcGVjaWZpY2FsbHkgcmVxdWVzdCB0aGF0IGEgc291cmNlIGxvY2F0aW9uIGlzIGdpdmVuLCBvciB3ZSBkaWRuJ3QgZmluZCBhIENMSSB5ZXQuXG4gIC8vIEEgQ0xJIHNvdXJjZSBpcyByZXF1aXJlZCwgc28gaWYgdGhpcyBmYWlscyB0aGF0J3MgYWxyaWdodC5cbiAgaWYgKGFyZ3NbJ2F1dG8tc291cmNlJ10gfHwgIWNsaVNvdXJjZS5pc1NldCgpKSB7XG4gICAgY2xpU291cmNlLnNldChuZXcgUnVubmVyQ2xpUmVwb1NvdXJjZShDTElfUEFDS0FHRV9OQU1FLCBhd2FpdCBhdXRvRmluZFJlcG9Sb290KCkpLCAnLS1hdXRvLXNvdXJjZScpO1xuICB9XG5cbiAgLy8gSWYgdGhlIENMSSBpcyB0YWtlbiBmcm9tIHRoZSBzb3VyY2UsIGFuZCBjZGstYXNzZXRzIGlzIG5vdCBzZXQsIHdlIGNhbiBjb3B5IHRoZSBjZGstYXNzZXRzIHNvdXJjZSBmcm9tIHRoZSBDTEkgc291cmNlLlxuICBpZiAoIWNka0Fzc2V0c1NvdXJjZS5pc1NldCgpKSB7XG4gICAgY29uc3QgY2xpU3JjID0gY2xpU291cmNlLmFzc2VydCgpO1xuICAgIGlmIChjbGlTcmMgaW5zdGFuY2VvZiBSdW5uZXJDbGlSZXBvU291cmNlKSB7XG4gICAgICBjZGtBc3NldHNTb3VyY2Uuc2V0KG5ldyBSdW5uZXJDbGlSZXBvU291cmNlKENES19BU1NFVFNfUEFDS0FHRV9OQU1FLCBjbGlTcmMucmVwb1Jvb3QpLCAnY29waWVkIGZyb20gQ0xJIHNvdXJjZScpO1xuICAgIH1cbiAgfVxuXG4gIC8vIElmIGNkay1hc3NldHMgaXMgc3RpbGwgbm90IGNvbmZpZ3VyZWQsIGZhbGwgYmFjayB0byB0aGUgbGF0ZXN0IHZlcnNpb24gdGhhdCBpcyBhdmFpbGFibGVcbiAgaWYgKCFjZGtBc3NldHNTb3VyY2UuaXNTZXQoKSkge1xuICAgIGNka0Fzc2V0c1NvdXJjZS5zZXQobmV3IFJ1bm5lckNsaU5wbVNvdXJjZShDREtfQVNTRVRTX1BBQ0tBR0VfTkFNRSwgJ2xhdGVzdCcpLCAnLS1jZGstYXNzZXRzLXZlcnNpb24gbm90IHNldCcpO1xuICB9XG5cbiAgLy8gTGlicmFyeSBzb3VyY2UgaXMgZWl0aGVyIHRoZSBnaXZlbiBvbmUsIG9yICdsYXRlc3QnIChuaWNlIGFuZCBzaW1wbGUpXG4gIGNvbnN0IGxpYnJhcnlTb3VyY2U6IElSdW5uZXJTb3VyY2U8SVRlc3RMaWJyYXJ5U291cmNlPlxuICAgID0gbmV3IFJ1bm5lckxpYnJhcnlOcG1Tb3VyY2UoJ2F3cy1jZGstbGliJywgYXJnc1snZnJhbWV3b3JrLXZlcnNpb24nXSA/IGFyZ3NbJ2ZyYW1ld29yay12ZXJzaW9uJ10gOiAnbGF0ZXN0Jyk7XG5cbiAgLy8gVG9vbGtpdCBsaWIgc291cmNlIGlzIGVpdGhlciB0aGUgZ2l2ZW4gb25lLCBvciB0aGUgb25lIHRoYXQncyBiZWluZyBicm91Z2h0IGJ5ICdwYWNrYWdlLmpzb24nIGFscmVhZHksIG9yICdsYXRlc3QnXG4gIGNvbnN0IHRvb2xraXRMaWJQYWNrYWdlID0gJ0Bhd3MtY2RrL3Rvb2xraXQtbGliJztcbiAgbGV0IHRvb2xraXRTb3VyY2U6IElSdW5uZXJTb3VyY2U8SVRlc3RMaWJyYXJ5U291cmNlPiB8IHVuZGVmaW5lZDtcbiAgaWYgKGFyZ3NbJ3Rvb2xraXQtbGliLXZlcnNpb24nXSkge1xuICAgIHRvb2xraXRTb3VyY2UgPSBuZXcgUnVubmVyTGlicmFyeUdsb2JhbEluc3RhbGxTb3VyY2UodG9vbGtpdExpYlBhY2thZ2UsIGFyZ3NbJ3Rvb2xraXQtbGliLXZlcnNpb24nXSk7XG4gIH1cbiAgaWYgKCF0b29sa2l0U291cmNlKSB7XG4gICAgdG9vbGtpdFNvdXJjZSA9IGF3YWl0IFJ1bm5lckxpYnJhcnlQcmVpbnN0YWxsZWRTb3VyY2UuaXNQcmVpbnN0YWxsZWQodG9vbGtpdExpYlBhY2thZ2UpXG4gICAgICA/IG5ldyBSdW5uZXJMaWJyYXJ5UHJlaW5zdGFsbGVkU291cmNlKHRvb2xraXRMaWJQYWNrYWdlKVxuICAgICAgOiBuZXcgUnVubmVyTGlicmFyeUdsb2JhbEluc3RhbGxTb3VyY2UodG9vbGtpdExpYlBhY2thZ2UsICdsYXRlc3QnKTtcbiAgfVxuXG4gIHByb2Nlc3MuZW52LkpFU1RfUkVUUllfVElNRVMgPSBTdHJpbmcoYXJncy5yZXRyeSk7XG5cbiAgY29uc29sZS5sb2coJy0tLS0tLT4gQ29uZmlndXJhdGlvbicpO1xuICBjb25zb2xlLmxvZyhgICAgICAgICBUZXN0IHN1aXRlOiAgICAgICAgICR7c3VpdGVOYW1lfWApO1xuICBjb25zb2xlLmxvZyhgICAgICAgICBUZXN0IHZlcnNpb246ICAgICAgICR7dGhpc1BhY2thZ2VWZXJzaW9uKCl9YCk7XG4gIGNvbnNvbGUubG9nKGAgICAgICAgIENMSSBzb3VyY2U6ICAgICAgICAgJHtjbGlTb3VyY2UuYXNzZXJ0KCkuc291cmNlRGVzY3JpcHRpb259YCk7XG4gIGNvbnNvbGUubG9nKGAgICAgICAgIExpYnJhcnkgc291cmNlOiAgICAgJHtsaWJyYXJ5U291cmNlLnNvdXJjZURlc2NyaXB0aW9ufWApO1xuICBjb25zb2xlLmxvZyhgICAgICAgICBUb29sa2l0IGxpYiBzb3VyY2U6ICR7dG9vbGtpdFNvdXJjZS5zb3VyY2VEZXNjcmlwdGlvbn1gKTtcbiAgY29uc29sZS5sb2coYCAgICAgICAgY2RrLWFzc2V0cyBzb3VyY2U6ICAke2Nka0Fzc2V0c1NvdXJjZS5hc3NlcnQoKS5zb3VyY2VEZXNjcmlwdGlvbn1gKTtcbiAgY29uc29sZS5sb2coYCAgICAgICAgUmV0cnk6ICAgICAgICAgICAgICAke2FyZ3MucmV0cnl9YCk7XG5cbiAgaWYgKGFyZ3MudmVyYm9zZSkge1xuICAgIHByb2Nlc3MuZW52LlZFUkJPU0UgPSAnMSc7XG4gIH1cblxuICAvLyBNb3RpdmF0aW9uIGJlaGluZCB0aGlzIGJlaGF2aW9yOiB3aGVuIGFkZGluZyBhIG5ldyB0ZXN0IHN1aXRlIHRvIHRoZSBwaXBlbGluZSwgYmVjYXVzZSBvZiB0aGUgd2F5IG91clxuICAvLyBQaXBlbGluZSBwYWNrYWdlIHdvcmtzLCB0aGUgc3VpdGUgd291bGQgYmUgYWRkZWQgdG8gdGhlIHBpcGVsaW5lIEFORCBhcyBhIGNhbmFyeSBpbW1lZGlhdGVseS4gVGhlIGNhbmFyeVxuICAvLyB3b3VsZCBmYWlsIHVudGlsIHRoZSBwYWNrYWdlIHdhcyBhY3R1YWxseSByZWxlYXNlZCwgc28gZm9yIGNhbmFyaWVzIHdlIG1ha2UgYW4gZXhjZXB0aW9uIHNvIHRoYXQgdGhlIGluaXRpYWxcbiAgLy8gY2FuYXJ5IHdvdWxkIHN1Y2NlZWQgZXZlbiBpZiB0aGUgc3VpdGUgd2Fzbid0IHlldCBhdmFpbGFibGUuIFRoZSBmYWN0IHRoYXQgdGhlIHN1aXRlIGlzIG5vdCBvcHRpb25hbCBpblxuICAvLyB0aGUgcGlwZWxpbmUgcHJvdGVjdHMgdXMgZnJvbSB0eXBvcy5cbiAgY29uc3QgcGFzc1dpdGhOb1Rlc3RzID0gYXJncy5wYXNzV2l0aE5vVGVzdHMgPz8gISFwcm9jZXNzLmVudi5JU19DQU5BUlk7XG5cbiAgLy8gQ29tbXVuaWNhdGUgd2l0aCB0aGUgY29uZmlnIGZpbGUgKGludGVnLmplc3QuY29uZmlnLmpzKVxuICBwcm9jZXNzLmVudi5URVNUX1NVSVRFX05BTUUgPSBzdWl0ZU5hbWU7XG5cbiAgY29uc3QgZGlzcG9zYWJsZXMgPSBuZXcgQXJyYXk8eyBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD4gfT4oKTtcbiAgdHJ5IHtcbiAgICBjb25zb2xlLmxvZygnLS0tLS0tPiBSZXNvbHZlZCB2ZXJzaW9ucycpO1xuICAgIGNvbnN0IGNsaSA9IGF3YWl0IGNsaVNvdXJjZS5hc3NlcnQoKS5ydW5uZXJQcmVwYXJlKCk7XG4gICAgZGlzcG9zYWJsZXMucHVzaChjbGkpO1xuICAgIGNvbnNvbGUubG9nKGAgICAgICAgIENMSTogICAgICAgICAgICAgJHtjbGkudmVyc2lvbn1gKTtcblxuICAgIGNvbnN0IGxpYnJhcnkgPSBhd2FpdCBsaWJyYXJ5U291cmNlLnJ1bm5lclByZXBhcmUoKTtcbiAgICBkaXNwb3NhYmxlcy5wdXNoKGxpYnJhcnkpO1xuICAgIGNvbnNvbGUubG9nKGAgICAgICAgIExpYnJhcnk6ICAgICAgICAgJHtsaWJyYXJ5LnZlcnNpb259YCk7XG5cbiAgICBjb25zdCB0b29sa2l0TGliID0gYXdhaXQgdG9vbGtpdFNvdXJjZS5ydW5uZXJQcmVwYXJlKCk7XG4gICAgZGlzcG9zYWJsZXMucHVzaCh0b29sa2l0TGliKTtcbiAgICBjb25zb2xlLmxvZyhgICAgICAgICBUb29sa2l0IGxpYnJhcnk6ICR7dG9vbGtpdExpYi52ZXJzaW9ufWApO1xuXG4gICAgY29uc3QgY2RrQXNzZXRzID0gYXdhaXQgY2RrQXNzZXRzU291cmNlLmFzc2VydCgpLnJ1bm5lclByZXBhcmUoKTtcbiAgICBkaXNwb3NhYmxlcy5wdXNoKGNka0Fzc2V0cyk7XG4gICAgY29uc29sZS5sb2coYCAgICAgICAgY2RrLWFzc2V0czogICAgICAke2Nka0Fzc2V0cy52ZXJzaW9ufWApO1xuXG4gICAgc2VyaWFsaXplU291cmNlcyh7XG4gICAgICBjbGksXG4gICAgICBsaWJyYXJ5LFxuICAgICAgdG9vbGtpdExpYixcbiAgICAgIGNka0Fzc2V0cyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGplc3RDb25maWcgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAncmVzb3VyY2VzJywgJ2ludGVnLmplc3QuY29uZmlnLmpzJyk7XG5cbiAgICAvLyBGbGlwIGEgZmxhZyB0byBpbmRpY2F0ZSB3ZSdyZSB0ZXN0aW5nIENESyBpdHNlbGYuIFNvbWUgcGFydHMgb2YgQ0RLIGJlaGF2ZSBtb3JlIHRob3JvdWdobHlcbiAgICAvLyAoYnV0IHNsb3dseSkgaWYgdGhpcyBmbGFnIGlzIHNldC5cbiAgICBwcm9jZXNzLmVudi5URVNUSU5HX0NESyA9ICcxJztcblxuICAgIC8vIGplc3QtanVuaXQgcmVwb3J0ZXIgY29uZmlndXJhdGlvblxuICAgIHByb2Nlc3MuZW52LkpFU1RfU1VJVEVfTkFNRSA9ICdqZXN0IHRlc3RzJztcbiAgICBwcm9jZXNzLmVudi5KRVNUX0pVTklUX09VVFBVVF9ESVIgPSAnY292ZXJhZ2UnO1xuXG4gICAgYXdhaXQgamVzdC5ydW4oW1xuICAgICAgJy0tcmVwb3J0ZXJzPWRlZmF1bHQnLFxuICAgICAgJy0tcmVwb3J0ZXJzPWplc3QtanVuaXQnLFxuICAgICAgLy8gT3ZlcnJpZGUgSmVzdCdzIGRlZmF1bHQgNXMgdGltZW91dCB3aGljaCBpcyB0b28gbG93IGZvciBpbnRlZyB0ZXN0cy5cbiAgICAgIC8vIFRlc3RzIHVzaW5nIHdpdGhBd3MoKSB3aWxsIGZ1cnRoZXIgb3ZlcnJpZGUgdGhpcyB0byAyIGhvdXJzIHRvIGFjY291bnQgZm9yIHJlZ2lvbiBsb2NrIHdhaXQgdGltZXMuXG4gICAgICAnLS10ZXN0VGltZW91dD02MDAwMCcsXG4gICAgICAnLS1yYW5kb21pemUnLFxuICAgICAgLi4uYXJncy5zZWVkID8gW2AtLXNlZWQ9JHthcmdzLnNlZWR9YF0gOiBbXSxcbiAgICAgIC4uLmFyZ3MucnVuSW5CYW5kID8gWyctaSddIDogW10sXG4gICAgICAuLi5hcmdzLnRlc3QgPyBbJy10JywgYXJncy50ZXN0XSA6IFtdLFxuICAgICAgLi4uYXJncy52ZXJib3NlID8gWyctLXZlcmJvc2UnXSA6IFtdLFxuICAgICAgLi4uYXJncy5tYXhXb3JrZXJzID8gW2AtLW1heFdvcmtlcnM9JHthcmdzLm1heFdvcmtlcnN9YF0gOiBbXSxcbiAgICAgIC4uLnBhc3NXaXRoTm9UZXN0cyA/IFsnLS1wYXNzV2l0aE5vVGVzdHMnXSA6IFtdLFxuICAgICAgLi4uYXJnc1sndGVzdC1maWxlJ10gPyBbYXJnc1sndGVzdC1maWxlJ11dIDogW10sXG4gICAgICAuLi5hcmdzLnNoYXJkID8gW2AtLXNoYXJkPSR7YXJncy5zaGFyZH1gXSA6IFtdLFxuICAgIF0sIGplc3RDb25maWcpO1xuICB9IGZpbmFsbHkge1xuICAgIGZvciAoY29uc3QgZGlzcCBvZiBkaXNwb3NhYmxlcykge1xuICAgICAgYXdhaXQgZGlzcC5kaXNwb3NlKCk7XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIFVuaXF1ZU9wdGlvbjxBPiB7XG4gIHB1YmxpYyB2YWx1ZTogQSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBzb3VyY2U6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHdoYXQ6IHN0cmluZykge1xuICB9XG5cbiAgcHVibGljIGlzU2V0KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlICE9PSB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgYXNzZXJ0KCk6IEEge1xuICAgIGlmICghdGhpcy52YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMud2hhdH0gbm90IGNvbmZpZ3VyZWRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gIH1cblxuICBwdWJsaWMgc2V0KHg6IEEsIHNvdXJjZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMudmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLndoYXR9OiAke3NvdXJjZX0gYWxyZWFkeSBjb25maWd1cmVkIHZpYSAke3RoaXMuc291cmNlfWApO1xuICAgIH1cbiAgICB0aGlzLnZhbHVlID0geDtcbiAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0aGlzUGFja2FnZVZlcnNpb24oKTogc3RyaW5nIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgcmV0dXJuIHJlcXVpcmUoJy4uLy4uL3BhY2thZ2UuanNvbicpLnZlcnNpb247XG59XG5cbm1haW4oKS5jYXRjaChlID0+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5lcnJvcihlKTtcbiAgcHJvY2Vzcy5leGl0Q29kZSA9IDE7XG59KTtcbiJdfQ==