UNPKG

@aws-cdk/integ-runner

Version:

CDK Integration Testing Tool

198 lines 26.1 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 { /** * 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); } constructor(enableLookups, testSuite, synthContext) { this.enableLookups = enableLookups; this.testSuite = testSuite; this.synthContext = synthContext; this.type = 'test-suite'; } /** * 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 { /** * 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)); } constructor(enableLookups, testSuite, synthContext) { super(enableLookups, testSuite); this.enableLookups = enableLookups; this.testSuite = testSuite; this.synthContext = synthContext; this.type = 'legacy-test-suite'; } /** * 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWctdGVzdC1zdWl0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImludGVnLXRlc3Qtc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQStCO0FBRy9CLDBFQUEwRDtBQUMxRCwrQkFBK0I7QUFDL0IsNkRBQStEO0FBRS9ELE1BQU0sc0JBQXNCLEdBQUcsZ0JBQWdCLENBQUM7QUFDaEQsTUFBTSxhQUFhLEdBQUcsU0FBUyxDQUFDO0FBQ2hDLE1BQU0seUJBQXlCLEdBQUcscUJBQXFCLENBQUM7QUFDeEQsTUFBTSxtQkFBbUIsR0FBRyw4QkFBOEIsQ0FBQztBQUMzRCxNQUFNLHVCQUF1QixHQUFHLGdDQUFnQyxDQUFDO0FBQ2pFLE1BQU0scUJBQXFCLEdBQUcsdUJBQXVCLENBQUM7QUFTdEQ7Ozs7R0FJRztBQUNILE1BQWEsY0FBYztJQUN6Qjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBWTtRQUNqQyxNQUFNLE1BQU0sR0FBRyxvQ0FBbUIsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEQsT0FBTyxJQUFJLGNBQWMsQ0FDdkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUN0QixNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FDMUIsQ0FBQztJQUNKLENBQUM7SUFJRCxZQUNrQixhQUFzQixFQUN0QixTQUFvQixFQUNwQixZQUF5QztRQUZ6QyxrQkFBYSxHQUFiLGFBQWEsQ0FBUztRQUN0QixjQUFTLEdBQVQsU0FBUyxDQUFXO1FBQ3BCLGlCQUFZLEdBQVosWUFBWSxDQUE2QjtRQUwzQyxTQUFJLEdBQWtCLFlBQVksQ0FBQztJQU9uRCxDQUFDO0lBRUQ7O09BRUc7SUFDSSw4QkFBOEI7UUFDbkMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7YUFDakMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxF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QUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUlELFlBQ2tCLGFBQXNCLEVBQ3RCLFNBQW9CLEVBQ3BCLFlBQXlDO1FBRXpELEtBQUssQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFKaEIsa0JBQWEsR0FBYixhQUFhLENBQVM7UUFDdEIsY0FBUyxHQUFULFNBQVMsQ0FBVztRQUNwQixpQkFBWSxHQUFaLFlBQVksQ0FBNkI7UUFMM0MsU0FBSSxHQUFrQixtQkFBbUIsQ0FBQztJQVExRCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxZQUFZLENBQUMsU0FBaUIsRUFBRSxPQUE2QjtRQUNsRSxNQUFNLFFBQVEsR0FBa0I7WUFDOUIsT0FBTyxFQUFFLGdDQUFRLENBQUMsT0FBTyxFQUFFO1lBQzNCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixZQUFZLEVBQUUsT0FBTztZQUNyQixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7U0FDbEMsQ0FBQztRQUNGLGdDQUFRLENBQUMsaUJBQWlCLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLG9DQUFtQixDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0NBQ0Y7QUE1SUQsb0RBNElDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgb3NQYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHR5cGUgeyBJQ2RrLCBMaXN0T3B0aW9ucyB9IGZyb20gJ0Bhd3MtY2RrL2Nkay1jbGktd3JhcHBlcic7XG5pbXBvcnQgdHlwZSB7IFRlc3RDYXNlLCBUZXN0T3B0aW9ucywgSW50ZWdNYW5pZmVzdCB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBNYW5pZmVzdCB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBJbnRlZ01hbmlmZXN0UmVhZGVyIH0gZnJvbSAnLi9wcml2YXRlL2ludGVnLW1hbmlmZXN0JztcblxuY29uc3QgQ0RLX0lOVEVHX1NUQUNLX1BSQUdNQSA9ICcvLy8gIWNkay1pbnRlZyc7XG5jb25zdCBQUkFHTUFfUFJFRklYID0gJ3ByYWdtYTonO1xuY29uc3QgU0VUX0NPTlRFWFRfUFJBR01BX1BSRUZJWCA9ICdwcmFnbWE6c2V0LWNvbnRleHQ6JztcbmNvbnN0IFZFUklGWV9BU1NFVF9IQVNIRVMgPSAncHJhZ21hOmluY2x1ZGUtYXNzZXRzLWhhc2hlcyc7XG5jb25zdCBESVNBQkxFX1VQREFURV9XT1JLRkxPVyA9ICdwcmFnbWE6ZGlzYWJsZS11cGRhdGUtd29ya2Zsb3cnO1xuY29uc3QgRU5BQkxFX0xPT0tVUFNfUFJBR01BID0gJ3ByYWdtYTplbmFibGUtbG9va3Vwcyc7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBpbnRlZ3JhdGlvbiB0ZXN0XG4gKi9cbmV4cG9ydCB0eXBlIFRlc3RTdWl0ZSA9IHsgW3Rlc3ROYW1lOiBzdHJpbmddOiBUZXN0Q2FzZSB9O1xuXG5leHBvcnQgdHlwZSBUZXN0U3VpdGVUeXBlID0gJ3Rlc3Qtc3VpdGUnIHwgJ2xlZ2FjeS10ZXN0LXN1aXRlJztcblxuLyoqXG4gKiBIZWxwZXIgY2xhc3MgZm9yIHdvcmtpbmcgd2l0aCBJbnRlZ3JhdGlvbiB0ZXN0c1xuICogVGhpcyByZXF1aXJlcyBhbiBgaW50ZWcuanNvbmAgZmlsZSBpbiB0aGUgc25hcHNob3RcbiAqIGRpcmVjdG9yeS4gRm9yIGxlZ2FjeSB0ZXN0IGNhc2VzIHVzZSBMZWdhY3lJbnRlZ1Rlc3RDYXNlc1xuICovXG5leHBvcnQgY2xhc3MgSW50ZWdUZXN0U3VpdGUge1xuICAvKipcbiAgICogTG9hZHMgaW50ZWcgdGVzdHMgZnJvbSBhIHNuYXBzaG90IGRpcmVjdG9yeVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tUGF0aChwYXRoOiBzdHJpbmcpOiBJbnRlZ1Rlc3RTdWl0ZSB7XG4gICAgY29uc3QgcmVhZGVyID0gSW50ZWdNYW5pZmVzdFJlYWRlci5mcm9tUGF0aChwYXRoKTtcbiAgICByZXR1cm4gbmV3IEludGVnVGVzdFN1aXRlKFxuICAgICAgcmVhZGVyLnRlc3RzLmVuYWJsZUxvb2t1cHMsXG4gICAgICByZWFkZXIudGVzdHMudGVzdENhc2VzLFxuICAgICAgcmVhZGVyLnRlc3RzLnN5bnRoQ29udGV4dCxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHR5cGU6IFRlc3RTdWl0ZVR5cGUgPSAndGVzdC1zdWl0ZSc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHJlYWRvbmx5IGVuYWJsZUxvb2t1cHM6IGJvb2xlYW4sXG4gICAgcHVibGljIHJlYWRvbmx5IHRlc3RTdWl0ZTogVGVzdFN1aXRlLFxuICAgIHB1YmxpYyByZWFkb25seSBzeW50aENvbnRleHQ/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgKSB7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxpc3Qgb2Ygc3RhY2tzIHRoYXQgaGF2ZSBzdGFja1VwZGF0ZVdvcmtmbG93IGRpc2FibGVkXG4gICAqL1xuICBwdWJsaWMgZ2V0U3RhY2tzV2l0aG91dFVwZGF0ZVdvcmtmbG93KCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnRlc3RTdWl0ZSlcbiAgICAgIC5maWx0ZXIodGVzdENhc2UgPT4gISh0ZXN0Q2FzZS5zdGFja1VwZGF0ZVdvcmtmbG93ID8/IHRydWUpKVxuICAgICAgLmZsYXRNYXAoKHRlc3RDYXNlOiBUZXN0Q2FzZSkgPT4gdGVzdENhc2Uuc3RhY2tzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRlc3QgY2FzZSBvcHRpb25zIGZvciBhIGdpdmVuIHN0YWNrXG4gICAqL1xuICBwdWJsaWMgZ2V0T3B0aW9uc0ZvclN0YWNrKHN0YWNrSWQ6IHN0cmluZyk6IFRlc3RPcHRpb25zIHwgdW5kZWZpbmVkIHtcbiAgICBmb3IgKGNvbnN0IHRlc3RDYXNlIG9mIE9iamVjdC52YWx1ZXModGhpcy50ZXN0U3VpdGUgPz8ge30pKSB7XG4gICAgICBpZiAodGVzdENhc2Uuc3RhY2tzLmluY2x1ZGVzKHN0YWNrSWQpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgaG9va3M6IHRlc3RDYXNlLmhvb2tzLFxuICAgICAgICAgIHJlZ2lvbnM6IHRlc3RDYXNlLnJlZ2lvbnMsXG4gICAgICAgICAgZGlmZkFzc2V0czogdGVzdENhc2UuZGlmZkFzc2V0cyA/PyBmYWxzZSxcbiAgICAgICAgICBhbGxvd0Rlc3Ryb3k6IHRlc3RDYXNlLmFsbG93RGVzdHJveSxcbiAgICAgICAgICBjZGtDb21tYW5kT3B0aW9uczogdGVzdENhc2UuY2RrQ29tbWFuZE9wdGlvbnMsXG4gICAgICAgICAgc3RhY2tVcGRhdGVXb3JrZmxvdzogdGVzdENhc2Uuc3RhY2tVcGRhdGVXb3JrZmxvdyA/PyB0cnVlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIGxpc3Qgb2Ygc3RhY2tzIGluIHRoZSB0ZXN0IHN1aXRlXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWNrcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy50ZXN0U3VpdGUpLmZsYXRNYXAodGVzdENhc2UgPT4gdGVzdENhc2Uuc3RhY2tzKTtcbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGEgcmVhZGluZyBhIGxlZ2FjeSB0ZXN0IGNhc2UgbWFuaWZlc3RcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMZWdhY3lUZXN0Q2FzZUNvbmZpZyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgdGVzdCBjYXNlXG4gICAqL1xuICByZWFkb25seSB0ZXN0TmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBPcHRpb25zIHRvIHVzZSB3aGVuIHBlcmZvcm1pbmcgYGNkayBsaXN0YFxuICAgKiBUaGlzIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZSBuYW1lIG9mIHRoZSBzdGFja3NcbiAgICogaW4gdGhlIHRlc3QgY2FzZVxuICAgKi9cbiAgcmVhZG9ubHkgbGlzdE9wdGlvbnM6IExpc3RPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBbiBpbnN0YW5jZSBvZiB0aGUgQ0RLIENMSSAoZS5nLiBDZGtDbGlXcmFwcGVyKVxuICAgKi9cbiAgcmVhZG9ubHkgY2RrOiBJQ2RrO1xuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCB0byB0aGUgaW50ZWdyYXRpb24gdGVzdCBmaWxlXG4gICAqIGkuZS4gaW50ZWcudGVzdC5qc1xuICAgKi9cbiAgcmVhZG9ubHkgaW50ZWdTb3VyY2VGaWxlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEhlbHBlciBjbGFzcyBmb3IgY3JlYXRpbmcgYW4gaW50ZWcgbWFuaWZlc3QgZm9yIGxlZ2FjeVxuICogdGVzdCBjYXNlcywgaS5lLiB0ZXN0cyB3aXRob3V0IGEgYGludGVnLmpzb25gLlxuICovXG5leHBvcnQgY2xhc3MgTGVnYWN5SW50ZWdUZXN0U3VpdGUgZXh0ZW5kcyBJbnRlZ1Rlc3RTdWl0ZSB7XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzaW5nbGUgdGVzdCBzdGFjayB0byB1c2UuXG4gICAqXG4gICAqIElmIHRoZSB0ZXN0IGhhcyBhIHNpbmdsZSBzdGFjaywgaXQgd2lsbCBiZSBjaG9zZW4uIE90aGVyd2lzZSBhIHByYWdtYSBpcyBleHBlY3RlZCB3aXRoaW4gdGhlXG4gICAqIHRlc3QgZmlsZSB0aGUgbmFtZSBvZiB0aGUgc3RhY2s6XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIC8vLyAhY2RrLWludGVnIDxzdGFjay1uYW1lPlxuICAgKlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhc3luYyBmcm9tTGVnYWN5KGNvbmZpZzogTGVnYWN5VGVzdENhc2VDb25maWcpOiBQcm9taXNlPExlZ2FjeUludGVnVGVzdFN1aXRlPiB7XG4gICAgY29uc3QgcHJhZ21hcyA9IHRoaXMucHJhZ21hcyhjb25maWcuaW50ZWdTb3VyY2VGaWxlUGF0aCk7XG4gICAgY29uc3QgdGVzdHM6IFRlc3RDYXNlID0ge1xuICAgICAgc3RhY2tzOiBbXSxcbiAgICAgIGRpZmZBc3NldHM6IHByYWdtYXMuaW5jbHVkZXMoVkVSSUZZX0FTU0VUX0hBU0hFUyksXG4gICAgICBzdGFja1VwZGF0ZVdvcmtmbG93OiAhcHJhZ21hcy5pbmNsdWRlcyhESVNBQkxFX1VQREFURV9XT1JLRkxPVyksXG4gICAgfTtcbiAgICBjb25zdCBwcmFnbWEgPSB0aGlzLnJlYWRTdGFja1ByYWdtYShjb25maWcuaW50ZWdTb3VyY2VGaWxlUGF0aCk7XG4gICAgaWYgKHByYWdtYS5sZW5ndGggPiAwKSB7XG4gICAgICB0ZXN0cy5zdGFja3MucHVzaCguLi5wcmFnbWEpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBvcHRpb25zOiBMaXN0T3B0aW9ucyA9IHtcbiAgICAgICAgLi4uY29uZmlnLmxpc3RPcHRpb25zLFxuICAgICAgICBub3RpY2VzOiBmYWxzZSxcbiAgICAgIH07XG4gICAgICBjb25zdCBzdGFja3MgPSBhd2FpdCBjb25maWcuY2RrLmxpc3Qob3B0aW9ucyk7XG4gICAgICBpZiAoc3RhY2tzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1wiaW50ZWctcnVubmVyXCIgY2FuIG9ubHkgb3BlcmF0ZSBvbiBhcHBzIHdpdGggYSBzaW5nbGUgc3RhY2suXFxuXFxuJyArXG4gICAgICAgICAgJyAgSWYgeW91ciBhcHAgaGFzIG11bHRpcGxlIHN0YWNrcywgc3BlY2lmeSB3aGljaCBzdGFjayB0byBzZWxlY3QgYnkgYWRkaW5nIHRoaXMgdG8geW91ciB0ZXN0IHNvdXJjZTpcXG5cXG4nICtcbiAgICAgICAgICBgICAgICAgJHtDREtfSU5URUdfU1RBQ0tfUFJBR01BfSBTVEFDSyAuLi5cXG5cXG5gICtcbiAgICAgICAgICBgICBBdmFpbGFibGUgc3RhY2tzOiAke3N0YWNrcy5qb2luKCcgJyl9ICh3aWxkY2FyZHMgYXJlIGFsc28gc3VwcG9ydGVkKVxcbmApO1xuICAgICAgfVxuICAgICAgaWYgKHN0YWNrcy5sZW5ndGggPT09IDEgJiYgc3RhY2tzWzBdID09PSAnJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHN0YWNrIGZvdW5kIGZvciB0ZXN0ICR7Y29uZmlnLnRlc3ROYW1lfWApO1xuICAgICAgfVxuICAgICAgdGVzdHMuc3RhY2tzLnB1c2goLi4uc3RhY2tzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IExlZ2FjeUludGVnVGVzdFN1aXRlKFxuICAgICAgcHJhZ21hcy5pbmNsdWRlcyhFTkFCTEVfTE9PS1VQU19QUkFHTUEpLFxuICAgICAge1xuICAgICAgICBbY29uZmlnLnRlc3ROYW1lXTogdGVzdHMsXG4gICAgICB9LFxuICAgICAgTGVnYWN5SW50ZWdUZXN0U3VpdGUuZ2V0UHJhZ21hQ29udGV4dChjb25maWcuaW50ZWdTb3VyY2VGaWxlUGF0aCksXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZ2V0UHJhZ21hQ29udGV4dChpbnRlZ1NvdXJjZUZpbGVQYXRoOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICBjb25zdCBjdHhQcmFnbWFDb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG5cbiAgICAvLyBhcHBseSBjb250ZXh0IGZyb20gc2V0LWNvbnRleHQgcHJhZ21hXG4gICAgLy8gdXNhZ2U6IHByYWdtYTpzZXQtY29udGV4dDprZXk9dmFsdWVcbiAgICBjb25zdCBjdHhQcmFnbWFzID0gKHRoaXMucHJhZ21hcyhpbnRlZ1NvdXJjZUZpbGVQYXRoKSkuZmlsdGVyKHAgPT4gcC5zdGFydHNXaXRoKFNFVF9DT05URVhUX1BSQUdNQV9QUkVGSVgpKTtcbiAgICBmb3IgKGNvbnN0IHAgb2YgY3R4UHJhZ21hcykge1xuICAgICAgY29uc3QgaW5zdHJ1Y3Rpb24gPSBwLnN1YnN0cmluZyhTRVRfQ09OVEVYVF9QUkFHTUFfUFJFRklYLmxlbmd0aCk7XG4gICAgICBjb25zdCBba2V5LCB2YWx1ZV0gPSBpbnN0cnVjdGlvbi5zcGxpdCgnPScpO1xuICAgICAgaWYgKGtleSA9PSBudWxsIHx8IHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIFwic2V0LWNvbnRleHRcIiBwcmFnbWEgc3ludGF4LiBleGFtcGxlOiBcInByYWdtYTpzZXQtY29udGV4dDpAYXdzLWNkay9jb3JlOm5ld1N0eWxlU3RhY2tTeW50aGVzaXM9dHJ1ZVwiIGdvdDogJHtwfWApO1xuICAgICAgfVxuXG4gICAgICBjdHhQcmFnbWFDb250ZXh0W2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmN0eFByYWdtYUNvbnRleHQsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBzdGFjayBuYW1lcyBmcm9tIHRoZSBcIiFjZGstaW50ZWdcIiBwcmFnbWEuXG4gICAqXG4gICAqIEV2ZXJ5IHdvcmQgdGhhdCdzIE5PVCBwcmVmaXhlZCBieSBcInByYWdtYTpcIiBpcyBjb25zaWRlcmVkIGEgc3RhY2sgbmFtZS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICpcbiAgICogICAgLy8vICFjZGstaW50ZWcgPHN0YWNrLW5hbWU+XG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkU3RhY2tQcmFnbWEoaW50ZWdTb3VyY2VGaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIHJldHVybiAodGhpcy5yZWFkSW50ZWdQcmFnbWEoaW50ZWdTb3VyY2VGaWxlUGF0aCkpLmZpbHRlcihwID0+ICFwLnN0YXJ0c1dpdGgoUFJBR01BX1BSRUZJWCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWQgYXJiaXRyYXJ5IGNkay1pbnRlZyBwcmFnbWEgZGlyZWN0aXZlc1xuICAgKlxuICAgKiBSZWFkcyB0aGUgdGVzdCBzb3VyY2UgZmlsZSBhbmQgbG9va3MgZm9yIHRoZSBcIiFjZGstaW50ZWdcIiBwcmFnbWEuIElmIGl0IGV4aXN0cywgcmV0dXJucyBpdCdzXG4gICAqIGNvbnRlbnRzLiBUaGlzIGFsbG93cyBpbnRlZyB0ZXN0cyB0byBzdXBwbHkgY3VzdG9tIGNvbW1hbmQgbGluZSBhcmd1bWVudHMgdG8gXCJjZGsgZGVwbG95XCIgYW5kIFwiY2RrIHN5bnRoXCIuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIC8vLyAhY2RrLWludGVnIFsuLi5dXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkSW50ZWdQcmFnbWEoaW50ZWdTb3VyY2VGaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHNvdXJjZSA9IGZzLnJlYWRGaWxlU3luYyhpbnRlZ1NvdXJjZUZpbGVQYXRoLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pO1xuICAgIGNvbnN0IHByYWdtYUxpbmUgPSBzb3VyY2Uuc3BsaXQoJ1xcbicpLmZpbmQoeCA9PiB4LnN0YXJ0c1dpdGgoQ0RLX0lOVEVHX1NUQUNLX1BSQUdNQSArICcgJykpO1xuICAgIGlmICghcHJhZ21hTGluZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGFyZ3MgPSBwcmFnbWFMaW5lLnN1YnN0cmluZyhDREtfSU5URUdfU1RBQ0tfUFJBR01BLmxlbmd0aCkudHJpbSgpLnNwbGl0KCcgJyk7XG4gICAgaWYgKGFyZ3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgc3ludGF4IGZvciBjZGstaW50ZWcgcHJhZ21hLiBVc2FnZTogXCIke0NES19JTlRFR19TVEFDS19QUkFHTUF9IFtTVEFDS10gW3ByYWdtYTpQUkFHTUFdIFsuLi5dXCJgKTtcbiAgICB9XG4gICAgcmV0dXJuIGFyZ3M7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBub24tc3RhY2sgcHJhZ21hc1xuICAgKlxuICAgKiBUaGVzZSBhcmUgYWxsIHByYWdtYXMgdGhhdCBzdGFydCB3aXRoIFwicHJhZ21hOlwiLlxuICAgKlxuICAgKiBGb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgcmVhc29ucywgYWxsIHByYWdtYXMgdGhhdCBET04nVCBzdGFydCB3aXRoIHRoaXNcbiAgICogc3RyaW5nIGFyZSBjb25zaWRlcmVkIHRvIGJlIHN0YWNrIG5hbWVzLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcHJhZ21hcyhpbnRlZ1NvdXJjZUZpbGVQYXRoOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuICh0aGlzLnJlYWRJbnRlZ1ByYWdtYShpbnRlZ1NvdXJjZUZpbGVQYXRoKSkuZmlsdGVyKHAgPT4gcC5zdGFydHNXaXRoKFBSQUdNQV9QUkVGSVgpKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSB0eXBlOiBUZXN0U3VpdGVUeXBlID0gJ2xlZ2FjeS10ZXN0LXN1aXRlJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgZW5hYmxlTG9va3VwczogYm9vbGVhbixcbiAgICBwdWJsaWMgcmVhZG9ubHkgdGVzdFN1aXRlOiBUZXN0U3VpdGUsXG4gICAgcHVibGljIHJlYWRvbmx5IHN5bnRoQ29udGV4dD86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9LFxuICApIHtcbiAgICBzdXBlcihlbmFibGVMb29rdXBzLCB0ZXN0U3VpdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNhdmUgdGhlIGludGVnIG1hbmlmZXN0IHRvIGEgZGlyZWN0b3J5XG4gICAqL1xuICBwdWJsaWMgc2F2ZU1hbmlmZXN0KGRpcmVjdG9yeTogc3RyaW5nLCBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgYW55Pik6IHZvaWQge1xuICAgIGNvbnN0IG1hbmlmZXN0OiBJbnRlZ01hbmlmZXN0ID0ge1xuICAgICAgdmVyc2lvbjogTWFuaWZlc3QudmVyc2lvbigpLFxuICAgICAgdGVzdENhc2VzOiB0aGlzLnRlc3RTdWl0ZSxcbiAgICAgIHN5bnRoQ29udGV4dDogY29udGV4dCxcbiAgICAgIGVuYWJsZUxvb2t1cHM6IHRoaXMuZW5hYmxlTG9va3VwcyxcbiAgICB9O1xuICAgIE1hbmlmZXN0LnNhdmVJbnRlZ01hbmlmZXN0KG1hbmlmZXN0LCBvc1BhdGguam9pbihkaXJlY3RvcnksIEludGVnTWFuaWZlc3RSZWFkZXIuREVGQVVMVF9GSUxFTkFNRSkpO1xuICB9XG59XG4iXX0=