UNPKG

@aws-cdk/integ-runner

Version:

CDK Integration Testing Tool

204 lines 26.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LegacyIntegTestSuite = exports.IntegTestSuite = void 0; const osPath = require("path"); const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema"); const fs = require("fs-extra"); const integ_manifest_1 = require("./private/integ-manifest"); const CDK_INTEG_STACK_PRAGMA = '/// !cdk-integ'; const PRAGMA_PREFIX = 'pragma:'; const SET_CONTEXT_PRAGMA_PREFIX = 'pragma:set-context:'; const VERIFY_ASSET_HASHES = 'pragma:include-assets-hashes'; const DISABLE_UPDATE_WORKFLOW = 'pragma:disable-update-workflow'; const ENABLE_LOOKUPS_PRAGMA = 'pragma:enable-lookups'; /** * Helper class for working with Integration tests * This requires an `integ.json` file in the snapshot * directory. For legacy test cases use LegacyIntegTestCases */ class IntegTestSuite { enableLookups; testSuite; synthContext; /** * Loads integ tests from a snapshot directory */ static fromPath(path) { const reader = integ_manifest_1.IntegManifestReader.fromPath(path); return new IntegTestSuite(reader.tests.enableLookups, reader.tests.testCases, reader.tests.synthContext); } type = 'test-suite'; constructor(enableLookups, testSuite, synthContext) { this.enableLookups = enableLookups; this.testSuite = testSuite; this.synthContext = synthContext; } /** * Returns a list of stacks that have stackUpdateWorkflow disabled */ getStacksWithoutUpdateWorkflow() { return Object.values(this.testSuite) .filter(testCase => !(testCase.stackUpdateWorkflow ?? true)) .flatMap((testCase) => testCase.stacks); } /** * Returns test case options for a given stack */ getOptionsForStack(stackId) { for (const testCase of Object.values(this.testSuite ?? {})) { if (testCase.stacks.includes(stackId)) { return { hooks: testCase.hooks, regions: testCase.regions, diffAssets: testCase.diffAssets ?? false, allowDestroy: testCase.allowDestroy, cdkCommandOptions: testCase.cdkCommandOptions, stackUpdateWorkflow: testCase.stackUpdateWorkflow ?? true, }; } } return undefined; } /** * Get a list of stacks in the test suite */ get stacks() { return Object.values(this.testSuite).flatMap(testCase => testCase.stacks); } } exports.IntegTestSuite = IntegTestSuite; /** * Helper class for creating an integ manifest for legacy * test cases, i.e. tests without a `integ.json`. */ class LegacyIntegTestSuite extends IntegTestSuite { enableLookups; testSuite; synthContext; /** * Returns the single test stack to use. * * If the test has a single stack, it will be chosen. Otherwise a pragma is expected within the * test file the name of the stack: * * @example * * /// !cdk-integ <stack-name> * */ static async fromLegacy(config) { const pragmas = this.pragmas(config.integSourceFilePath); const tests = { stacks: [], diffAssets: pragmas.includes(VERIFY_ASSET_HASHES), stackUpdateWorkflow: !pragmas.includes(DISABLE_UPDATE_WORKFLOW), }; const pragma = this.readStackPragma(config.integSourceFilePath); if (pragma.length > 0) { tests.stacks.push(...pragma); } else { const options = { ...config.listOptions, notices: false, }; const stacks = await config.cdk.list(options); if (stacks.length !== 1) { throw new Error('"integ-runner" can only operate on apps with a single stack.\n\n' + ' If your app has multiple stacks, specify which stack to select by adding this to your test source:\n\n' + ` ${CDK_INTEG_STACK_PRAGMA} STACK ...\n\n` + ` Available stacks: ${stacks.join(' ')} (wildcards are also supported)\n`); } if (stacks.length === 1 && stacks[0] === '') { throw new Error(`No stack found for test ${config.testName}`); } tests.stacks.push(...stacks); } return new LegacyIntegTestSuite(pragmas.includes(ENABLE_LOOKUPS_PRAGMA), { [config.testName]: tests, }, LegacyIntegTestSuite.getPragmaContext(config.integSourceFilePath)); } static getPragmaContext(integSourceFilePath) { const ctxPragmaContext = {}; // apply context from set-context pragma // usage: pragma:set-context:key=value const ctxPragmas = (this.pragmas(integSourceFilePath)).filter(p => p.startsWith(SET_CONTEXT_PRAGMA_PREFIX)); for (const p of ctxPragmas) { const instruction = p.substring(SET_CONTEXT_PRAGMA_PREFIX.length); const [key, value] = instruction.split('='); if (key == null || value == null) { throw new Error(`invalid "set-context" pragma syntax. example: "pragma:set-context:@aws-cdk/core:newStyleStackSynthesis=true" got: ${p}`); } ctxPragmaContext[key] = value; } return { ...ctxPragmaContext, }; } /** * Reads stack names from the "!cdk-integ" pragma. * * Every word that's NOT prefixed by "pragma:" is considered a stack name. * * @example * * /// !cdk-integ <stack-name> */ static readStackPragma(integSourceFilePath) { return (this.readIntegPragma(integSourceFilePath)).filter(p => !p.startsWith(PRAGMA_PREFIX)); } /** * Read arbitrary cdk-integ pragma directives * * Reads the test source file and looks for the "!cdk-integ" pragma. If it exists, returns it's * contents. This allows integ tests to supply custom command line arguments to "cdk deploy" and "cdk synth". * * @example * * /// !cdk-integ [...] */ static readIntegPragma(integSourceFilePath) { const source = fs.readFileSync(integSourceFilePath, { encoding: 'utf-8' }); const pragmaLine = source.split('\n').find(x => x.startsWith(CDK_INTEG_STACK_PRAGMA + ' ')); if (!pragmaLine) { return []; } const args = pragmaLine.substring(CDK_INTEG_STACK_PRAGMA.length).trim().split(' '); if (args.length === 0) { throw new Error(`Invalid syntax for cdk-integ pragma. Usage: "${CDK_INTEG_STACK_PRAGMA} [STACK] [pragma:PRAGMA] [...]"`); } return args; } /** * Return the non-stack pragmas * * These are all pragmas that start with "pragma:". * * For backwards compatibility reasons, all pragmas that DON'T start with this * string are considered to be stack names. */ static pragmas(integSourceFilePath) { return (this.readIntegPragma(integSourceFilePath)).filter(p => p.startsWith(PRAGMA_PREFIX)); } type = 'legacy-test-suite'; constructor(enableLookups, testSuite, synthContext) { super(enableLookups, testSuite); this.enableLookups = enableLookups; this.testSuite = testSuite; this.synthContext = synthContext; } /** * Save the integ manifest to a directory */ saveManifest(directory, context) { const manifest = { version: cloud_assembly_schema_1.Manifest.version(), testCases: this.testSuite, synthContext: context, enableLookups: this.enableLookups, }; cloud_assembly_schema_1.Manifest.saveIntegManifest(manifest, osPath.join(directory, integ_manifest_1.IntegManifestReader.DEFAULT_FILENAME)); } } exports.LegacyIntegTestSuite = LegacyIntegTestSuite; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWctdGVzdC1zdWl0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImludGVnLXRlc3Qtc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQStCO0FBRS9CLDBFQUEwRDtBQUMxRCwrQkFBK0I7QUFFL0IsNkRBQStEO0FBRS9ELE1BQU0sc0JBQXNCLEdBQUcsZ0JBQWdCLENBQUM7QUFDaEQsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDO0FBQ2hDLE1BQU0seUJBQXlCLEdBQUcscUJBQXFCLENBQUM7QUFDeEQsTUFBTSxtQkFBbUIsR0FBRyw4QkFBOEIsQ0FBQztBQUMzRCxNQUFNLHVCQUF1QixHQUFHLGdDQUFnQyxDQUFDO0FBQ2pFLE1BQU0scUJBQXFCLEdBQUcsdUJBQXVCLENBQUM7QUFTdEQ7Ozs7R0FJRztBQUNILE1BQWEsY0FBYztJQWdCUDtJQUNBO0lBQ0E7SUFqQmxCOztPQUVHO0lBQ0ksTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFZO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLG9DQUFtQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRCxPQUFPLElBQUksY0FBYyxDQUN2QixNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFDMUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQ3RCLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUMxQixDQUFDO0lBQ0osQ0FBQztJQUVlLElBQUksR0FBa0IsWUFBWSxDQUFDO0lBRW5ELFlBQ2tCLGFBQXNCLEVBQ3RCLFNBQW9CLEVBQ3BCLFlBQXlDO1FBRnpDLGtCQUFhLEdBQWIsYUFBYSxDQUFTO1FBQ3RCLGNBQVMsR0FBVCxTQUFTLENBQVc7UUFDcEIsaUJBQVksR0FBWixZQUFZLENBQTZCO0lBRTNELENBQUM7SUFFRDs7T0FFRztJQUNJLDhCQUE4QjtRQUNuQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQzthQUNqQyxNQUFN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QU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUM5RixDQUFDO0lBRWUsSUFBSSxHQUFrQixtQkFBbUIsQ0FBQztJQUUxRCxZQUNrQixhQUFzQixFQUN0QixTQUFvQixFQUNwQixZQUF5QztRQUV6RCxLQUFLLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBSmhCLGtCQUFhLEdBQWIsYUFBYSxDQUFTO1FBQ3RCLGNBQVMsR0FBVCxTQUFTLENBQVc7UUFDcEIsaUJBQVksR0FBWixZQUFZLENBQTZCO0lBRzNELENBQUM7SUFFRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxTQUFpQixFQUFFLE9BQTZCO1FBQ2xFLE1BQU0sUUFBUSxHQUFrQjtZQUM5QixPQUFPLEVBQUUsZ0NBQVEsQ0FBQyxPQUFPLEVBQUU7WUFDM0IsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3pCLFlBQVksRUFBRSxPQUFPO1lBQ3JCLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtTQUNsQyxDQUFDO1FBQ0YsZ0NBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsb0NBQW1CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7Q0FDRjtBQTVJRCxvREE0SUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvc1BhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgdHlwZSB7IFRlc3RDYXNlLCBUZXN0T3B0aW9ucywgSW50ZWdNYW5pZmVzdCB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBNYW5pZmVzdCB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgdHlwZSB7IElDZGssIExpc3RPcHRpb25zIH0gZnJvbSAnLi4vZW5naW5lcy9jZGstaW50ZXJmYWNlJztcbmltcG9ydCB7IEludGVnTWFuaWZlc3RSZWFkZXIgfSBmcm9tICcuL3ByaXZhdGUvaW50ZWctbWFuaWZlc3QnO1xuXG5jb25zdCBDREtfSU5URUdfU1RBQ0tfUFJBR01BID0gJy8vLyAhY2RrLWludGVnJztcbmNvbnN0IFBSQUdNQV9QUkVGSVggPSAncHJhZ21hOic7XG5jb25zdCBTRVRfQ09OVEVYVF9QUkFHTUFfUFJFRklYID0gJ3ByYWdtYTpzZXQtY29udGV4dDonO1xuY29uc3QgVkVSSUZZX0FTU0VUX0hBU0hFUyA9ICdwcmFnbWE6aW5jbHVkZS1hc3NldHMtaGFzaGVzJztcbmNvbnN0IERJU0FCTEVfVVBEQVRFX1dPUktGTE9XID0gJ3ByYWdtYTpkaXNhYmxlLXVwZGF0ZS13b3JrZmxvdyc7XG5jb25zdCBFTkFCTEVfTE9PS1VQU19QUkFHTUEgPSAncHJhZ21hOmVuYWJsZS1sb29rdXBzJztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGludGVncmF0aW9uIHRlc3RcbiAqL1xuZXhwb3J0IHR5cGUgVGVzdFN1aXRlID0geyBbdGVzdE5hbWU6IHN0cmluZ106IFRlc3RDYXNlIH07XG5cbmV4cG9ydCB0eXBlIFRlc3RTdWl0ZVR5cGUgPSAndGVzdC1zdWl0ZScgfCAnbGVnYWN5LXRlc3Qtc3VpdGUnO1xuXG4vKipcbiAqIEhlbHBlciBjbGFzcyBmb3Igd29ya2luZyB3aXRoIEludGVncmF0aW9uIHRlc3RzXG4gKiBUaGlzIHJlcXVpcmVzIGFuIGBpbnRlZy5qc29uYCBmaWxlIGluIHRoZSBzbmFwc2hvdFxuICogZGlyZWN0b3J5LiBGb3IgbGVnYWN5IHRlc3QgY2FzZXMgdXNlIExlZ2FjeUludGVnVGVzdENhc2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnRlZ1Rlc3RTdWl0ZSB7XG4gIC8qKlxuICAgKiBMb2FkcyBpbnRlZyB0ZXN0cyBmcm9tIGEgc25hcHNob3QgZGlyZWN0b3J5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21QYXRoKHBhdGg6IHN0cmluZyk6IEludGVnVGVzdFN1aXRlIHtcbiAgICBjb25zdCByZWFkZXIgPSBJbnRlZ01hbmlmZXN0UmVhZGVyLmZyb21QYXRoKHBhdGgpO1xuICAgIHJldHVybiBuZXcgSW50ZWdUZXN0U3VpdGUoXG4gICAgICByZWFkZXIudGVzdHMuZW5hYmxlTG9va3VwcyxcbiAgICAgIHJlYWRlci50ZXN0cy50ZXN0Q2FzZXMsXG4gICAgICByZWFkZXIudGVzdHMuc3ludGhDb250ZXh0LFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgdHlwZTogVGVzdFN1aXRlVHlwZSA9ICd0ZXN0LXN1aXRlJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgZW5hYmxlTG9va3VwczogYm9vbGVhbixcbiAgICBwdWJsaWMgcmVhZG9ubHkgdGVzdFN1aXRlOiBUZXN0U3VpdGUsXG4gICAgcHVibGljIHJlYWRvbmx5IHN5bnRoQ29udGV4dD86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9LFxuICApIHtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbGlzdCBvZiBzdGFja3MgdGhhdCBoYXZlIHN0YWNrVXBkYXRlV29ya2Zsb3cgZGlzYWJsZWRcbiAgICovXG4gIHB1YmxpYyBnZXRTdGFja3NXaXRob3V0VXBkYXRlV29ya2Zsb3coKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMudGVzdFN1aXRlKVxuICAgICAgLmZpbHRlcih0ZXN0Q2FzZSA9PiAhKHRlc3RDYXNlLnN0YWNrVXBkYXRlV29ya2Zsb3cgPz8gdHJ1ZSkpXG4gICAgICAuZmxhdE1hcCgodGVzdENhc2U6IFRlc3RDYXNlKSA9PiB0ZXN0Q2FzZS5zdGFja3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGVzdCBjYXNlIG9wdGlvbnMgZm9yIGEgZ2l2ZW4gc3RhY2tcbiAgICovXG4gIHB1YmxpYyBnZXRPcHRpb25zRm9yU3RhY2soc3RhY2tJZDogc3RyaW5nKTogVGVzdE9wdGlvbnMgfCB1bmRlZmluZWQge1xuICAgIGZvciAoY29uc3QgdGVzdENhc2Ugb2YgT2JqZWN0LnZhbHVlcyh0aGlzLnRlc3RTdWl0ZSA/PyB7fSkpIHtcbiAgICAgIGlmICh0ZXN0Q2FzZS5zdGFja3MuaW5jbHVkZXMoc3RhY2tJZCkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBob29rczogdGVzdENhc2UuaG9va3MsXG4gICAgICAgICAgcmVnaW9uczogdGVzdENhc2UucmVnaW9ucyxcbiAgICAgICAgICBkaWZmQXNzZXRzOiB0ZXN0Q2FzZS5kaWZmQXNzZXRzID8/IGZhbHNlLFxuICAgICAgICAgIGFsbG93RGVzdHJveTogdGVzdENhc2UuYWxsb3dEZXN0cm95LFxuICAgICAgICAgIGNka0NvbW1hbmRPcHRpb25zOiB0ZXN0Q2FzZS5jZGtDb21tYW5kT3B0aW9ucyxcbiAgICAgICAgICBzdGFja1VwZGF0ZVdvcmtmbG93OiB0ZXN0Q2FzZS5zdGFja1VwZGF0ZVdvcmtmbG93ID8/IHRydWUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgbGlzdCBvZiBzdGFja3MgaW4gdGhlIHRlc3Qgc3VpdGVcbiAgICovXG4gIHB1YmxpYyBnZXQgc3RhY2tzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnRlc3RTdWl0ZSkuZmxhdE1hcCh0ZXN0Q2FzZSA9PiB0ZXN0Q2FzZS5zdGFja3MpO1xuICB9XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYSByZWFkaW5nIGEgbGVnYWN5IHRlc3QgY2FzZSBtYW5pZmVzdFxuICovXG5leHBvcnQgaW50ZXJmYWNlIExlZ2FjeVRlc3RDYXNlQ29uZmlnIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSB0ZXN0IGNhc2VcbiAgICovXG4gIHJlYWRvbmx5IHRlc3ROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgdG8gdXNlIHdoZW4gcGVyZm9ybWluZyBgY2RrIGxpc3RgXG4gICAqIFRoaXMgaXMgdXNlZCB0byBkZXRlcm1pbmUgdGhlIG5hbWUgb2YgdGhlIHN0YWNrc1xuICAgKiBpbiB0aGUgdGVzdCBjYXNlXG4gICAqL1xuICByZWFkb25seSBsaXN0T3B0aW9uczogTGlzdE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEFuIGluc3RhbmNlIG9mIHRoZSBDREsgQ0xJIChlLmcuIENka0NsaVdyYXBwZXIpXG4gICAqL1xuICByZWFkb25seSBjZGs6IElDZGs7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIHRvIHRoZSBpbnRlZ3JhdGlvbiB0ZXN0IGZpbGVcbiAgICogaS5lLiBpbnRlZy50ZXN0LmpzXG4gICAqL1xuICByZWFkb25seSBpbnRlZ1NvdXJjZUZpbGVQYXRoOiBzdHJpbmc7XG59XG5cbi8qKlxuICogSGVscGVyIGNsYXNzIGZvciBjcmVhdGluZyBhbiBpbnRlZyBtYW5pZmVzdCBmb3IgbGVnYWN5XG4gKiB0ZXN0IGNhc2VzLCBpLmUuIHRlc3RzIHdpdGhvdXQgYSBgaW50ZWcuanNvbmAuXG4gKi9cbmV4cG9ydCBjbGFzcyBMZWdhY3lJbnRlZ1Rlc3RTdWl0ZSBleHRlbmRzIEludGVnVGVzdFN1aXRlIHtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHNpbmdsZSB0ZXN0IHN0YWNrIHRvIHVzZS5cbiAgICpcbiAgICogSWYgdGhlIHRlc3QgaGFzIGEgc2luZ2xlIHN0YWNrLCBpdCB3aWxsIGJlIGNob3Nlbi4gT3RoZXJ3aXNlIGEgcHJhZ21hIGlzIGV4cGVjdGVkIHdpdGhpbiB0aGVcbiAgICogdGVzdCBmaWxlIHRoZSBuYW1lIG9mIHRoZSBzdGFjazpcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgLy8vICFjZGstaW50ZWcgPHN0YWNrLW5hbWU+XG4gICAqXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZyb21MZWdhY3koY29uZmlnOiBMZWdhY3lUZXN0Q2FzZUNvbmZpZyk6IFByb21pc2U8TGVnYWN5SW50ZWdUZXN0U3VpdGU+IHtcbiAgICBjb25zdCBwcmFnbWFzID0gdGhpcy5wcmFnbWFzKGNvbmZpZy5pbnRlZ1NvdXJjZUZpbGVQYXRoKTtcbiAgICBjb25zdCB0ZXN0czogVGVzdENhc2UgPSB7XG4gICAgICBzdGFja3M6IFtdLFxuICAgICAgZGlmZkFzc2V0czogcHJhZ21hcy5pbmNsdWRlcyhWRVJJRllfQVNTRVRfSEFTSEVTKSxcbiAgICAgIHN0YWNrVXBkYXRlV29ya2Zsb3c6ICFwcmFnbWFzLmluY2x1ZGVzKERJU0FCTEVfVVBEQVRFX1dPUktGTE9XKSxcbiAgICB9O1xuICAgIGNvbnN0IHByYWdtYSA9IHRoaXMucmVhZFN0YWNrUHJhZ21hKGNvbmZpZy5pbnRlZ1NvdXJjZUZpbGVQYXRoKTtcbiAgICBpZiAocHJhZ21hLmxlbmd0aCA+IDApIHtcbiAgICAgIHRlc3RzLnN0YWNrcy5wdXNoKC4uLnByYWdtYSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG9wdGlvbnM6IExpc3RPcHRpb25zID0ge1xuICAgICAgICAuLi5jb25maWcubGlzdE9wdGlvbnMsXG4gICAgICAgIG5vdGljZXM6IGZhbHNlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHN0YWNrcyA9IGF3YWl0IGNvbmZpZy5jZGsubGlzdChvcHRpb25zKTtcbiAgICAgIGlmIChzdGFja3MubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignXCJpbnRlZy1ydW5uZXJcIiBjYW4gb25seSBvcGVyYXRlIG9uIGFwcHMgd2l0aCBhIHNpbmdsZSBzdGFjay5cXG5cXG4nICtcbiAgICAgICAgICAnICBJZiB5b3VyIGFwcCBoYXMgbXVsdGlwbGUgc3RhY2tzLCBzcGVjaWZ5IHdoaWNoIHN0YWNrIHRvIHNlbGVjdCBieSBhZGRpbmcgdGhpcyB0byB5b3VyIHRlc3Qgc291cmNlOlxcblxcbicgK1xuICAgICAgICAgIGAgICAgICAke0NES19JTlRFR19TVEFDS19QUkFHTUF9IFNUQUNLIC4uLlxcblxcbmAgK1xuICAgICAgICAgIGAgIEF2YWlsYWJsZSBzdGFja3M6ICR7c3RhY2tzLmpvaW4oJyAnKX0gKHdpbGRjYXJkcyBhcmUgYWxzbyBzdXBwb3J0ZWQpXFxuYCk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhY2tzLmxlbmd0aCA9PT0gMSAmJiBzdGFja3NbMF0gPT09ICcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gc3RhY2sgZm91bmQgZm9yIHRlc3QgJHtjb25maWcudGVzdE5hbWV9YCk7XG4gICAgICB9XG4gICAgICB0ZXN0cy5zdGFja3MucHVzaCguLi5zdGFja3MpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGVnYWN5SW50ZWdUZXN0U3VpdGUoXG4gICAgICBwcmFnbWFzLmluY2x1ZGVzKEVOQUJMRV9MT09LVVBTX1BSQUdNQSksXG4gICAgICB7XG4gICAgICAgIFtjb25maWcudGVzdE5hbWVdOiB0ZXN0cyxcbiAgICAgIH0sXG4gICAgICBMZWdhY3lJbnRlZ1Rlc3RTdWl0ZS5nZXRQcmFnbWFDb250ZXh0KGNvbmZpZy5pbnRlZ1NvdXJjZUZpbGVQYXRoKSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXRQcmFnbWFDb250ZXh0KGludGVnU291cmNlRmlsZVBhdGg6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICAgIGNvbnN0IGN0eFByYWdtYUNvbnRleHQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcblxuICAgIC8vIGFwcGx5IGNvbnRleHQgZnJvbSBzZXQtY29udGV4dCBwcmFnbWFcbiAgICAvLyB1c2FnZTogcHJhZ21hOnNldC1jb250ZXh0OmtleT12YWx1ZVxuICAgIGNvbnN0IGN0eFByYWdtYXMgPSAodGhpcy5wcmFnbWFzKGludGVnU291cmNlRmlsZVBhdGgpKS5maWx0ZXIocCA9PiBwLnN0YXJ0c1dpdGgoU0VUX0NPTlRFWFRfUFJBR01BX1BSRUZJWCkpO1xuICAgIGZvciAoY29uc3QgcCBvZiBjdHhQcmFnbWFzKSB7XG4gICAgICBjb25zdCBpbnN0cnVjdGlvbiA9IHAuc3Vic3RyaW5nKFNFVF9DT05URVhUX1BSQUdNQV9QUkVGSVgubGVuZ3RoKTtcbiAgICAgIGNvbnN0IFtrZXksIHZhbHVlXSA9IGluc3RydWN0aW9uLnNwbGl0KCc9Jyk7XG4gICAgICBpZiAoa2V5ID09IG51bGwgfHwgdmFsdWUgPT0gbnVsbCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgXCJzZXQtY29udGV4dFwiIHByYWdtYSBzeW50YXguIGV4YW1wbGU6IFwicHJhZ21hOnNldC1jb250ZXh0OkBhd3MtY2RrL2NvcmU6bmV3U3R5bGVTdGFja1N5bnRoZXNpcz10cnVlXCIgZ290OiAke3B9YCk7XG4gICAgICB9XG5cbiAgICAgIGN0eFByYWdtYUNvbnRleHRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgLi4uY3R4UHJhZ21hQ29udGV4dCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWRzIHN0YWNrIG5hbWVzIGZyb20gdGhlIFwiIWNkay1pbnRlZ1wiIHByYWdtYS5cbiAgICpcbiAgICogRXZlcnkgd29yZCB0aGF0J3MgTk9UIHByZWZpeGVkIGJ5IFwicHJhZ21hOlwiIGlzIGNvbnNpZGVyZWQgYSBzdGFjayBuYW1lLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAgICAvLy8gIWNkay1pbnRlZyA8c3RhY2stbmFtZT5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlYWRTdGFja1ByYWdtYShpbnRlZ1NvdXJjZUZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuICh0aGlzLnJlYWRJbnRlZ1ByYWdtYShpbnRlZ1NvdXJjZUZpbGVQYXRoKSkuZmlsdGVyKHAgPT4gIXAuc3RhcnRzV2l0aChQUkFHTUFfUFJFRklYKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVhZCBhcmJpdHJhcnkgY2RrLWludGVnIHByYWdtYSBkaXJlY3RpdmVzXG4gICAqXG4gICAqIFJlYWRzIHRoZSB0ZXN0IHNvdXJjZSBmaWxlIGFuZCBsb29rcyBmb3IgdGhlIFwiIWNkay1pbnRlZ1wiIHByYWdtYS4gSWYgaXQgZXhpc3RzLCByZXR1cm5zIGl0J3NcbiAgICogY29udGVudHMuIFRoaXMgYWxsb3dzIGludGVnIHRlc3RzIHRvIHN1cHBseSBjdXN0b20gY29tbWFuZCBsaW5lIGFyZ3VtZW50cyB0byBcImNkayBkZXBsb3lcIiBhbmQgXCJjZGsgc3ludGhcIi5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgLy8vICFjZGstaW50ZWcgWy4uLl1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlYWRJbnRlZ1ByYWdtYShpbnRlZ1NvdXJjZUZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgc291cmNlID0gZnMucmVhZEZpbGVTeW5jKGludGVnU291cmNlRmlsZVBhdGgsIHsgZW5jb2Rpbmc6ICd1dGYtOCcgfSk7XG4gICAgY29uc3QgcHJhZ21hTGluZSA9IHNvdXJjZS5zcGxpdCgnXFxuJykuZmluZCh4ID0+IHguc3RhcnRzV2l0aChDREtfSU5URUdfU1RBQ0tfUFJBR01BICsgJyAnKSk7XG4gICAgaWYgKCFwcmFnbWFMaW5lKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgY29uc3QgYXJncyA9IHByYWdtYUxpbmUuc3Vic3RyaW5nKENES19JTlRFR19TVEFDS19QUkFHTUEubGVuZ3RoKS50cmltKCkuc3BsaXQoJyAnKTtcbiAgICBpZiAoYXJncy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBzeW50YXggZm9yIGNkay1pbnRlZyBwcmFnbWEuIFVzYWdlOiBcIiR7Q0RLX0lOVEVHX1NUQUNLX1BSQUdNQX0gW1NUQUNLXSBbcHJhZ21hOlBSQUdNQV0gWy4uLl1cImApO1xuICAgIH1cbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIG5vbi1zdGFjayBwcmFnbWFzXG4gICAqXG4gICAqIFRoZXNlIGFyZSBhbGwgcHJhZ21hcyB0aGF0IHN0YXJ0IHdpdGggXCJwcmFnbWE6XCIuXG4gICAqXG4gICAqIEZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSByZWFzb25zLCBhbGwgcHJhZ21hcyB0aGF0IERPTidUIHN0YXJ0IHdpdGggdGhpc1xuICAgKiBzdHJpbmcgYXJlIGNvbnNpZGVyZWQgdG8gYmUgc3RhY2sgbmFtZXMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBwcmFnbWFzKGludGVnU291cmNlRmlsZVBhdGg6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gKHRoaXMucmVhZEludGVnUHJhZ21hKGludGVnU291cmNlRmlsZVBhdGgpKS5maWx0ZXIocCA9PiBwLnN0YXJ0c1dpdGgoUFJBR01BX1BSRUZJWCkpO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHR5cGU6IFRlc3RTdWl0ZVR5cGUgPSAnbGVnYWN5LXRlc3Qtc3VpdGUnO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBlbmFibGVMb29rdXBzOiBib29sZWFuLFxuICAgIHB1YmxpYyByZWFkb25seSB0ZXN0U3VpdGU6IFRlc3RTdWl0ZSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgc3ludGhDb250ZXh0PzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICkge1xuICAgIHN1cGVyKGVuYWJsZUxvb2t1cHMsIHRlc3RTdWl0ZSk7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSB0aGUgaW50ZWcgbWFuaWZlc3QgdG8gYSBkaXJlY3RvcnlcbiAgICovXG4gIHB1YmxpYyBzYXZlTWFuaWZlc3QoZGlyZWN0b3J5OiBzdHJpbmcsIGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogdm9pZCB7XG4gICAgY29uc3QgbWFuaWZlc3Q6IEludGVnTWFuaWZlc3QgPSB7XG4gICAgICB2ZXJzaW9uOiBNYW5pZmVzdC52ZXJzaW9uKCksXG4gICAgICB0ZXN0Q2FzZXM6IHRoaXMudGVzdFN1aXRlLFxuICAgICAgc3ludGhDb250ZXh0OiBjb250ZXh0LFxuICAgICAgZW5hYmxlTG9va3VwczogdGhpcy5lbmFibGVMb29rdXBzLFxuICAgIH07XG4gICAgTWFuaWZlc3Quc2F2ZUludGVnTWFuaWZlc3QobWFuaWZlc3QsIG9zUGF0aC5qb2luKGRpcmVjdG9yeSwgSW50ZWdNYW5pZmVzdFJlYWRlci5ERUZBVUxUX0ZJTEVOQU1FKSk7XG4gIH1cbn1cbiJdfQ==