aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
229 lines • 29.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chalk = require("chalk");
const cli_io_host_1 = require("../../lib/toolkit/cli-io-host");
const ioHost = cli_io_host_1.CliIoHost.instance({
logLevel: 'trace',
});
describe('CliIoHost', () => {
let mockStdout;
let mockStderr;
let defaultMessage;
beforeEach(() => {
mockStdout = jest.fn();
mockStderr = jest.fn();
// Reset singleton state
ioHost.isTTY = process.stdout.isTTY ?? false;
ioHost.isCI = false;
ioHost.currentAction = 'synth';
defaultMessage = {
time: new Date('2024-01-01T12:00:00'),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'test message',
};
jest.spyOn(process.stdout, 'write').mockImplementation((str, encoding, cb) => {
mockStdout(str.toString());
const callback = typeof encoding === 'function' ? encoding : cb;
if (callback)
callback();
return true;
});
jest.spyOn(process.stderr, 'write').mockImplementation((str, encoding, cb) => {
mockStderr(str.toString());
const callback = typeof encoding === 'function' ? encoding : cb;
if (callback)
callback();
return true;
});
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('stream selection', () => {
test('writes to stderr by default for non-error messages in non-CI mode', async () => {
ioHost.isTTY = true;
await ioHost.notify({
time: new Date(),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'test message',
});
expect(mockStderr).toHaveBeenCalledWith(chalk.white('test message') + '\n');
expect(mockStdout).not.toHaveBeenCalled();
});
test('writes to stderr for error level with red color', async () => {
ioHost.isTTY = true;
await ioHost.notify({
time: new Date(),
level: 'error',
action: 'synth',
code: 'CDK_TOOLKIT_E0001',
message: 'error message',
});
expect(mockStderr).toHaveBeenCalledWith(chalk.red('error message') + '\n');
expect(mockStdout).not.toHaveBeenCalled();
});
test('writes to stdout when forceStdout is true', async () => {
ioHost.isTTY = true;
await ioHost.notify({
time: new Date(),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'forced message',
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith(chalk.white('forced message') + '\n');
expect(mockStderr).not.toHaveBeenCalled();
});
});
describe('message formatting', () => {
beforeEach(() => {
ioHost.isTTY = true;
});
test('formats debug messages with timestamp', async () => {
await ioHost.notify({
...defaultMessage,
level: 'debug',
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith(`[12:00:00] ${chalk.gray('test message')}\n`);
});
test('formats trace messages with timestamp', async () => {
await ioHost.notify({
...defaultMessage,
level: 'trace',
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith(`[12:00:00] ${chalk.gray('test message')}\n`);
});
test('applies no styling when TTY is false', async () => {
ioHost.isTTY = false;
await ioHost.notify({
...defaultMessage,
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith('test message\n');
});
test('applies correct color styles for different message levels', async () => {
const testCases = [
{ level: 'error', style: chalk.red },
{ level: 'warn', style: chalk.yellow },
{ level: 'info', style: chalk.white },
{ level: 'debug', style: chalk.gray },
{ level: 'trace', style: chalk.gray },
];
for (const { level, style } of testCases) {
await ioHost.notify({
...defaultMessage,
level,
forceStdout: true,
});
const expectedOutput = level === 'debug' || level === 'trace'
? `[12:00:00] ${style('test message')}\n`
: `${style('test message')}\n`;
expect(mockStdout).toHaveBeenCalledWith(expectedOutput);
mockStdout.mockClear();
}
});
});
describe('action handling', () => {
test('sets and gets current action', () => {
ioHost.currentAction = 'deploy';
expect(ioHost.currentAction).toBe('deploy');
});
});
describe('CI mode behavior', () => {
beforeEach(() => {
ioHost.isTTY = true;
ioHost.isCI = true;
});
test('writes to stdout in CI mode when level is not error', async () => {
await ioHost.notify({
time: new Date(),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_W0001',
message: 'ci message',
});
expect(mockStdout).toHaveBeenCalledWith(chalk.white('ci message') + '\n');
expect(mockStderr).not.toHaveBeenCalled();
});
test('writes to stderr for error level in CI mode', async () => {
await ioHost.notify({
time: new Date(),
level: 'error',
action: 'synth',
code: 'CDK_TOOLKIT_E0001',
message: 'ci error message',
});
expect(mockStderr).toHaveBeenCalledWith(chalk.red('ci error message') + '\n');
expect(mockStdout).not.toHaveBeenCalled();
});
});
describe('timestamp handling', () => {
beforeEach(() => {
ioHost.isTTY = true;
});
test('includes timestamp for DEBUG level with gray color', async () => {
const testDate = new Date('2024-01-01T12:34:56');
await ioHost.notify({
time: testDate,
level: 'debug',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'debug message',
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith(`[12:34:56] ${chalk.gray('debug message')}\n`);
});
test('excludes timestamp for other levels but includes color', async () => {
const testDate = new Date('2024-01-01T12:34:56');
await ioHost.notify({
time: testDate,
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'info message',
forceStdout: true,
});
expect(mockStdout).toHaveBeenCalledWith(chalk.white('info message') + '\n');
});
});
describe('error handling', () => {
test('rejects on write error', async () => {
jest.spyOn(process.stdout, 'write').mockImplementation((_, callback) => {
if (callback)
callback(new Error('Write failed'));
return true;
});
await expect(ioHost.notify({
time: new Date(),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'test message',
forceStdout: true,
})).rejects.toThrow('Write failed');
});
});
describe('requestResponse', () => {
test('logs messages and returns default', async () => {
ioHost.isTTY = true;
const response = await ioHost.requestResponse({
time: new Date(),
level: 'info',
action: 'synth',
code: 'CDK_TOOLKIT_I0001',
message: 'test message',
defaultResponse: 'default response',
});
expect(mockStderr).toHaveBeenCalledWith(chalk.white('test message') + '\n');
expect(response).toBe('default response');
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWlvLWhvc3QudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsaS1pby1ob3N0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSwrQkFBK0I7QUFDL0IsK0RBQXFFO0FBRXJFLE1BQU0sTUFBTSxHQUFHLHVCQUFTLENBQUMsUUFBUSxDQUFDO0lBQ2hDLFFBQVEsRUFBRSxPQUFPO0NBQ2xCLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFO0lBQ3pCLElBQUksVUFBcUIsQ0FBQztJQUMxQixJQUFJLFVBQXFCLENBQUM7SUFDMUIsSUFBSSxjQUFrQyxDQUFDO0lBRXZDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxVQUFVLEdBQUcsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3ZCLFVBQVUsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFFdkIsd0JBQXdCO1FBQ3hCLE1BQU0sQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDO1FBQzdDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxhQUFhLEdBQUcsT0FBTyxDQUFDO1FBRS9CLGNBQWMsR0FBRztZQUNmLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxxQkFBcUIsQ0FBQztZQUNyQyxLQUFLLEVBQUUsTUFBTTtZQUNiLE1BQU0sRUFBRSxPQUFPO1lBQ2YsSUFBSSxFQUFFLG1CQUFtQjtZQUN6QixPQUFPLEVBQUUsY0FBYztTQUN4QixDQUFDO1FBRUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDLGtCQUFrQixDQUFDLENBQUMsR0FBUSxFQUFFLFFBQWMsRUFBRSxFQUFRLEVBQUUsRUFBRTtZQUM1RixVQUFVLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDM0IsTUFB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RSxHQUFHLEVBQUU7UUFDL0IsSUFBSSxDQUFDLG1DQUFtQyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ25ELE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLGVBQWUsQ0FBQztnQkFDNUMsSUFBSSxFQUFFLElBQUksSUFBSSxFQUFFO2dCQUNoQixLQUFLLEVBQUUsTUFBTTtnQkFDYixNQUFNLEVBQUUsT0FBTztnQkFDZixJQUFJLEVBQUUsbUJBQW1CO2dCQUN6QixPQUFPLEVBQUUsY0FBYztnQkFDdkIsZUFBZSxFQUFFLGtCQUFrQjthQUNwQyxDQUFDLENBQUM7WUFFSCxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztZQUM1RSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDNUMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2hhbGsgZnJvbSAnY2hhbGsnO1xuaW1wb3J0IHsgQ2xpSW9Ib3N0LCBJb01lc3NhZ2UgfSBmcm9tICcuLi8uLi9saWIvdG9vbGtpdC9jbGktaW8taG9zdCc7XG5cbmNvbnN0IGlvSG9zdCA9IENsaUlvSG9zdC5pbnN0YW5jZSh7XG4gIGxvZ0xldmVsOiAndHJhY2UnLFxufSk7XG5cbmRlc2NyaWJlKCdDbGlJb0hvc3QnLCAoKSA9PiB7XG4gIGxldCBtb2NrU3Rkb3V0OiBqZXN0Lk1vY2s7XG4gIGxldCBtb2NrU3RkZXJyOiBqZXN0Lk1vY2s7XG4gIGxldCBkZWZhdWx0TWVzc2FnZTogSW9NZXNzYWdlPHVua25vd24+O1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIG1vY2tTdGRvdXQgPSBqZXN0LmZuKCk7XG4gICAgbW9ja1N0ZGVyciA9IGplc3QuZm4oKTtcblxuICAgIC8vIFJlc2V0IHNpbmdsZXRvbiBzdGF0ZVxuICAgIGlvSG9zdC5pc1RUWSA9IHByb2Nlc3Muc3Rkb3V0LmlzVFRZID8/IGZhbHNlO1xuICAgIGlvSG9zdC5pc0NJID0gZmFsc2U7XG4gICAgaW9Ib3N0LmN1cnJlbnRBY3Rpb24gPSAnc3ludGgnO1xuXG4gICAgZGVmYXVsdE1lc3NhZ2UgPSB7XG4gICAgICB0aW1lOiBuZXcgRGF0ZSgnMjAyNC0wMS0wMVQxMjowMDowMCcpLFxuICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgIGFjdGlvbjogJ3N5bnRoJyxcbiAgICAgIGNvZGU6ICdDREtfVE9PTEtJVF9JMDAwMScsXG4gICAgICBtZXNzYWdlOiAndGVzdCBtZXNzYWdlJyxcbiAgICB9O1xuXG4gICAgamVzdC5zcHlPbihwcm9jZXNzLnN0ZG91dCwgJ3dyaXRlJykubW9ja0ltcGxlbWVudGF0aW9uKChzdHI6IGFueSwgZW5jb2Rpbmc/OiBhbnksIGNiPzogYW55KSA9PiB7XG4gICAgICBtb2NrU3Rkb3V0KHN0ci50b1N0cmluZygpKTtcbiAgICAgIGNvbnN0IGNhbGxiYWNrID0gdHlwZW9mIGVuY29kaW5nID09PSAnZnVuY3Rpb24nID8gZW5jb2RpbmcgOiBjYjtcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pO1xuXG4gICAgamVzdC5zcHlPbihwcm9jZXNzLnN0ZGVyciwgJ3dyaXRlJykubW9ja0ltcGxlbWVudGF0aW9uKChzdHI6IGFueSwgZW5jb2Rpbmc/OiBhbnksIGNiPzogYW55KSA9PiB7XG4gICAgICBtb2NrU3RkZXJyKHN0ci50b1N0cmluZygpKTtcbiAgICAgIGNvbnN0IGNhbGxiYWNrID0gdHlwZW9mIGVuY29kaW5nID09PSAnZnVuY3Rpb24nID8gZW5jb2RpbmcgOiBjYjtcbiAgICAgIGlmIChjYWxsYmFjaykgY2FsbGJhY2soKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pO1xuICB9KTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIGplc3QucmVzdG9yZUFsbE1vY2tzKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzdHJlYW0gc2VsZWN0aW9uJywgKCkgPT4ge1xuICAgIHRlc3QoJ3dyaXRlcyB0byBzdGRlcnIgYnkgZGVmYXVsdCBmb3Igbm9uLWVycm9yIG1lc3NhZ2VzIGluIG5vbi1DSSBtb2RlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgaW9Ib3N0LmlzVFRZID0gdHJ1ZTtcbiAgICAgIGF3YWl0IGlvSG9zdC5ub3RpZnkoe1xuICAgICAgICB0aW1lOiBuZXcgRGF0ZSgpLFxuICAgICAgICBsZXZlbDogJ2luZm8nLFxuICAgICAgICBhY3Rpb246ICdzeW50aCcsXG4gICAgICAgIGNvZGU6ICdDREtfVE9PTEtJVF9JMDAwMScsXG4gICAgICAgIG1lc3NhZ2U6ICd0ZXN0IG1lc3NhZ2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RkZXJyKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChjaGFsay53aGl0ZSgndGVzdCBtZXNzYWdlJykgKyAnXFxuJyk7XG4gICAgICBleHBlY3QobW9ja1N0ZG91dCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3dyaXRlcyB0byBzdGRlcnIgZm9yIGVycm9yIGxldmVsIHdpdGggcmVkIGNvbG9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgaW9Ib3N0LmlzVFRZID0gdHJ1ZTtcbiAgICAgIGF3YWl0IGlvSG9zdC5ub3RpZnkoe1xuICAgICAgICB0aW1lOiBuZXcgRGF0ZSgpLFxuICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgYWN0aW9uOiAnc3ludGgnLFxuICAgICAgICBjb2RlOiAnQ0RLX1RPT0xLSVRfRTAwMDEnLFxuICAgICAgICBtZXNzYWdlOiAnZXJyb3IgbWVzc2FnZScsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRlcnIpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGNoYWxrLnJlZCgnZXJyb3IgbWVzc2FnZScpICsgJ1xcbicpO1xuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd3cml0ZXMgdG8gc3Rkb3V0IHdoZW4gZm9yY2VTdGRvdXQgaXMgdHJ1ZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGlvSG9zdC5pc1RUWSA9IHRydWU7XG4gICAgICBhd2FpdCBpb0hvc3Qubm90aWZ5KHtcbiAgICAgICAgdGltZTogbmV3IERhdGUoKSxcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgYWN0aW9uOiAnc3ludGgnLFxuICAgICAgICBjb2RlOiAnQ0RLX1RPT0xLSVRfSTAwMDEnLFxuICAgICAgICBtZXNzYWdlOiAnZm9yY2VkIG1lc3NhZ2UnLFxuICAgICAgICBmb3JjZVN0ZG91dDogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QobW9ja1N0ZG91dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoY2hhbGsud2hpdGUoJ2ZvcmNlZCBtZXNzYWdlJykgKyAnXFxuJyk7XG4gICAgICBleHBlY3QobW9ja1N0ZGVycikubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ21lc3NhZ2UgZm9ybWF0dGluZycsICgpID0+IHtcbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIGlvSG9zdC5pc1RUWSA9IHRydWU7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdmb3JtYXRzIGRlYnVnIG1lc3NhZ2VzIHdpdGggdGltZXN0YW1wJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgaW9Ib3N0Lm5vdGlmeSh7XG4gICAgICAgIC4uLmRlZmF1bHRNZXNzYWdlLFxuICAgICAgICBsZXZlbDogJ2RlYnVnJyxcbiAgICAgICAgZm9yY2VTdGRvdXQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGBbMTI6MDA6MDBdICR7Y2hhbGsuZ3JheSgndGVzdCBtZXNzYWdlJyl9XFxuYCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdmb3JtYXRzIHRyYWNlIG1lc3NhZ2VzIHdpdGggdGltZXN0YW1wJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgaW9Ib3N0Lm5vdGlmeSh7XG4gICAgICAgIC4uLmRlZmF1bHRNZXNzYWdlLFxuICAgICAgICBsZXZlbDogJ3RyYWNlJyxcbiAgICAgICAgZm9yY2VTdGRvdXQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGBbMTI6MDA6MDBdICR7Y2hhbGsuZ3JheSgndGVzdCBtZXNzYWdlJyl9XFxuYCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdhcHBsaWVzIG5vIHN0eWxpbmcgd2hlbiBUVFkgaXMgZmFsc2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBpb0hvc3QuaXNUVFkgPSBmYWxzZTtcbiAgICAgIGF3YWl0IGlvSG9zdC5ub3RpZnkoe1xuICAgICAgICAuLi5kZWZhdWx0TWVzc2FnZSxcbiAgICAgICAgZm9yY2VTdGRvdXQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCd0ZXN0IG1lc3NhZ2VcXG4nKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2FwcGxpZXMgY29ycmVjdCBjb2xvciBzdHlsZXMgZm9yIGRpZmZlcmVudCBtZXNzYWdlIGxldmVscycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RDYXNlcyA9IFtcbiAgICAgICAgeyBsZXZlbDogJ2Vycm9yJyBhcyBjb25zdCwgc3R5bGU6IGNoYWxrLnJlZCB9LFxuICAgICAgICB7IGxldmVsOiAnd2FybicgYXMgY29uc3QsIHN0eWxlOiBjaGFsay55ZWxsb3cgfSxcbiAgICAgICAgeyBsZXZlbDogJ2luZm8nIGFzIGNvbnN0LCBzdHlsZTogY2hhbGsud2hpdGUgfSxcbiAgICAgICAgeyBsZXZlbDogJ2RlYnVnJyBhcyBjb25zdCwgc3R5bGU6IGNoYWxrLmdyYXkgfSxcbiAgICAgICAgeyBsZXZlbDogJ3RyYWNlJyBhcyBjb25zdCwgc3R5bGU6IGNoYWxrLmdyYXkgfSxcbiAgICAgIF07XG5cbiAgICAgIGZvciAoY29uc3QgeyBsZXZlbCwgc3R5bGUgfSBvZiB0ZXN0Q2FzZXMpIHtcbiAgICAgICAgYXdhaXQgaW9Ib3N0Lm5vdGlmeSh7XG4gICAgICAgICAgLi4uZGVmYXVsdE1lc3NhZ2UsXG4gICAgICAgICAgbGV2ZWwsXG4gICAgICAgICAgZm9yY2VTdGRvdXQ6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGV4cGVjdGVkT3V0cHV0ID0gbGV2ZWwgPT09ICdkZWJ1ZycgfHwgbGV2ZWwgPT09ICd0cmFjZSdcbiAgICAgICAgICA/IGBbMTI6MDA6MDBdICR7c3R5bGUoJ3Rlc3QgbWVzc2FnZScpfVxcbmBcbiAgICAgICAgICA6IGAke3N0eWxlKCd0ZXN0IG1lc3NhZ2UnKX1cXG5gO1xuXG4gICAgICAgIGV4cGVjdChtb2NrU3Rkb3V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3RlZE91dHB1dCk7XG4gICAgICAgIG1vY2tTdGRvdXQubW9ja0NsZWFyKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdhY3Rpb24gaGFuZGxpbmcnLCAoKSA9PiB7XG4gICAgdGVzdCgnc2V0cyBhbmQgZ2V0cyBjdXJyZW50IGFjdGlvbicsICgpID0+IHtcbiAgICAgIGlvSG9zdC5jdXJyZW50QWN0aW9uID0gJ2RlcGxveSc7XG4gICAgICBleHBlY3QoaW9Ib3N0LmN1cnJlbnRBY3Rpb24pLnRvQmUoJ2RlcGxveScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ0kgbW9kZSBiZWhhdmlvcicsICgpID0+IHtcbiAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgIGlvSG9zdC5pc1RUWSA9IHRydWU7XG4gICAgICBpb0hvc3QuaXNDSSA9IHRydWU7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd3cml0ZXMgdG8gc3Rkb3V0IGluIENJIG1vZGUgd2hlbiBsZXZlbCBpcyBub3QgZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBpb0hvc3Qubm90aWZ5KHtcbiAgICAgICAgdGltZTogbmV3IERhdGUoKSxcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgYWN0aW9uOiAnc3ludGgnLFxuICAgICAgICBjb2RlOiAnQ0RLX1RPT0xLSVRfVzAwMDEnLFxuICAgICAgICBtZXNzYWdlOiAnY2kgbWVzc2FnZScsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGNoYWxrLndoaXRlKCdjaSBtZXNzYWdlJykgKyAnXFxuJyk7XG4gICAgICBleHBlY3QobW9ja1N0ZGVycikubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3dyaXRlcyB0byBzdGRlcnIgZm9yIGVycm9yIGxldmVsIGluIENJIG1vZGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBpb0hvc3Qubm90aWZ5KHtcbiAgICAgICAgdGltZTogbmV3IERhdGUoKSxcbiAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgIGFjdGlvbjogJ3N5bnRoJyxcbiAgICAgICAgY29kZTogJ0NES19UT09MS0lUX0UwMDAxJyxcbiAgICAgICAgbWVzc2FnZTogJ2NpIGVycm9yIG1lc3NhZ2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RkZXJyKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChjaGFsay5yZWQoJ2NpIGVycm9yIG1lc3NhZ2UnKSArICdcXG4nKTtcbiAgICAgIGV4cGVjdChtb2NrU3Rkb3V0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndGltZXN0YW1wIGhhbmRsaW5nJywgKCkgPT4ge1xuICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgaW9Ib3N0LmlzVFRZID0gdHJ1ZTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2luY2x1ZGVzIHRpbWVzdGFtcCBmb3IgREVCVUcgbGV2ZWwgd2l0aCBncmF5IGNvbG9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdERhdGUgPSBuZXcgRGF0ZSgnMjAyNC0wMS0wMVQxMjozNDo1NicpO1xuICAgICAgYXdhaXQgaW9Ib3N0Lm5vdGlmeSh7XG4gICAgICAgIHRpbWU6IHRlc3REYXRlLFxuICAgICAgICBsZXZlbDogJ2RlYnVnJyxcbiAgICAgICAgYWN0aW9uOiAnc3ludGgnLFxuICAgICAgICBjb2RlOiAnQ0RLX1RPT0xLSVRfSTAwMDEnLFxuICAgICAgICBtZXNzYWdlOiAnZGVidWcgbWVzc2FnZScsXG4gICAgICAgIGZvcmNlU3Rkb3V0OiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3Rkb3V0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChgWzEyOjM0OjU2XSAke2NoYWxrLmdyYXkoJ2RlYnVnIG1lc3NhZ2UnKX1cXG5gKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2V4Y2x1ZGVzIHRpbWVzdGFtcCBmb3Igb3RoZXIgbGV2ZWxzIGJ1dCBpbmNsdWRlcyBjb2xvcicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3REYXRlID0gbmV3IERhdGUoJzIwMjQtMDEtMDFUMTI6MzQ6NTYnKTtcbiAgICAgIGF3YWl0IGlvSG9zdC5ub3RpZnkoe1xuICAgICAgICB0aW1lOiB0ZXN0RGF0ZSxcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgYWN0aW9uOiAnc3ludGgnLFxuICAgICAgICBjb2RlOiAnQ0RLX1RPT0xLSVRfSTAwMDEnLFxuICAgICAgICBtZXNzYWdlOiAnaW5mbyBtZXNzYWdlJyxcbiAgICAgICAgZm9yY2VTdGRvdXQ6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGRvdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGNoYWxrLndoaXRlKCdpbmZvIG1lc3NhZ2UnKSArICdcXG4nKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2Vycm9yIGhhbmRsaW5nJywgKCkgPT4ge1xuICAgIHRlc3QoJ3JlamVjdHMgb24gd3JpdGUgZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gICAgICBqZXN0LnNweU9uKHByb2Nlc3Muc3Rkb3V0LCAnd3JpdGUnKS5tb2NrSW1wbGVtZW50YXRpb24oKF86IGFueSwgY2FsbGJhY2s6IGFueSkgPT4ge1xuICAgICAgICBpZiAoY2FsbGJhY2spIGNhbGxiYWNrKG5ldyBFcnJvcignV3JpdGUgZmFpbGVkJykpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCBleHBlY3QoaW9Ib3N0Lm5vdGlmeSh7XG4gICAgICAgIHRpbWU6IG5ldyBEYXRlKCksXG4gICAgICAgIGxldmVsOiAnaW5mbycsXG4gICAgICAgIGFjdGlvbjogJ3N5bnRoJyxcbiAgICAgICAgY29kZTogJ0NES19UT09MS0lUX0kwMDAxJyxcbiAgICAgICAgbWVzc2FnZTogJ3Rlc3QgbWVzc2FnZScsXG4gICAgICAgIGZvcmNlU3Rkb3V0OiB0cnVlLFxuICAgICAgfSkpLnJlamVjdHMudG9UaHJvdygnV3JpdGUgZmFpbGVkJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdyZXF1ZXN0UmVzcG9uc2UnLCAoKSA9PiB7XG4gICAgdGVzdCgnbG9ncyBtZXNzYWdlcyBhbmQgcmV0dXJucyBkZWZhdWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgaW9Ib3N0LmlzVFRZID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgaW9Ib3N0LnJlcXVlc3RSZXNwb25zZSh7XG4gICAgICAgIHRpbWU6IG5ldyBEYXRlKCksXG4gICAgICAgIGxldmVsOiAnaW5mbycsXG4gICAgICAgIGFjdGlvbjogJ3N5bnRoJyxcbiAgICAgICAgY29kZTogJ0NES19UT09MS0lUX0kwMDAxJyxcbiAgICAgICAgbWVzc2FnZTogJ3Rlc3QgbWVzc2FnZScsXG4gICAgICAgIGRlZmF1bHRSZXNwb25zZTogJ2RlZmF1bHQgcmVzcG9uc2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RkZXJyKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChjaGFsay53aGl0ZSgndGVzdCBtZXNzYWdlJykgKyAnXFxuJyk7XG4gICAgICBleHBlY3QocmVzcG9uc2UpLnRvQmUoJ2RlZmF1bHQgcmVzcG9uc2UnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==