aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
186 lines • 48.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const os = require("os");
const path = require("path");
const util_1 = require("util");
const fs = require("fs-extra");
const migrate_1 = require("../../lib/commands/migrate");
const mock_sdk_1 = require("../util/mock-sdk");
const exec = (0, util_1.promisify)(child_process_1.exec);
describe('Migrate Function Tests', () => {
let sdkProvider;
let getTemplateMock;
let cfnMocks;
const testResourcePath = [__dirname, 'test-resources'];
const templatePath = [...testResourcePath, 'templates'];
const stackPath = [...testResourcePath, 'stacks'];
const validTemplatePath = path.join(...templatePath, 's3-template.json');
const validTemplate = (0, migrate_1.readFromPath)(validTemplatePath);
beforeEach(() => {
sdkProvider = new mock_sdk_1.MockSdkProvider();
getTemplateMock = jest.fn();
cfnMocks = { getTemplate: getTemplateMock };
sdkProvider.stubCloudFormation(cfnMocks);
});
test('validateSourceOptions throws if both --from-path and --from-stack is provided', () => {
expect(() => (0, migrate_1.validateSourceOptions)('any-value', true)).toThrowError('Only one of `--from-path` or `--from-stack` may be provided.');
});
test('validateSourceOptions throws if neither --from-path or --from-stack is provided', () => {
expect(() => (0, migrate_1.validateSourceOptions)(undefined, undefined)).toThrowError('Either `--from-path` or `--from-stack` must be used to provide the source of the CloudFormation template.');
});
test('validateSourceOptions does not throw when only --from-path is supplied', () => {
expect(() => (0, migrate_1.validateSourceOptions)('any-value', false)).not.toThrow();
});
test('validateSourceOptions does now throw when only --from-stack is provided', () => {
expect(() => (0, migrate_1.validateSourceOptions)(undefined, true)).not.toThrow();
});
test('readFromPath produces a string representation of the template at a given path', () => {
expect((0, migrate_1.readFromPath)(validTemplatePath)).toEqual(fs.readFileSync(validTemplatePath, 'utf8'));
});
test('readFromPath returns undefined when template file is not provided', () => {
expect((0, migrate_1.readFromPath)()).toEqual(undefined);
});
test('readFromPath throws error when template file does not exist at a given path', () => {
const badTemplatePath = './not-here.json';
expect(() => (0, migrate_1.readFromPath)(badTemplatePath)).toThrowError(`\'${badTemplatePath}\' is not a valid path.`);
});
test('readFromStack produces a string representation of the template retrieved from CloudFormation', async () => {
const template = fs.readFileSync(validTemplatePath);
getTemplateMock.mockImplementationOnce(() => ({
TemplateBody: template,
}));
expect(await (0, migrate_1.readFromStack)('this-one', sdkProvider, { account: 'num', region: 'here', name: 'hello-my-name-is-what...' })).toEqual(template);
});
test('readFromStack throws error when no stack exists with the stack name in the account and region', async () => {
getTemplateMock.mockImplementationOnce(() => { throw new Error('No stack. This did not go well.'); });
await expect(() => (0, migrate_1.readFromStack)('that-one', sdkProvider, { account: 'num', region: 'here', name: 'hello-my-name-is-who...' })).rejects.toThrowError('No stack. This did not go well.');
});
test('setEnvironment sets account and region when provided', () => {
expect((0, migrate_1.setEnvironment)('my-account', 'somewhere')).toEqual({ account: 'my-account', region: 'somewhere', name: 'cdk-migrate-env' });
});
test('serEnvironment uses default account and region when not provided', () => {
expect((0, migrate_1.setEnvironment)()).toEqual({ account: 'unknown-account', region: 'unknown-region', name: 'cdk-migrate-env' });
});
test('generateStack generates the expected stack string when called for typescript', () => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodTypeScript', 'typescript');
expect(stack).toEqual(fs.readFileSync(path.join(...stackPath, 's3-stack.ts'), 'utf8'));
});
test('generateStack generates the expected stack string when called for python', () => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodPython', 'python');
expect(stack).toEqual(fs.readFileSync(path.join(...stackPath, 's3_stack.py'), 'utf8'));
});
test('generateStack generates the expected stack string when called for java', () => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodJava', 'java');
expect(stack).toEqual(fs.readFileSync(path.join(...stackPath, 'S3Stack.java'), 'utf8'));
});
test('generateStack generates the expected stack string when called for csharp', () => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodCSharp', 'csharp');
expect(stack).toEqual(fs.readFileSync(path.join(...stackPath, 'S3Stack.cs'), 'utf8'));
});
// TODO: fix with actual go template
test('generateStack generates the expected stack string when called for go', () => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodGo', 'go');
expect(stack).toEqual(fs.readFileSync(path.join(...stackPath, 's3.go'), 'utf8'));
});
test('generateStack throws error when called for other language', () => {
expect(() => (0, migrate_1.generateStack)(validTemplate, 'BadBadBad', 'php')).toThrowError('stack generation failed due to error \'unreachable\'');
});
cliTest('generateCdkApp generates the expected cdk app when called for typescript', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodTypeScript', 'typescript');
await (0, migrate_1.generateCdkApp)('GoodTypeScript', stack, 'typescript', workDir);
// Packages exist in the correct spot
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'package.json'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'bin', 'good_type_script.ts'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'lib', 'good_type_script-stack.ts'))).toBeTruthy();
// Replaced stack file is referenced correctly in app file
const app = fs.readFileSync(path.join(workDir, 'GoodTypeScript', 'bin', 'good_type_script.ts'), 'utf8').split('\n');
expect(app.map(line => line.match('import { GoodTypeScriptStack } from \'../lib/good_type_script-stack\';')).filter(line => line).length).toEqual(1);
expect(app.map(line => line.match(/new GoodTypeScriptStack\(app, \'GoodTypeScript\', \{/)).filter(line => line).length).toEqual(1);
// Replaced stack file is correctly generated
const replacedStack = fs.readFileSync(path.join(workDir, 'GoodTypeScript', 'lib', 'good_type_script-stack.ts'), 'utf8');
expect(replacedStack).toEqual(fs.readFileSync(path.join(...stackPath, 's3-stack.ts'), 'utf8'));
});
cliTest('generateCdkApp generates the expected cdk app when called for python', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodPython', 'python');
await (0, migrate_1.generateCdkApp)('GoodPython', stack, 'python', workDir);
// Packages exist in the correct spot
expect(fs.pathExistsSync(path.join(workDir, 'GoodPython', 'requirements.txt'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodPython', 'app.py'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodPython', 'good_python', 'good_python_stack.py'))).toBeTruthy();
// Replaced stack file is referenced correctly in app file
const app = fs.readFileSync(path.join(workDir, 'GoodPython', 'app.py'), 'utf8').split('\n');
expect(app.map(line => line.match('from good_python.good_python_stack import GoodPythonStack')).filter(line => line).length).toEqual(1);
expect(app.map(line => line.match(/GoodPythonStack\(app, "GoodPython",/)).filter(line => line).length).toEqual(1);
// Replaced stack file is correctly generated
const replacedStack = fs.readFileSync(path.join(workDir, 'GoodPython', 'good_python', 'good_python_stack.py'), 'utf8');
expect(replacedStack).toEqual(fs.readFileSync(path.join(...stackPath, 's3_stack.py'), 'utf8'));
});
cliTest('generateCdkApp generates the expected cdk app when called for java', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodJava', 'java');
await (0, migrate_1.generateCdkApp)('GoodJava', stack, 'java', workDir);
// Packages exist in the correct spot
expect(fs.pathExistsSync(path.join(workDir, 'GoodJava', 'pom.xml'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodJava', 'src', 'main', 'java', 'com', 'myorg', 'GoodJavaApp.java'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodJava', 'src', 'main', 'java', 'com', 'myorg', 'GoodJavaStack.java'))).toBeTruthy();
// Replaced stack file is referenced correctly in app file
const app = fs.readFileSync(path.join(workDir, 'GoodJava', 'src', 'main', 'java', 'com', 'myorg', 'GoodJavaApp.java'), 'utf8').split('\n');
expect(app.map(line => line.match('public class GoodJavaApp {')).filter(line => line).length).toEqual(1);
expect(app.map(line => line.match(/ new GoodJavaStack\(app, "GoodJava", StackProps.builder()/)).filter(line => line).length).toEqual(1);
// Replaced stack file is correctly generated
const replacedStack = fs.readFileSync(path.join(workDir, 'GoodJava', 'src', 'main', 'java', 'com', 'myorg', 'GoodJavaStack.java'), 'utf8');
expect(replacedStack).toEqual(fs.readFileSync(path.join(...stackPath, 'S3Stack.java'), 'utf8'));
});
cliTest('generateCdkApp generates the expected cdk app when called for csharp', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodCSharp', 'csharp');
await (0, migrate_1.generateCdkApp)('GoodCSharp', stack, 'csharp', workDir);
// Packages exist in the correct spot
expect(fs.pathExistsSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp.sln'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp', 'Program.cs'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp', 'GoodCSharpStack.cs'))).toBeTruthy();
// Replaced stack file is referenced correctly in app file
const app = fs.readFileSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp', 'Program.cs'), 'utf8').split('\n');
expect(app.map(line => line.match('namespace GoodCSharp')).filter(line => line).length).toEqual(1);
expect(app.map(line => line.match(/ new GoodCSharpStack\(app, "GoodCSharp", new GoodCSharpStackProps/)).filter(line => line).length).toEqual(1);
// Replaced stack file is correctly generated
const replacedStack = fs.readFileSync(path.join(workDir, 'GoodCSharp', 'src', 'GoodCSharp', 'GoodCSharpStack.cs'), 'utf8');
expect(replacedStack).toEqual(fs.readFileSync(path.join(...stackPath, 'S3Stack.cs'), 'utf8'));
});
cliTest('generatedCdkApp generates the expected cdk app when called for go', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodGo', 'go');
await (0, migrate_1.generateCdkApp)('GoodGo', stack, 'go', workDir);
expect(fs.pathExists(path.join(workDir, 's3.go'))).toBeTruthy();
const app = fs.readFileSync(path.join(workDir, 'GoodGo', 'good_go.go'), 'utf8').split('\n');
expect(app.map(line => line.match(/func NewGoodGoStack\(scope constructs.Construct, id string, props GoodGoStackProps\) \*GoodGoStack \{/)).filter(line => line).length).toEqual(1);
expect(app.map(line => line.match(/ NewGoodGoStack\(app, "GoodGo", &GoodGoStackProps\{/)));
});
cliTest('generatedCdkApp generates a zip file when --compress is used', async (workDir) => {
const stack = (0, migrate_1.generateStack)(validTemplate, 'GoodTypeScript', 'typescript');
await (0, migrate_1.generateCdkApp)('GoodTypeScript', stack, 'typescript', workDir, true);
// Packages not in outDir
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'package.json'))).toBeFalsy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'bin', 'good_type_script.ts'))).toBeFalsy();
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'lib', 'good_type_script-stack.ts'))).toBeFalsy();
// Zip file exists
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript.zip'))).toBeTruthy();
// Unzip it
await exec(`unzip ${path.join(workDir, 'GoodTypeScript.zip')}`, { cwd: workDir });
// Now the files should be there
expect(fs.pathExistsSync(path.join(workDir, 'package.json'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'bin', 'good_type_script.ts'))).toBeTruthy();
expect(fs.pathExistsSync(path.join(workDir, 'lib', 'good_type_script-stack.ts'))).toBeTruthy();
});
});
function cliTest(name, handler) {
test(name, () => withTempDir(handler));
}
async function withTempDir(cb) {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'aws-cdk-test'));
try {
await cb(tmpDir);
}
finally {
await fs.remove(tmpDir);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0ZS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWlncmF0ZS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaURBQThDO0FBQzlDLHlCQUF5QjtBQUN6Qiw2QkFBNkI7QUFDN0IsK0JBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQix3REFBK0k7QUFDL0ksK0NBQXNGO0FBRXRGLE1BQU0sSUFBSSxHQUFHLElBQUEsZ0JBQVMsRUFBQyxvQkFBSyxDQUFDLENBQUM7QUFFOUIsUUFBUSxDQUFDLHdCQUF3QixFQUFFLEdBQUcsRUFBRTtJQUN0QyxJQUFJLFdBQTRCLENBQUM7SUFDakMsSUFBSSxlQUEwQixDQUFDO0lBQy9CLElBQUksUUFBK0QsQ0FBQztJQUVwRSxNQUFNLGdCQUFnQixHQUFHLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDdkQsTUFBTSxZQUFZLEdBQUcsQ0FBQyxHQUFHLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUVsRCxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxZQUFZLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztJQUN6RSxNQUFNLGFBQWEsR0FBRyxJQUFBLHNCQUFZLEVBQUMsaUJBQWlCLENBQUUsQ0FBQztJQUV2RCxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsV0FBVyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO1FBQ3BDLGVBQWUsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDNUIsUUFBUSxHQUFHLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxDQUFDO1FBQzVDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFlLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQywrRUFBK0UsRUFBRSxHQUFH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QUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUN4RSxJQUFJO1FBQ0YsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDbEI7WUFBUztRQUNSLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztLQUN6QjtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBleGVjIGFzIF9leGVjIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSAndXRpbCc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBnZW5lcmF0ZUNka0FwcCwgZ2VuZXJhdGVTdGFjaywgcmVhZEZyb21QYXRoLCByZWFkRnJvbVN0YWNrLCBzZXRFbnZpcm9ubWVudCwgdmFsaWRhdGVTb3VyY2VPcHRpb25zIH0gZnJvbSAnLi4vLi4vbGliL2NvbW1hbmRzL21pZ3JhdGUnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyLCBNb2NrZWRPYmplY3QsIFN5bmNIYW5kbGVyU3Vic2V0T2YgfSBmcm9tICcuLi91dGlsL21vY2stc2RrJztcblxuY29uc3QgZXhlYyA9IHByb21pc2lmeShfZXhlYyk7XG5cbmRlc2NyaWJlKCdNaWdyYXRlIEZ1bmN0aW9uIFRlc3RzJywgKCkgPT4ge1xuICBsZXQgc2RrUHJvdmlkZXI6IE1vY2tTZGtQcm92aWRlcjtcbiAgbGV0IGdldFRlbXBsYXRlTW9jazogamVzdC5Nb2NrO1xuICBsZXQgY2ZuTW9ja3M6IE1vY2tlZE9iamVjdDxTeW5jSGFuZGxlclN1YnNldE9mPEFXUy5DbG91ZEZvcm1hdGlvbj4+O1xuXG4gIGNvbnN0IHRlc3RSZXNvdXJjZVBhdGggPSBbX19kaXJuYW1lLCAndGVzdC1yZXNvdXJjZXMnXTtcbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gWy4uLnRlc3RSZXNvdXJjZVBhdGgsICd0ZW1wbGF0ZXMnXTtcbiAgY29uc3Qgc3RhY2tQYXRoID0gWy4uLnRlc3RSZXNvdXJjZVBhdGgsICdzdGFja3MnXTtcblxuICBjb25zdCB2YWxpZFRlbXBsYXRlUGF0aCA9IHBhdGguam9pbiguLi50ZW1wbGF0ZVBhdGgsICdzMy10ZW1wbGF0ZS5qc29uJyk7XG4gIGNvbnN0IHZhbGlkVGVtcGxhdGUgPSByZWFkRnJvbVBhdGgodmFsaWRUZW1wbGF0ZVBhdGgpITtcblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBzZGtQcm92aWRlciA9IG5ldyBNb2NrU2RrUHJvdmlkZXIoKTtcbiAgICBnZXRUZW1wbGF0ZU1vY2sgPSBqZXN0LmZuKCk7XG4gICAgY2ZuTW9ja3MgPSB7IGdldFRlbXBsYXRlOiBnZXRUZW1wbGF0ZU1vY2sgfTtcbiAgICBzZGtQcm92aWRlci5zdHViQ2xvdWRGb3JtYXRpb24oY2ZuTW9ja3MgYXMgYW55KTtcbiAgfSk7XG5cbiAgdGVzdCgndmFsaWRhdGVTb3VyY2VPcHRpb25zIHRocm93cyBpZiBib3RoIC0tZnJvbS1wYXRoIGFuZCAtLWZyb20tc3RhY2sgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHZhbGlkYXRlU291cmNlT3B0aW9ucygnYW55LXZhbHVlJywgdHJ1ZSkpLnRvVGhyb3dFcnJvcignT25seSBvbmUgb2YgYC0tZnJvbS1wYXRoYCBvciBgLS1mcm9tLXN0YWNrYCBtYXkgYmUgcHJvdmlkZWQuJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ3ZhbGlkYXRlU291cmNlT3B0aW9ucyB0aHJvd3MgaWYgbmVpdGhlciAtLWZyb20tcGF0aCBvciAtLWZyb20tc3RhY2sgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHZhbGlkYXRlU291cmNlT3B0aW9ucyh1bmRlZmluZWQsIHVuZGVmaW5lZCkpLnRvVGhyb3dFcnJvcignRWl0aGVyIGAtLWZyb20tcGF0aGAgb3IgYC0tZnJvbS1zdGFja2AgbXVzdCBiZSB1c2VkIHRvIHByb3ZpZGUgdGhlIHNvdXJjZSBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUuJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ3ZhbGlkYXRlU291cmNlT3B0aW9ucyBkb2VzIG5vdCB0aHJvdyB3aGVuIG9ubHkgLS1mcm9tLXBhdGggaXMgc3VwcGxpZWQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHZhbGlkYXRlU291cmNlT3B0aW9ucygnYW55LXZhbHVlJywgZmFsc2UpKS5ub3QudG9UaHJvdygpO1xuICB9KTtcblxuICB0ZXN0KCd2YWxpZGF0ZVNvdXJjZU9wdGlvbnMgZG9lcyBub3cgdGhyb3cgd2hlbiBvbmx5IC0tZnJvbS1zdGFjayBpcyBwcm92aWRlZCcsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdmFsaWRhdGVTb3VyY2VPcHRpb25zKHVuZGVmaW5lZCwgdHJ1ZSkpLm5vdC50b1Rocm93KCk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JlYWRGcm9tUGF0aCBwcm9kdWNlcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdGVtcGxhdGUgYXQgYSBnaXZlbiBwYXRoJywgKCkgPT4ge1xuICAgIGV4cGVjdChyZWFkRnJvbVBhdGgodmFsaWRUZW1wbGF0ZVBhdGgpKS50b0VxdWFsKGZzLnJlYWRGaWxlU3luYyh2YWxpZFRlbXBsYXRlUGF0aCwgJ3V0ZjgnKSk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JlYWRGcm9tUGF0aCByZXR1cm5zIHVuZGVmaW5lZCB3aGVuIHRlbXBsYXRlIGZpbGUgaXMgbm90IHByb3ZpZGVkJywgKCkgPT4ge1xuICAgIGV4cGVjdChyZWFkRnJvbVBhdGgoKSkudG9FcXVhbCh1bmRlZmluZWQpO1xuICB9KTtcblxuICB0ZXN0KCdyZWFkRnJvbVBhdGggdGhyb3dzIGVycm9yIHdoZW4gdGVtcGxhdGUgZmlsZSBkb2VzIG5vdCBleGlzdCBhdCBhIGdpdmVuIHBhdGgnLCAoKSA9PiB7XG4gICAgY29uc3QgYmFkVGVtcGxhdGVQYXRoID0gJy4vbm90LWhlcmUuanNvbic7XG4gICAgZXhwZWN0KCgpID0+IHJlYWRGcm9tUGF0aChiYWRUZW1wbGF0ZVBhdGgpKS50b1Rocm93RXJyb3IoYFxcJyR7YmFkVGVtcGxhdGVQYXRofVxcJyBpcyBub3QgYSB2YWxpZCBwYXRoLmApO1xuICB9KTtcblxuICB0ZXN0KCdyZWFkRnJvbVN0YWNrIHByb2R1Y2VzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0ZW1wbGF0ZSByZXRyaWV2ZWQgZnJvbSBDbG91ZEZvcm1hdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9IGZzLnJlYWRGaWxlU3luYyh2YWxpZFRlbXBsYXRlUGF0aCk7XG4gICAgZ2V0VGVtcGxhdGVNb2NrLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFRlbXBsYXRlQm9keTogdGVtcGxhdGUsXG4gICAgfSkpO1xuXG4gICAgZXhwZWN0KGF3YWl0IHJlYWRGcm9tU3RhY2soJ3RoaXMtb25lJywgc2RrUHJvdmlkZXIsIHsgYWNjb3VudDogJ251bScsIHJlZ2lvbjogJ2hlcmUnLCBuYW1lOiAnaGVsbG8tbXktbmFtZS1pcy13aGF0Li4uJyB9KSkudG9FcXVhbCh0ZW1wbGF0ZSk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JlYWRGcm9tU3RhY2sgdGhyb3dzIGVycm9yIHdoZW4gbm8gc3RhY2sgZXhpc3RzIHdpdGggdGhlIHN0YWNrIG5hbWUgaW4gdGhlIGFjY291bnQgYW5kIHJlZ2lvbicsIGFzeW5jICgpID0+IHtcbiAgICBnZXRUZW1wbGF0ZU1vY2subW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiB7IHRocm93IG5ldyBFcnJvcignTm8gc3RhY2suIFRoaXMgZGlkIG5vdCBnbyB3ZWxsLicpOyB9KTtcbiAgICBhd2FpdCBleHBlY3QoKCkgPT4gcmVhZEZyb21TdGFjaygndGhhdC1vbmUnLCBzZGtQcm92aWRlciwgeyBhY2NvdW50OiAnbnVtJywgcmVnaW9uOiAnaGVyZScsIG5hbWU6ICdoZWxsby1teS1uYW1lLWlzLXdoby4uLicgfSkpLnJlamVjdHMudG9UaHJvd0Vycm9yKCdObyBzdGFjay4gVGhpcyBkaWQgbm90IGdvIHdlbGwuJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ3NldEVudmlyb25tZW50IHNldHMgYWNjb3VudCBhbmQgcmVnaW9uIHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KHNldEVudmlyb25tZW50KCdteS1hY2NvdW50JywgJ3NvbWV3aGVyZScpKS50b0VxdWFsKHsgYWNjb3VudDogJ215LWFjY291bnQnLCByZWdpb246ICdzb21ld2hlcmUnLCBuYW1lOiAnY2RrLW1pZ3JhdGUtZW52JyB9KTtcbiAgfSk7XG5cbiAgdGVzdCgnc2VyRW52aXJvbm1lbnQgdXNlcyBkZWZhdWx0IGFjY291bnQgYW5kIHJlZ2lvbiB3aGVuIG5vdCBwcm92aWRlZCcsICgpID0+IHtcbiAgICBleHBlY3Qoc2V0RW52aXJvbm1lbnQoKSkudG9FcXVhbCh7IGFjY291bnQ6ICd1bmtub3duLWFjY291bnQnLCByZWdpb246ICd1bmtub3duLXJlZ2lvbicsIG5hbWU6ICdjZGstbWlncmF0ZS1lbnYnIH0pO1xuICB9KTtcblxuICB0ZXN0KCdnZW5lcmF0ZVN0YWNrIGdlbmVyYXRlcyB0aGUgZXhwZWN0ZWQgc3RhY2sgc3RyaW5nIHdoZW4gY2FsbGVkIGZvciB0eXBlc2NyaXB0JywgKCkgPT4ge1xuICAgIGNvbnN0IHN0YWNrID0gZ2VuZXJhdGVTdGFjayh2YWxpZFRlbXBsYXRlLCAnR29vZFR5cGVTY3JpcHQnLCAndHlwZXNjcmlwdCcpO1xuICAgIGV4cGVjdChzdGFjaykudG9FcXVhbChmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKC4uLnN0YWNrUGF0aCwgJ3MzLXN0YWNrLnRzJyksICd1dGY4JykpO1xuICB9KTtcblxuICB0ZXN0KCdnZW5lcmF0ZVN0YWNrIGdlbmVyYXRlcyB0aGUgZXhwZWN0ZWQgc3RhY2sgc3RyaW5nIHdoZW4gY2FsbGVkIGZvciBweXRob24nLCAoKSA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBnZW5lcmF0ZVN0YWNrKHZhbGlkVGVtcGxhdGUsICdHb29kUHl0aG9uJywgJ3B5dGhvbicpO1xuICAgIGV4cGVjdChzdGFjaykudG9FcXVhbChmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKC4uLnN0YWNrUGF0aCwgJ3MzX3N0YWNrLnB5JyksICd1dGY4JykpO1xuICB9KTtcblxuICB0ZXN0KCdnZW5lcmF0ZVN0YWNrIGdlbmVyYXRlcyB0aGUgZXhwZWN0ZWQgc3RhY2sgc3RyaW5nIHdoZW4gY2FsbGVkIGZvciBqYXZhJywgKCkgPT4ge1xuICAgIGNvbnN0IHN0YWNrID0gZ2VuZXJhdGVTdGFjayh2YWxpZFRlbXBsYXRlLCAnR29vZEphdmEnLCAnamF2YScpO1xuICAgIGV4cGVjdChzdGFjaykudG9FcXVhbChmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKC4uLnN0YWNrUGF0aCwgJ1MzU3RhY2suamF2YScpLCAndXRmOCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnZ2VuZXJhdGVTdGFjayBnZW5lcmF0ZXMgdGhlIGV4cGVjdGVkIHN0YWNrIHN0cmluZyB3aGVuIGNhbGxlZCBmb3IgY3NoYXJwJywgKCkgPT4ge1xuICAgIGNvbnN0IHN0YWNrID0gZ2VuZXJhdGVTdGFjayh2YWxpZFRlbXBsYXRlLCAnR29vZENTaGFycCcsICdjc2hhcnAnKTtcbiAgICBleHBlY3Qoc3RhY2spLnRvRXF1YWwoZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbiguLi5zdGFja1BhdGgsICdTM1N0YWNrLmNzJyksICd1dGY4JykpO1xuICB9KTtcblxuICAvLyBUT0RPOiBmaXggd2l0aCBhY3R1YWwgZ28gdGVtcGxhdGVcbiAgdGVzdCgnZ2VuZXJhdGVTdGFjayBnZW5lcmF0ZXMgdGhlIGV4cGVjdGVkIHN0YWNrIHN0cmluZyB3aGVuIGNhbGxlZCBmb3IgZ28nLCAoKSA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBnZW5lcmF0ZVN0YWNrKHZhbGlkVGVtcGxhdGUsICdHb29kR28nLCAnZ28nKTtcbiAgICBleHBlY3Qoc3RhY2spLnRvRXF1YWwoZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbiguLi5zdGFja1BhdGgsICdzMy5nbycpLCAndXRmOCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnZ2VuZXJhdGVTdGFjayB0aHJvd3MgZXJyb3Igd2hlbiBjYWxsZWQgZm9yIG90aGVyIGxhbmd1YWdlJywgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiBnZW5lcmF0ZVN0YWNrKHZhbGlkVGVtcGxhdGUsICdCYWRCYWRCYWQnLCAncGhwJykpLnRvVGhyb3dFcnJvcignc3RhY2sgZ2VuZXJhdGlvbiBmYWlsZWQgZHVlIHRvIGVycm9yIFxcJ3VucmVhY2hhYmxlXFwnJyk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2dlbmVyYXRlQ2RrQXBwIGdlbmVyYXRlcyB0aGUgZXhwZWN0ZWQgY2RrIGFwcCB3aGVuIGNhbGxlZCBmb3IgdHlwZXNjcmlwdCcsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBnZW5lcmF0ZVN0YWNrKHZhbGlkVGVtcGxhdGUsICdHb29kVHlwZVNjcmlwdCcsICd0eXBlc2NyaXB0Jyk7XG4gICAgYXdhaXQgZ2VuZXJhdGVDZGtBcHAoJ0dvb2RUeXBlU2NyaXB0Jywgc3RhY2ssICd0eXBlc2NyaXB0Jywgd29ya0Rpcik7XG5cbiAgICAvLyBQYWNrYWdlcyBleGlzdCBpbiB0aGUgY29ycmVjdCBzcG90XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFR5cGVTY3JpcHQnLCAncGFja2FnZS5qc29uJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFR5cGVTY3JpcHQnLCAnYmluJywgJ2dvb2RfdHlwZV9zY3JpcHQudHMnKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kVHlwZVNjcmlwdCcsICdsaWInLCAnZ29vZF90eXBlX3NjcmlwdC1zdGFjay50cycpKSkudG9CZVRydXRoeSgpO1xuXG4gICAgLy8gUmVwbGFjZWQgc3RhY2sgZmlsZSBpcyByZWZlcmVuY2VkIGNvcnJlY3RseSBpbiBhcHAgZmlsZVxuICAgIGNvbnN0IGFwcCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RUeXBlU2NyaXB0JywgJ2JpbicsICdnb29kX3R5cGVfc2NyaXB0LnRzJyksICd1dGY4Jykuc3BsaXQoJ1xcbicpO1xuICAgIGV4cGVjdChhcHAubWFwKGxpbmUgPT4gbGluZS5tYXRjaCgnaW1wb3J0IHsgR29vZFR5cGVTY3JpcHRTdGFjayB9IGZyb20gXFwnLi4vbGliL2dvb2RfdHlwZV9zY3JpcHQtc3RhY2tcXCc7JykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcbiAgICBleHBlY3QoYXBwLm1hcChsaW5lID0+IGxpbmUubWF0Y2goL25ldyBHb29kVHlwZVNjcmlwdFN0YWNrXFwoYXBwLCBcXCdHb29kVHlwZVNjcmlwdFxcJywgXFx7LykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcblxuICAgIC8vIFJlcGxhY2VkIHN0YWNrIGZpbGUgaXMgY29ycmVjdGx5IGdlbmVyYXRlZFxuICAgIGNvbnN0IHJlcGxhY2VkU3RhY2sgPSBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kVHlwZVNjcmlwdCcsICdsaWInLCAnZ29vZF90eXBlX3NjcmlwdC1zdGFjay50cycpLCAndXRmOCcpO1xuICAgIGV4cGVjdChyZXBsYWNlZFN0YWNrKS50b0VxdWFsKGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4oLi4uc3RhY2tQYXRoLCAnczMtc3RhY2sudHMnKSwgJ3V0ZjgnKSk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2dlbmVyYXRlQ2RrQXBwIGdlbmVyYXRlcyB0aGUgZXhwZWN0ZWQgY2RrIGFwcCB3aGVuIGNhbGxlZCBmb3IgcHl0aG9uJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBjb25zdCBzdGFjayA9IGdlbmVyYXRlU3RhY2sodmFsaWRUZW1wbGF0ZSwgJ0dvb2RQeXRob24nLCAncHl0aG9uJyk7XG4gICAgYXdhaXQgZ2VuZXJhdGVDZGtBcHAoJ0dvb2RQeXRob24nLCBzdGFjaywgJ3B5dGhvbicsIHdvcmtEaXIpO1xuXG4gICAgLy8gUGFja2FnZXMgZXhpc3QgaW4gdGhlIGNvcnJlY3Qgc3BvdFxuICAgIGV4cGVjdChmcy5wYXRoRXhpc3RzU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RQeXRob24nLCAncmVxdWlyZW1lbnRzLnR4dCcpKSkudG9CZVRydXRoeSgpO1xuICAgIGV4cGVjdChmcy5wYXRoRXhpc3RzU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RQeXRob24nLCAnYXBwLnB5JykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFB5dGhvbicsICdnb29kX3B5dGhvbicsICdnb29kX3B5dGhvbl9zdGFjay5weScpKSkudG9CZVRydXRoeSgpO1xuXG4gICAgLy8gUmVwbGFjZWQgc3RhY2sgZmlsZSBpcyByZWZlcmVuY2VkIGNvcnJlY3RseSBpbiBhcHAgZmlsZVxuICAgIGNvbnN0IGFwcCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RQeXRob24nLCAnYXBwLnB5JyksICd1dGY4Jykuc3BsaXQoJ1xcbicpO1xuICAgIGV4cGVjdChhcHAubWFwKGxpbmUgPT4gbGluZS5tYXRjaCgnZnJvbSBnb29kX3B5dGhvbi5nb29kX3B5dGhvbl9zdGFjayBpbXBvcnQgR29vZFB5dGhvblN0YWNrJykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcbiAgICBleHBlY3QoYXBwLm1hcChsaW5lID0+IGxpbmUubWF0Y2goL0dvb2RQeXRob25TdGFja1xcKGFwcCwgXCJHb29kUHl0aG9uXCIsLykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcblxuICAgIC8vIFJlcGxhY2VkIHN0YWNrIGZpbGUgaXMgY29ycmVjdGx5IGdlbmVyYXRlZFxuICAgIGNvbnN0IHJlcGxhY2VkU3RhY2sgPSBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kUHl0aG9uJywgJ2dvb2RfcHl0aG9uJywgJ2dvb2RfcHl0aG9uX3N0YWNrLnB5JyksICd1dGY4Jyk7XG4gICAgZXhwZWN0KHJlcGxhY2VkU3RhY2spLnRvRXF1YWwoZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbiguLi5zdGFja1BhdGgsICdzM19zdGFjay5weScpLCAndXRmOCcpKTtcbiAgfSk7XG5cbiAgY2xpVGVzdCgnZ2VuZXJhdGVDZGtBcHAgZ2VuZXJhdGVzIHRoZSBleHBlY3RlZCBjZGsgYXBwIHdoZW4gY2FsbGVkIGZvciBqYXZhJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBjb25zdCBzdGFjayA9IGdlbmVyYXRlU3RhY2sodmFsaWRUZW1wbGF0ZSwgJ0dvb2RKYXZhJywgJ2phdmEnKTtcbiAgICBhd2FpdCBnZW5lcmF0ZUNka0FwcCgnR29vZEphdmEnLCBzdGFjaywgJ2phdmEnLCB3b3JrRGlyKTtcblxuICAgIC8vIFBhY2thZ2VzIGV4aXN0IGluIHRoZSBjb3JyZWN0IHNwb3RcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kSmF2YScsICdwb20ueG1sJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZEphdmEnLCAnc3JjJywgJ21haW4nLCAnamF2YScsICdjb20nLCAnbXlvcmcnLCAnR29vZEphdmFBcHAuamF2YScpKSkudG9CZVRydXRoeSgpO1xuICAgIGV4cGVjdChmcy5wYXRoRXhpc3RzU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RKYXZhJywgJ3NyYycsICdtYWluJywgJ2phdmEnLCAnY29tJywgJ215b3JnJywgJ0dvb2RKYXZhU3RhY2suamF2YScpKSkudG9CZVRydXRoeSgpO1xuXG4gICAgLy8gUmVwbGFjZWQgc3RhY2sgZmlsZSBpcyByZWZlcmVuY2VkIGNvcnJlY3RseSBpbiBhcHAgZmlsZVxuICAgIGNvbnN0IGFwcCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RKYXZhJywgJ3NyYycsICdtYWluJywgJ2phdmEnLCAnY29tJywgJ215b3JnJywgJ0dvb2RKYXZhQXBwLmphdmEnKSwgJ3V0ZjgnKS5zcGxpdCgnXFxuJyk7XG4gICAgZXhwZWN0KGFwcC5tYXAobGluZSA9PiBsaW5lLm1hdGNoKCdwdWJsaWMgY2xhc3MgR29vZEphdmFBcHAgeycpKS5maWx0ZXIobGluZSA9PiBsaW5lKS5sZW5ndGgpLnRvRXF1YWwoMSk7XG4gICAgZXhwZWN0KGFwcC5tYXAobGluZSA9PiBsaW5lLm1hdGNoKC8gICAgICAgIG5ldyBHb29kSmF2YVN0YWNrXFwoYXBwLCBcIkdvb2RKYXZhXCIsIFN0YWNrUHJvcHMuYnVpbGRlcigpLykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcblxuICAgIC8vIFJlcGxhY2VkIHN0YWNrIGZpbGUgaXMgY29ycmVjdGx5IGdlbmVyYXRlZFxuICAgIGNvbnN0IHJlcGxhY2VkU3RhY2sgPSBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kSmF2YScsICdzcmMnLCAnbWFpbicsICdqYXZhJywgJ2NvbScsICdteW9yZycsICdHb29kSmF2YVN0YWNrLmphdmEnKSwgJ3V0ZjgnKTtcbiAgICBleHBlY3QocmVwbGFjZWRTdGFjaykudG9FcXVhbChmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKC4uLnN0YWNrUGF0aCwgJ1MzU3RhY2suamF2YScpLCAndXRmOCcpKTtcbiAgfSk7XG5cbiAgY2xpVGVzdCgnZ2VuZXJhdGVDZGtBcHAgZ2VuZXJhdGVzIHRoZSBleHBlY3RlZCBjZGsgYXBwIHdoZW4gY2FsbGVkIGZvciBjc2hhcnAnLCBhc3luYyAod29ya0RpcikgPT4ge1xuICAgIGNvbnN0IHN0YWNrID0gZ2VuZXJhdGVTdGFjayh2YWxpZFRlbXBsYXRlLCAnR29vZENTaGFycCcsICdjc2hhcnAnKTtcbiAgICBhd2FpdCBnZW5lcmF0ZUNka0FwcCgnR29vZENTaGFycCcsIHN0YWNrLCAnY3NoYXJwJywgd29ya0Rpcik7XG5cbiAgICAvLyBQYWNrYWdlcyBleGlzdCBpbiB0aGUgY29ycmVjdCBzcG90XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZENTaGFycCcsICdzcmMnLCAnR29vZENTaGFycC5zbG4nKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kQ1NoYXJwJywgJ3NyYycsICdHb29kQ1NoYXJwJywgJ1Byb2dyYW0uY3MnKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kQ1NoYXJwJywgJ3NyYycsICdHb29kQ1NoYXJwJywgJ0dvb2RDU2hhcnBTdGFjay5jcycpKSkudG9CZVRydXRoeSgpO1xuXG4gICAgLy8gUmVwbGFjZWQgc3RhY2sgZmlsZSBpcyByZWZlcmVuY2VkIGNvcnJlY3RseSBpbiBhcHAgZmlsZVxuICAgIGNvbnN0IGFwcCA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4od29ya0RpciwgJ0dvb2RDU2hhcnAnLCAnc3JjJywgJ0dvb2RDU2hhcnAnLCAnUHJvZ3JhbS5jcycpLCAndXRmOCcpLnNwbGl0KCdcXG4nKTtcbiAgICBleHBlY3QoYXBwLm1hcChsaW5lID0+IGxpbmUubWF0Y2goJ25hbWVzcGFjZSBHb29kQ1NoYXJwJykpLmZpbHRlcihsaW5lID0+IGxpbmUpLmxlbmd0aCkudG9FcXVhbCgxKTtcbiAgICBleHBlY3QoYXBwLm1hcChsaW5lID0+IGxpbmUubWF0Y2goLyAgICAgICAgbmV3IEdvb2RDU2hhcnBTdGFja1xcKGFwcCwgXCJHb29kQ1NoYXJwXCIsIG5ldyBHb29kQ1NoYXJwU3RhY2tQcm9wcy8pKS5maWx0ZXIobGluZSA9PiBsaW5lKS5sZW5ndGgpLnRvRXF1YWwoMSk7XG5cbiAgICAvLyBSZXBsYWNlZCBzdGFjayBmaWxlIGlzIGNvcnJlY3RseSBnZW5lcmF0ZWRcbiAgICBjb25zdCByZXBsYWNlZFN0YWNrID0gZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZENTaGFycCcsICdzcmMnLCAnR29vZENTaGFycCcsICdHb29kQ1NoYXJwU3RhY2suY3MnKSwgJ3V0ZjgnKTtcbiAgICBleHBlY3QocmVwbGFjZWRTdGFjaykudG9FcXVhbChmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKC4uLnN0YWNrUGF0aCwgJ1MzU3RhY2suY3MnKSwgJ3V0ZjgnKSk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2dlbmVyYXRlZENka0FwcCBnZW5lcmF0ZXMgdGhlIGV4cGVjdGVkIGNkayBhcHAgd2hlbiBjYWxsZWQgZm9yIGdvJywgYXN5bmMgKHdvcmtEaXIpID0+IHtcbiAgICBjb25zdCBzdGFjayA9IGdlbmVyYXRlU3RhY2sodmFsaWRUZW1wbGF0ZSwgJ0dvb2RHbycsICdnbycpO1xuICAgIGF3YWl0IGdlbmVyYXRlQ2RrQXBwKCdHb29kR28nLCBzdGFjaywgJ2dvJywgd29ya0Rpcik7XG5cbiAgICBleHBlY3QoZnMucGF0aEV4aXN0cyhwYXRoLmpvaW4od29ya0RpciwgJ3MzLmdvJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgY29uc3QgYXBwID0gZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZEdvJywgJ2dvb2RfZ28uZ28nKSwgJ3V0ZjgnKS5zcGxpdCgnXFxuJyk7XG4gICAgZXhwZWN0KGFwcC5tYXAobGluZSA9PiBsaW5lLm1hdGNoKC9mdW5jIE5ld0dvb2RHb1N0YWNrXFwoc2NvcGUgY29uc3RydWN0cy5Db25zdHJ1Y3QsIGlkIHN0cmluZywgcHJvcHMgR29vZEdvU3RhY2tQcm9wc1xcKSBcXCpHb29kR29TdGFjayBcXHsvKSkuZmlsdGVyKGxpbmUgPT4gbGluZSkubGVuZ3RoKS50b0VxdWFsKDEpO1xuICAgIGV4cGVjdChhcHAubWFwKGxpbmUgPT4gbGluZS5tYXRjaCgvICAgIE5ld0dvb2RHb1N0YWNrXFwoYXBwLCBcIkdvb2RHb1wiLCAmR29vZEdvU3RhY2tQcm9wc1xcey8pKSk7XG4gIH0pO1xuXG4gIGNsaVRlc3QoJ2dlbmVyYXRlZENka0FwcCBnZW5lcmF0ZXMgYSB6aXAgZmlsZSB3aGVuIC0tY29tcHJlc3MgaXMgdXNlZCcsIGFzeW5jICh3b3JrRGlyKSA9PiB7XG4gICAgY29uc3Qgc3RhY2sgPSBnZW5lcmF0ZVN0YWNrKHZhbGlkVGVtcGxhdGUsICdHb29kVHlwZVNjcmlwdCcsICd0eXBlc2NyaXB0Jyk7XG4gICAgYXdhaXQgZ2VuZXJhdGVDZGtBcHAoJ0dvb2RUeXBlU2NyaXB0Jywgc3RhY2ssICd0eXBlc2NyaXB0Jywgd29ya0RpciwgdHJ1ZSk7XG5cbiAgICAvLyBQYWNrYWdlcyBub3QgaW4gb3V0RGlyXG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFR5cGVTY3JpcHQnLCAncGFja2FnZS5qc29uJykpKS50b0JlRmFsc3koKTtcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdHb29kVHlwZVNjcmlwdCcsICdiaW4nLCAnZ29vZF90eXBlX3NjcmlwdC50cycpKSkudG9CZUZhbHN5KCk7XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFR5cGVTY3JpcHQnLCAnbGliJywgJ2dvb2RfdHlwZV9zY3JpcHQtc3RhY2sudHMnKSkpLnRvQmVGYWxzeSgpO1xuXG4gICAgLy8gWmlwIGZpbGUgZXhpc3RzXG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnR29vZFR5cGVTY3JpcHQuemlwJykpKS50b0JlVHJ1dGh5KCk7XG5cbiAgICAvLyBVbnppcCBpdFxuICAgIGF3YWl0IGV4ZWMoYHVuemlwICR7cGF0aC5qb2luKHdvcmtEaXIsICdHb29kVHlwZVNjcmlwdC56aXAnKX1gLCB7IGN3ZDogd29ya0RpciB9KTtcblxuICAgIC8vIE5vdyB0aGUgZmlsZXMgc2hvdWxkIGJlIHRoZXJlXG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAncGFja2FnZS5qc29uJykpKS50b0JlVHJ1dGh5KCk7XG4gICAgZXhwZWN0KGZzLnBhdGhFeGlzdHNTeW5jKHBhdGguam9pbih3b3JrRGlyLCAnYmluJywgJ2dvb2RfdHlwZV9zY3JpcHQudHMnKSkpLnRvQmVUcnV0aHkoKTtcbiAgICBleHBlY3QoZnMucGF0aEV4aXN0c1N5bmMocGF0aC5qb2luKHdvcmtEaXIsICdsaWInLCAnZ29vZF90eXBlX3NjcmlwdC1zdGFjay50cycpKSkudG9CZVRydXRoeSgpO1xuICB9KTtcbn0pO1xuXG5mdW5jdGlvbiBjbGlUZXN0KG5hbWU6IHN0cmluZywgaGFuZGxlcjogKGRpcjogc3RyaW5nKSA9PiB2b2lkIHwgUHJvbWlzZTxhbnk+KTogdm9pZCB7XG4gIHRlc3QobmFtZSwgKCkgPT4gd2l0aFRlbXBEaXIoaGFuZGxlcikpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB3aXRoVGVtcERpcihjYjogKGRpcjogc3RyaW5nKSA9PiB2b2lkIHwgUHJvbWlzZTxhbnk+KSB7XG4gIGNvbnN0IHRtcERpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCAnYXdzLWNkay10ZXN0JykpO1xuICB0cnkge1xuICAgIGF3YWl0IGNiKHRtcERpcik7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgZnMucmVtb3ZlKHRtcERpcik7XG4gIH1cbn0iXX0=