@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
332 lines • 44.6 kB
JavaScript
;
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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-console */
const path = __importStar(require("path"));
const jest = __importStar(require("jest"));
const yargs = __importStar(require("yargs"));
const emf_1 = require("../emf");
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',
// makes it easier to control from the outside and mitigate
// resource utilization issues on codebuild.
default: process.env.JEST_MAX_WORKERS,
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,
});
if (process.env.CODEBUILD_BUILD_ID) {
// Emitting here is sliiiightly going to mess up the output of the test run, but since this is
// CodeBuild not too many people are going to look at it probably. Ultimately we only want these
// metrics into CloudWatch.
(0, emf_1.emitVersionsEmf)({
cli: cli.version,
library: library.version,
toolkitLib: toolkitLib.version,
cdkAssets: cdkAssets.version,
tests: thisPackageVersion(),
});
}
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLXN1aXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicnVuLXN1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsK0JBQStCO0FBQy9CLDJDQUE2QjtBQUM3QiwyQ0FBNkI7QUFDN0IsNkNBQStCO0FBQy9CLGdDQUF5QztBQUN6QyxzRUFBdUU7QUFDdkUsd0VBQXlFO0FBQ3pFLDREQUFnRTtBQUNoRSxrR0FBbUc7QUFDbkcsOEVBQStFO0FBQy9FLGdHQUFpRztBQUVqRyw4REFBaUU7QUFFakUsTUFBTSxnQkFBZ0IsR0FBRyxTQUFTLENBQUM7QUFDbkMsTUFBTSx1QkFBdUIsR0FBRyxZQUFZLENBQUM7QUFFN0MsS0FBSyxVQUFVLElBQUk7SUFDakIsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLO1NBQ3JCLE9BQU8sQ0FBQyxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ2hELFVBQVUsQ0FBQyxXQUFXLEVBQUU7UUFDdkIsUUFBUSxFQUFFLCtCQUErQjtRQUN6QyxJQUFJLEVBQUUsUUFBUTtRQUNkLFlBQVksRUFBRSxJQUFJO0tBQ25CLENBQUM7UUFDRiw2RUFBNkU7UUFDN0Usd0JBQXdCO1NBQ3ZCLE9BQU8sQ0FBQyxhQUFhLEVBQUU7UUFDdEIsUUFBUSxFQUFFLHFCQUFxQjtRQUMvQixLQUFLLEVBQUUsR0FBRztRQUNWLElBQUksRUFBRSxRQUFRO0tBQ2YsQ0FBQztTQUNELE9BQU8sQ0FBQyxZQUFZLEVBQUU7UUFDckIsUUFBUSxFQUFFLDRDQUE0QztRQUN0RCxLQUFLLEVBQUUsR0FBRztRQUNWLElBQUksRUFBRSxRQUFRO0tBQ2YsQ0FBQztTQUNELE9BQU8sQ0FBQyxtQkFBbUIsRUFBRTtRQUM1QixRQUFRLEVBQUUsMEJBQTBCO1FBQ3BDLEtBQUssRUFBRSxHQUFHO1FBQ1YsSUFBSSxFQUFFLFFBQVE7S0FDZixDQUFDO1NB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LE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakIsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7QUFDdkIsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgamVzdCBmcm9tICdqZXN0JztcbmltcG9ydCAqIGFzIHlhcmdzIGZyb20gJ3lhcmdzJztcbmltcG9ydCB7IGVtaXRWZXJzaW9uc0VtZiB9IGZyb20gJy4uL2VtZic7XG5pbXBvcnQgeyBSdW5uZXJDbGlOcG1Tb3VyY2UgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvY2xpLW5wbS1zb3VyY2UnO1xuaW1wb3J0IHsgUnVubmVyQ2xpUmVwb1NvdXJjZSB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9jbGktcmVwby1zb3VyY2UnO1xuaW1wb3J0IHsgYXV0b0ZpbmRSZXBvUm9vdCB9IGZyb20gJy4uL3BhY2thZ2Utc291cmNlcy9maW5kLXJvb3QnO1xuaW1wb3J0IHsgUnVubmVyTGlicmFyeUdsb2JhbEluc3RhbGxTb3VyY2UgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvbGlicmFyeS1nbG9iYWxpbnN0YWxsLXNvdXJjZSc7XG5pbXBvcnQgeyBSdW5uZXJMaWJyYXJ5TnBtU291cmNlIH0gZnJvbSAnLi4vcGFja2FnZS1zb3VyY2VzL2xpYnJhcnktbnBtLXNvdXJjZSc7XG5pbXBvcnQgeyBSdW5uZXJMaWJyYXJ5UHJlaW5zdGFsbGVkU291cmNlIH0gZnJvbSAnLi4vcGFja2FnZS1zb3VyY2VzL2xpYnJhcnktcHJlaW5zdGFsbGVkLXNvdXJjZSc7XG5pbXBvcnQgdHlwZSB7IElSdW5uZXJTb3VyY2UsIElUZXN0Q2xpU291cmNlLCBJVGVzdExpYnJhcnlTb3VyY2UgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvc291cmNlJztcbmltcG9ydCB7IHNlcmlhbGl6ZVNvdXJjZXMgfSBmcm9tICcuLi9wYWNrYWdlLXNvdXJjZXMvc3VicHJvY2Vzcyc7XG5cbmNvbnN0IENMSV9QQUNLQUdFX05BTUUgPSAnYXdzLWNkayc7XG5jb25zdCBDREtfQVNTRVRTX1BBQ0tBR0VfTkFNRSA9ICdjZGstYXNzZXRzJztcblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgY29uc3QgYXJncyA9IGF3YWl0IHlhcmdzXG4gICAgLmNvbW1hbmQoJyogPFNVSVRFTkFNRT4nLCAnZGVmYXVsdCBjb21tYW5kJywgeSA9PiB5XG4gICAgICAucG9zaXRpb25hbCgnU1VJVEVOQU1FJywge1xuICAgICAgICBkZXNjcmliZTogJ05hbWUgb2YgdGhlIHRlc3Qgc3VpdGUgdG8gcnVuJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIGRlbWFuZE9wdGlvbjogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgICAgLy8gIFNvdXJjZXMgYW5kIHZlcnNpb25zXG4gICAgICAub3B0aW9ucygnY2xpLXZlcnNpb24nLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnQ0xJIHZlcnNpb24gdG8gdXNlLicsXG4gICAgICAgIGFsaWFzOiAnYycsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCdjbGktc291cmNlJywge1xuICAgICAgICBkZXNjcmliZTogJ1Jvb3Qgb2YgYXdzLWNkay1jbGkgcmVwb3NpdG9yeSwgb3IgXCJhdXRvXCIuJyxcbiAgICAgICAgYWxpYXM6ICdzJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ2ZyYW1ld29yay12ZXJzaW9uJywge1xuICAgICAgICBkZXNjcmliZTogJ0ZyYW1ld29yayB2ZXJzaW9uIHRvIHVzZScsXG4gICAgICAgIGFsaWFzOiAnZicsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCd0b29sa2l0LWxpYi12ZXJzaW9uJywge1xuICAgICAgICBkZXNjcmliZTogJ1Rvb2xraXQgbGliIHZlcnNpb24gdG8gdXNlJyxcbiAgICAgICAgYWxpYXM6ICdsJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ2Nkay1hc3NldHMtdmVyc2lvbicsIHtcbiAgICAgICAgZGVzY3JpYmU6ICdjZGstYXNzZXRzIHZlcnNpb24gdG8gdXNlLicsXG4gICAgICAgIGFsaWFzOiAnYScsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3VzZS1zb3VyY2UnLCB7XG4gICAgICAgIGRlc2NyaXB0b246ICdVc2UgVHlwZVNjcmlwdCBwYWNrYWdlcyBmcm9tIHRoZSBnaXZlbiBzb3VyY2UgcmVwb3NpdG9yeSAob3IgXCJhdXRvXCIpJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgICBkZXByZWNhdGVkOiAnVXNlIC0tY2xpLXNvdXJjZSBpbnN0ZWFkJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCd1c2UtY2xpLXJlbGVhc2UnLCB7XG4gICAgICAgIGRlc2NyaXB0b246ICdSdW4gdGhlIGN1cnJlbnQgdGVzdHMgYWdhaW5zdCB0aGUgQ0xJIGF0IHRoZSBnaXZlbiB2ZXJzaW9uJyxcbiAgICAgICAgYWxpYXM6ICd1JyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgICBkZXByZWNhdGVkOiAnVXNlIC0tY2xpLXZlcnNpb24gaW5zdGVhZCcsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbignYXV0by1zb3VyY2UnLCB7XG4gICAgICAgIGFsaWFzOiAnYScsXG4gICAgICAgIGRlc2NyaWJlOiAnQXV0b21hdGljYWxseSBmaW5kIHRoZSBzb3VyY2UgdHJlZSBmcm9tIHRoZSBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5JyxcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICByZXF1aXJlc0FyZzogZmFsc2UsXG4gICAgICAgIGRlcHJlY2F0ZWQ6ICdVc2UgLS11c2Utc291cmNlPWF1dG8gaW5zdGVhZCcsXG4gICAgICB9KVxuICAgICAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbiAgICAgIC8vICBUZXN0IHJ1bm5pbmcgZmxhZ3NcbiAgICAgIC5vcHRpb24oJ3J1bkluQmFuZCcsIHtcbiAgICAgICAgZGVzY3JpcHRvbjogJ1J1biBhbGwgdGVzdHMgaW4gb25lIE5vZGUgcHJvY2VzcycsXG4gICAgICAgIGFsaWFzOiAnaScsXG4gICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCd0ZXN0Jywge1xuICAgICAgICBkZXNjcmlwdG9uOiAnVGVzdCBwYXR0ZXJuIHRvIHNlbGVjdGl2ZWx5IHJ1biB0ZXN0cycsXG4gICAgICAgIGFsaWFzOiAndCcsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICByZXF1aXJlc0FyZzogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCd0ZXN0LWZpbGUnLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnVGhlIHNwZWNpZmljIHRlc3QgZmlsZSB0byBydW4nLFxuICAgICAgICBhbGlhczogJ0YnLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3NlZWQnLCB7XG4gICAgICAgIGRlc2NyaWJlOiAnU2V0IHRoZSBzZWVkIHZhbHVlIHRvIHJlcGxpY2F0ZSBhIHRlc3QgcnVuJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCd2ZXJib3NlJywge1xuICAgICAgICBhbGlhczogJ3YnLFxuICAgICAgICBkZXNjcmliZTogJ1J1biBpbiB2ZXJib3NlIG1vZGUnLFxuICAgICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICAgIHJlcXVpcmVzQXJnOiBmYWxzZSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9ucygncGFzc1dpdGhOb1Rlc3RzJywge1xuICAgICAgICBkZXNjcmliZTogJ0FsbG93IHBhc3NpbmcgaWYgdGhlIHRlc3Qgc3VpdGUgaXMgbm90IGZvdW5kIChkZWZhdWx0IHRydWUgd2hlbiBJU19DQU5BUlkgbW9kZSwgZmFsc2Ugb3RoZXJ3aXNlKScsXG4gICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IGZhbHNlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCdtYXhXb3JrZXJzJywge1xuICAgICAgICBhbGlhczogJ3cnLFxuICAgICAgICBkZXNjcmliZTogJ1NwZWNpZmllcyB0aGUgbWF4aW11bSBudW1iZXIgb2Ygd29ya2VycyB0aGUgd29ya2VyLXBvb2wgd2lsbCBzcGF3biBmb3IgcnVubmluZyB0ZXN0cy4gV2UgdXNlIGEgc2Vuc2libGUgZGVmYXVsdCBmb3IgcnVubmluZyBjbGkgaW50ZWcgdGVzdHMuJyxcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIC8vIG1ha2VzIGl0IGVhc2llciB0byBjb250cm9sIGZyb20gdGhlIG91dHNpZGUgYW5kIG1pdGlnYXRlXG4gICAgICAgIC8vIHJlc291cmNlIHV0aWxpemF0aW9uIGlzc3VlcyBvbiBjb2RlYnVpbGQuXG4gICAgICAgIGRlZmF1bHQ6IHByb2Nlc3MuZW52LkpFU1RfTUFYX1dPUktFUlMsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCdzaGFyZCcsIHtcbiAgICAgICAgZGVzY3JpYmU6ICdUaGUgdGVzdCBzdWl0ZSBzaGFyZCB0byBleGVjdXRlIGluIGEgZm9ybWF0IG9mICg/PHNoYXJkSW5kZXg+XFxkKykvKD88c2hhcmRDb3VudD5cXGQrKS4gYHNoYXJkSW5kZXhgIGRlc2NyaWJlcyB3aGljaCBzaGFyZCB0byBzZWxlY3Qgd2hpbGUgYHNoYXJkQ291bnRgIGNvbnRyb2xzIHRoZSBudW1iZXIgb2Ygc2hhcmRzIHRoZSBzdWl0ZSBzaG91bGQgYmUgc3BsaXQgaW50by4gYHNoYXJkSW5kZXhgIGFuZCBgc2hhcmRDb3VudGAgaGF2ZSB0byBiZSAxLWJhc2VkLCBwb3NpdGl2ZSBudW1iZXJzLCBhbmQgYHNoYXJkSW5kZXhgIGhhcyB0byBiZSBsb3dlciB0aGFuIG9yIGVxdWFsIHRvIGBzaGFyZENvdW50YC4nLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgcmVxdWlyZXNBcmc6IHRydWUsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3JldHJ5Jywge1xuICAgICAgICBkZXNjcmliZTogJ051bWJlciBvZiB0aW1lcyB0byByZXRyeSBmYWlsZWQgdGVzdHMuJyxcbiAgICAgICAgdHlwZTogJ251bWJlcicsXG4gICAgICAgIHJlcXVpcmVzQXJnOiB0cnVlLFxuICAgICAgICBkZWZhdWx0OiAhIShwcm9jZXNzLmVudi5DSSB8fCBwcm9jZXNzLmVudi5DT0RFQlVJTERfQlVJTERfSUQpID8gMiA6IDAsXG4gICAgICAgIGRlZmF1bHREZXNjcmlwdGlvbjogJzIgaW4gQ0kvQ29kZUJ1aWxkLCAwIG90aGVyd2lzZScsXG4gICAgICB9KSwgKCkgPT4ge1xuICAgIH0sXG4gICAgKVxuICAgIC5zdHJpY3QoKVxuICAgIC5wYXJzZSgpO1xuXG4gIGNvbnN0IHN1aXRlTmFtZSA9IGFyZ3MuU1VJVEVOQU1FO1xuXG4gIC8vIFNvIG1hbnkgd2F5cyB0byBzcGVjaWZ5IHRoaXMsIGFuZCB3aXRoIHZhcmlvdXMgd2F5cyB0byBzcGVsbCB0aGUgc2FtZSBmbGFnIChvX08pXG4gIC8vIEFsc28sIHNvbWUgb2YgdGhlbSBkZXBlbmQgb24gZWFjaCBvdGhlciBmb3IgY29udmVuaWVuY2UuXG4gIGNvbnN0IGNsaVNvdXJjZSA9IG5ldyBVbmlxdWVPcHRpb248SVJ1bm5lclNvdXJjZTxJVGVzdENsaVNvdXJjZT4+KCdDTEkgdmVyc2lvbicpO1xuICBjb25zdCBjZGtBc3NldHNTb3VyY2UgPSBuZXcgVW5pcXVlT3B0aW9uPElSdW5uZXJTb3VyY2U8SVRlc3RDbGlTb3VyY2U+PignY2RrLWFzc2V0cyB2ZXJzaW9uJyk7XG5cbiAgLy8gU3BlY2lmaWMgQ0xJIHZlcnNpb25cbiAgZm9yIChjb25zdCBmbGFnQWxpYXMgb2YgWydjbGktdmVyc2lvbicsICd1c2UtY2xpLXJlbGVhc2UnXSBhcyBjb25zdCkge1xuICAgIGlmIChhcmdzW2ZsYWdBbGlhc10pIHtcbiAgICAgIGNsaVNvdXJjZS5zZXQobmV3IFJ1bm5lckNsaU5wbVNvdXJjZShDTElfUEFDS0FHRV9OQU1FLCBhcmdzW2ZsYWdBbGlhc10pLCBgLS0ke2ZsYWdBbGlhc31gKTtcbiAgICB9XG4gIH1cblxuICAvLyBTcGVjaWZpYyBjZGstYXNzZXRzIHZlcnNpb25cbiAgaWYgKGFyZ3NbJ2Nkay1hc3NldHMtdmVyc2lvbiddKSB7XG4gICAgY2RrQXNzZXRzU291cmNlLnNldChuZXcgUnVubmVyQ2xpTnBtU291cmNlKENES19BU1NFVFNfUEFDS0FHRV9OQU1FLCBhcmdzWydjZGstYXNzZXRzLXZlcnNpb24nXSksICctLWNkay1hc3NldHMtdmVyc2lvbicpO1xuICB9XG5cbiAgLy8gU3BlY2lmaWNhbGx5IHVzZSBhIHNvdXJjZSBsb2NhdGlvblxuICBmb3IgKGNvbnN0IGZsYWdBbGlhcyBvZiBbJ2NsaS1zb3VyY2UnLCAndXNlLXNvdXJjZSddIGFzIGNvbnN0KSB7XG4gICAgaWYgKGFyZ3NbZmxhZ0FsaWFzXSkge1xuICAgICAgY29uc3Qgcm9vdCA9IGFyZ3NbZmxhZ0FsaWFzXSA9PT0gJ2F1dG8nID8gYXdhaXQgYXV0b0ZpbmRSZXBvUm9vdCgpIDogYXJnc1tmbGFnQWxpYXNdO1xuICAgICAgY2xpU291cmNlLnNldChuZXcgUnVubmVyQ2xpUmVwb1NvdXJjZShDTElfUEFDS0FHRV9OQU1FLCByb290KSwgYC0tJHtmbGFnQWxpYXN9YCk7XG4gICAgICBjZGtBc3NldHNTb3VyY2Uuc2V0KG5ldyBSdW5uZXJDbGlSZXBvU291cmNlKENES19BU1NFVFNfUEFDS0FHRV9OQU1FLCByb290KSwgYC0tJHtmbGFnQWxpYXN9YCk7XG4gICAgfVxuICB9XG5cbiAgLy8gU3BlY2lmaWNhbGx5IHJlcXVlc3QgdGhhdCBhIHNvdXJjZSBsb2NhdGlvbiBpcyBnaXZlbiwgb3Igd2UgZGlkbid0IGZpbmQgYSBDTEkgeWV0LlxuICAvLyBBIENMSSBzb3VyY2UgaXMgcmVxdWlyZWQsIHNvIGlmIHRoaXMgZmFpbHMgdGhhdCdzIGFscmlnaHQuXG4gIGlmIChhcmdzWydhdXRvLXNvdXJjZSddIHx8ICFjbGlTb3VyY2UuaXNTZXQoKSkge1xuICAgIGNsaVNvdXJjZS5zZXQobmV3IFJ1bm5lckNsaVJlcG9Tb3VyY2UoQ0xJX1BBQ0tBR0VfTkFNRSwgYXdhaXQgYXV0b0ZpbmRSZXBvUm9vdCgpKSwgJy0tYXV0by1zb3VyY2UnKTtcbiAgfVxuXG4gIC8vIElmIHRoZSBDTEkgaXMgdGFrZW4gZnJvbSB0aGUgc291cmNlLCBhbmQgY2RrLWFzc2V0cyBpcyBub3Qgc2V0LCB3ZSBjYW4gY29weSB0aGUgY2RrLWFzc2V0cyBzb3VyY2UgZnJvbSB0aGUgQ0xJIHNvdXJjZS5cbiAgaWYgKCFjZGtBc3NldHNTb3VyY2UuaXNTZXQoKSkge1xuICAgIGNvbnN0IGNsaVNyYyA9IGNsaVNvdXJjZS5hc3NlcnQoKTtcbiAgICBpZiAoY2xpU3JjIGluc3RhbmNlb2YgUnVubmVyQ2xpUmVwb1NvdXJjZSkge1xuICAgICAgY2RrQXNzZXRzU291cmNlLnNldChuZXcgUnVubmVyQ2xpUmVwb1NvdXJjZShDREtfQVNTRVRTX1BBQ0tBR0VfTkFNRSwgY2xpU3JjLnJlcG9Sb290KSwgJ2NvcGllZCBmcm9tIENMSSBzb3VyY2UnKTtcbiAgICB9XG4gIH1cblxuICAvLyBJZiBjZGstYXNzZXRzIGlzIHN0aWxsIG5vdCBjb25maWd1cmVkLCBmYWxsIGJhY2sgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uIHRoYXQgaXMgYXZhaWxhYmxlXG4gIGlmICghY2RrQXNzZXRzU291cmNlLmlzU2V0KCkpIHtcbiAgICBjZGtBc3NldHNTb3VyY2Uuc2V0KG5ldyBSdW5uZXJDbGlOcG1Tb3VyY2UoQ0RLX0FTU0VUU19QQUNLQUdFX05BTUUsICdsYXRlc3QnKSwgJy0tY2RrLWFzc2V0cy12ZXJzaW9uIG5vdCBzZXQnKTtcbiAgfVxuXG4gIC8vIExpYnJhcnkgc291cmNlIGlzIGVpdGhlciB0aGUgZ2l2ZW4gb25lLCBvciAnbGF0ZXN0JyAobmljZSBhbmQgc2ltcGxlKVxuICBjb25zdCBsaWJyYXJ5U291cmNlOiBJUnVubmVyU291cmNlPElUZXN0TGlicmFyeVNvdXJjZT5cbiAgICA9IG5ldyBSdW5uZXJMaWJyYXJ5TnBtU291cmNlKCdhd3MtY2RrLWxpYicsIGFyZ3NbJ2ZyYW1ld29yay12ZXJzaW9uJ10gPyBhcmdzWydmcmFtZXdvcmstdmVyc2lvbiddIDogJ2xhdGVzdCcpO1xuXG4gIC8vIFRvb2xraXQgbGliIHNvdXJjZSBpcyBlaXRoZXIgdGhlIGdpdmVuIG9uZSwgb3IgdGhlIG9uZSB0aGF0J3MgYmVpbmcgYnJvdWdodCBieSAncGFja2FnZS5qc29uJyBhbHJlYWR5LCBvciAnbGF0ZXN0J1xuICBjb25zdCB0b29sa2l0TGliUGFja2FnZSA9ICdAYXdzLWNkay90b29sa2l0LWxpYic7XG4gIGxldCB0b29sa2l0U291cmNlOiBJUnVubmVyU291cmNlPElUZXN0TGlicmFyeVNvdXJjZT4gfCB1bmRlZmluZWQ7XG4gIGlmIChhcmdzWyd0b29sa2l0LWxpYi12ZXJzaW9uJ10pIHtcbiAgICB0b29sa2l0U291cmNlID0gbmV3IFJ1bm5lckxpYnJhcnlHbG9iYWxJbnN0YWxsU291cmNlKHRvb2xraXRMaWJQYWNrYWdlLCBhcmdzWyd0b29sa2l0LWxpYi12ZXJzaW9uJ10pO1xuICB9XG4gIGlmICghdG9vbGtpdFNvdXJjZSkge1xuICAgIHRvb2xraXRTb3VyY2UgPSBhd2FpdCBSdW5uZXJMaWJyYXJ5UHJlaW5zdGFsbGVkU291cmNlLmlzUHJlaW5zdGFsbGVkKHRvb2xraXRMaWJQYWNrYWdlKVxuICAgICAgPyBuZXcgUnVubmVyTGlicmFyeVByZWluc3RhbGxlZFNvdXJjZSh0b29sa2l0TGliUGFja2FnZSlcbiAgICAgIDogbmV3IFJ1bm5lckxpYnJhcnlHbG9iYWxJbnN0YWxsU291cmNlKHRvb2xraXRMaWJQYWNrYWdlLCAnbGF0ZXN0Jyk7XG4gIH1cblxuICBwcm9jZXNzLmVudi5KRVNUX1JFVFJZX1RJTUVTID0gU3RyaW5nKGFyZ3MucmV0cnkpO1xuXG4gIGNvbnNvbGUubG9nKCctLS0tLS0+IENvbmZpZ3VyYXRpb24nKTtcbiAgY29uc29sZS5sb2coYCAgICAgICAgVGVzdCBzdWl0ZTogICAgICAgICAke3N1aXRlTmFtZX1gKTtcbiAgY29uc29sZS5sb2coYCAgICAgICAgVGVzdCB2ZXJzaW9uOiAgICAgICAke3RoaXNQYWNrYWdlVmVyc2lvbigpfWApO1xuICBjb25zb2xlLmxvZyhgICAgICAgICBDTEkgc291cmNlOiAgICAgICAgICR7Y2xpU291cmNlLmFzc2VydCgpLnNvdXJjZURlc2NyaXB0aW9ufWApO1xuICBjb25zb2xlLmxvZyhgICAgICAgICBMaWJyYXJ5IHNvdXJjZTogICAgICR7bGlicmFyeVNvdXJjZS5zb3VyY2VEZXNjcmlwdGlvbn1gKTtcbiAgY29uc29sZS5sb2coYCAgICAgICAgVG9vbGtpdCBsaWIgc291cmNlOiAke3Rvb2xraXRTb3VyY2Uuc291cmNlRGVzY3JpcHRpb259YCk7XG4gIGNvbnNvbGUubG9nKGAgICAgICAgIGNkay1hc3NldHMgc291cmNlOiAgJHtjZGtBc3NldHNTb3VyY2UuYXNzZXJ0KCkuc291cmNlRGVzY3JpcHRpb259YCk7XG4gIGNvbnNvbGUubG9nKGAgICAgICAgIFJldHJ5OiAgICAgICAgICAgICAgJHthcmdzLnJldHJ5fWApO1xuXG4gIGlmIChhcmdzLnZlcmJvc2UpIHtcbiAgICBwcm9jZXNzLmVudi5WRVJCT1NFID0gJzEnO1xuICB9XG5cbiAgLy8gTW90aXZhdGlvbiBiZWhpbmQgdGhpcyBiZWhhdmlvcjogd2hlbiBhZGRpbmcgYSBuZXcgdGVzdCBzdWl0ZSB0byB0aGUgcGlwZWxpbmUsIGJlY2F1c2Ugb2YgdGhlIHdheSBvdXJcbiAgLy8gUGlwZWxpbmUgcGFja2FnZSB3b3JrcywgdGhlIHN1aXRlIHdvdWxkIGJlIGFkZGVkIHRvIHRoZSBwaXBlbGluZSBBTkQgYXMgYSBjYW5hcnkgaW1tZWRpYXRlbHkuIFRoZSBjYW5hcnlcbiAgLy8gd291bGQgZmFpbCB1bnRpbCB0aGUgcGFja2FnZSB3YXMgYWN0dWFsbHkgcmVsZWFzZWQsIHNvIGZvciBjYW5hcmllcyB3ZSBtYWtlIGFuIGV4Y2VwdGlvbiBzbyB0aGF0IHRoZSBpbml0aWFsXG4gIC8vIGNhbmFyeSB3b3VsZCBzdWNjZWVkIGV2ZW4gaWYgdGhlIHN1aXRlIHdhc24ndCB5ZXQgYXZhaWxhYmxlLiBUaGUgZmFjdCB0aGF0IHRoZSBzdWl0ZSBpcyBub3Qgb3B0aW9uYWwgaW5cbiAgLy8gdGhlIHBpcGVsaW5lIHByb3RlY3RzIHVzIGZyb20gdHlwb3MuXG4gIGNvbnN0IHBhc3NXaXRoTm9UZXN0cyA9IGFyZ3MucGFzc1dpdGhOb1Rlc3RzID8/ICEhcHJvY2Vzcy5lbnYuSVNfQ0FOQVJZO1xuXG4gIC8vIENvbW11bmljYXRlIHdpdGggdGhlIGNvbmZpZyBmaWxlIChpbnRlZy5qZXN0LmNvbmZpZy5qcylcbiAgcHJvY2Vzcy5lbnYuVEVTVF9TVUlURV9OQU1FID0gc3VpdGVOYW1lO1xuXG4gIGNvbnN0IGRpc3Bvc2FibGVzID0gbmV3IEFycmF5PHsgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IH0+KCk7XG4gIHRyeSB7XG4gICAgY29uc29sZS5sb2coJy0tLS0tLT4gUmVzb2x2ZWQgdmVyc2lvbnMnKTtcbiAgICBjb25zdCBjbGkgPSBhd2FpdCBjbGlTb3VyY2UuYXNzZXJ0KCkucnVubmVyUHJlcGFyZSgpO1xuICAgIGRpc3Bvc2FibGVzLnB1c2goY2xpKTtcbiAgICBjb25zb2xlLmxvZyhgICAgICAgICBDTEk6ICAgICAgICAgICAgICR7Y2xpLnZlcnNpb259YCk7XG5cbiAgICBjb25zdCBsaWJyYXJ5ID0gYXdhaXQgbGlicmFyeVNvdXJjZS5ydW5uZXJQcmVwYXJlKCk7XG4gICAgZGlzcG9zYWJsZXMucHVzaChsaWJyYXJ5KTtcbiAgICBjb25zb2xlLmxvZyhgICAgICAgICBMaWJyYXJ5OiAgICAgICAgICR7bGlicmFyeS52ZXJzaW9ufWApO1xuXG4gICAgY29uc3QgdG9vbGtpdExpYiA9IGF3YWl0IHRvb2xraXRTb3VyY2UucnVubmVyUHJlcGFyZSgpO1xuICAgIGRpc3Bvc2FibGVzLnB1c2godG9vbGtpdExpYik7XG4gICAgY29uc29sZS5sb2coYCAgICAgICAgVG9vbGtpdCBsaWJyYXJ5OiAke3Rvb2xraXRMaWIudmVyc2lvbn1gKTtcblxuICAgIGNvbnN0IGNka0Fzc2V0cyA9IGF3YWl0IGNka0Fzc2V0c1NvdXJjZS5hc3NlcnQoKS5ydW5uZXJQcmVwYXJlKCk7XG4gICAgZGlzcG9zYWJsZXMucHVzaChjZGtBc3NldHMpO1xuICAgIGNvbnNvbGUubG9nKGAgICAgICAgIGNkay1hc3NldHM6ICAgICAgJHtjZGtBc3NldHMudmVyc2lvbn1gKTtcblxuICAgIHNlcmlhbGl6ZVNvdXJjZXMoe1xuICAgICAgY2xpLFxuICAgICAgbGlicmFyeSxcbiAgICAgIHRvb2xraXRMaWIsXG4gICAgICBjZGtBc3NldHMsXG4gICAgfSk7XG5cbiAgICBpZiAocHJvY2Vzcy5lbnYuQ09ERUJVSUxEX0JVSUxEX0lEKSB7XG4gICAgICAvLyBFbWl0dGluZyBoZXJlIGlzIHNsaWlpaWdodGx5IGdvaW5nIHRvIG1lc3MgdXAgdGhlIG91dHB1dCBvZiB0aGUgdGVzdCBydW4sIGJ1dCBzaW5jZSB0aGlzIGlzXG4gICAgICAvLyBDb2RlQnVpbGQgbm90IHRvbyBtYW55IHBlb3BsZSBhcmUgZ29pbmcgdG8gbG9vayBhdCBpdCBwcm9iYWJseS4gVWx0aW1hdGVseSB3ZSBvbmx5IHdhbnQgdGhlc2VcbiAgICAgIC8vIG1ldHJpY3MgaW50byBDbG91ZFdhdGNoLlxuICAgICAgZW1pdFZlcnNpb25zRW1mKHtcbiAgICAgICAgY2xpOiBjbGkudmVyc2lvbixcbiAgICAgICAgbGlicmFyeTogbGlicmFyeS52ZXJzaW9uLFxuICAgICAgICB0b29sa2l0TGliOiB0b29sa2l0TGliLnZlcnNpb24sXG4gICAgICAgIGNka0Fzc2V0czogY2RrQXNzZXRzLnZlcnNpb24sXG4gICAgICAgIHRlc3RzOiB0aGlzUGFja2FnZVZlcnNpb24oKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGplc3RDb25maWcgPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAncmVzb3VyY2VzJywgJ2ludGVnLmplc3QuY29uZmlnLmpzJyk7XG5cbiAgICAvLyBGbGlwIGEgZmxhZyB0byBpbmRpY2F0ZSB3ZSdyZSB0ZXN0aW5nIENESyBpdHNlbGYuIFNvbWUgcGFydHMgb2YgQ0RLIGJlaGF2ZSBtb3JlIHRob3JvdWdobHlcbiAgICAvLyAoYnV0IHNsb3dseSkgaWYgdGhpcyBmbGFnIGlzIHNldC5cbiAgICBwcm9jZXNzLmVudi5URVNUSU5HX0NESyA9ICcxJztcblxuICAgIC8vIGplc3QtanVuaXQgcmVwb3J0ZXIgY29uZmlndXJhdGlvblxuICAgIHByb2Nlc3MuZW52LkpFU1RfU1VJVEVfTkFNRSA9ICdqZXN0IHRlc3RzJztcbiAgICBwcm9jZXNzLmVudi5KRVNUX0pVTklUX09VVFBVVF9ESVIgPSAnY292ZXJhZ2UnO1xuXG4gICAgYXdhaXQgamVzdC5ydW4oW1xuICAgICAgJy0tcmVwb3J0ZXJzPWRlZmF1bHQnLFxuICAgICAgJy0tcmVwb3J0ZXJzPWplc3QtanVuaXQnLFxuICAgICAgLy8gT3ZlcnJpZGUgSmVzdCdzIGRlZmF1bHQgNXMgdGltZW91dCB3aGljaCBpcyB0b28gbG93IGZvciBpbnRlZyB0ZXN0cy5cbiAgICAgIC8vIFRlc3RzIHVzaW5nIHdpdGhBd3MoKSB3aWxsIGZ1cnRoZXIgb3ZlcnJpZGUgdGhpcyB0byAyIGhvdXJzIHRvIGFjY291bnQgZm9yIHJlZ2lvbiBsb2NrIHdhaXQgdGltZXMuXG4gICAgICAnLS10ZXN0VGltZW91dD02MDAwMCcsXG4gICAgICAnLS1yYW5kb21pemUnLFxuICAgICAgLi4uYXJncy5zZWVkID8gW2AtLXNlZWQ9JHthcmdzLnNlZWR9YF0gOiBbXSxcbiAgICAgIC4uLmFyZ3MucnVuSW5CYW5kID8gWyctaSddIDogW10sXG4gICAgICAuLi5hcmdzLnRlc3QgPyBbJy10JywgYXJncy50ZXN0XSA6IFtdLFxuICAgICAgLi4uYXJncy52ZXJib3NlID8gWyctLXZlcmJvc2UnXSA6IFtdLFxuICAgICAgLi4uYXJncy5tYXhXb3JrZXJzID8gW2AtLW1heFdvcmtlcnM9JHthcmdzLm1heFdvcmtlcnN9YF0gOiBbXSxcbiAgICAgIC4uLnBhc3NXaXRoTm9UZXN0cyA/IFsnLS1wYXNzV2l0aE5vVGVzdHMnXSA6IFtdLFxuICAgICAgLi4uYXJnc1sndGVzdC1maWxlJ10gPyBbYXJnc1sndGVzdC1maWxlJ11dIDogW10sXG4gICAgICAuLi5hcmdzLnNoYXJkID8gW2AtLXNoYXJkPSR7YXJncy5zaGFyZH1gXSA6IFtdLFxuICAgIF0sIGplc3RDb25maWcpO1xuICB9IGZpbmFsbHkge1xuICAgIGZvciAoY29uc3QgZGlzcCBvZiBkaXNwb3NhYmxlcykge1xuICAgICAgYXdhaXQgZGlzcC5kaXNwb3NlKCk7XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIFVuaXF1ZU9wdGlvbjxBPiB7XG4gIHB1YmxpYyB2YWx1ZTogQSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBzb3VyY2U6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHdoYXQ6IHN0cmluZykge1xuICB9XG5cbiAgcHVibGljIGlzU2V0KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlICE9PSB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgYXNzZXJ0KCk6IEEge1xuICAgIGlmICghdGhpcy52YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMud2hhdH0gbm90IGNvbmZpZ3VyZWRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gIH1cblxuICBwdWJsaWMgc2V0KHg6IEEsIHNvdXJjZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMudmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLndoYXR9OiAke3NvdXJjZX0gYWxyZWFkeSBjb25maWd1cmVkIHZpYSAke3RoaXMuc291cmNlfWApO1xuICAgIH1cbiAgICB0aGlzLnZhbHVlID0geDtcbiAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0aGlzUGFja2FnZVZlcnNpb24oKTogc3RyaW5nIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgcmV0dXJuIHJlcXVpcmUoJy4uLy4uL3BhY2thZ2UuanNvbicpLnZlcnNpb247XG59XG5cbm1haW4oKS5jYXRjaChlID0+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5lcnJvcihlKTtcbiAgcHJvY2Vzcy5leGl0Q29kZSA9IDE7XG59KTtcblxuIl19