stack-monitor.test.js
1 "use strict"; 2 Object.defineProperty(exports, "__esModule", { value: true }); 3 const stack_activity_monitor_1 = require("../../lib/api/util/cloudformation/stack-activity-monitor"); 4 const aws_1 = require("../integ/helpers/aws"); 5 const mock_sdk_1 = require("./mock-sdk"); 6 let sdk; 7 let printer; 8 beforeEach(() => { 9 sdk = new mock_sdk_1.MockSdk(); 10 printer = new FakePrinter(); 11 }); 12 test('continue to the next page if it exists', async () => { 13 await testMonitorWithEventCalls([ 14 (request) => { 15 expect(request.NextToken).toBeUndefined(); 16 return { 17 StackEvents: [event(102)], 18 NextToken: 'some-token', 19 }; 20 }, 21 (request) => { 22 expect(request.NextToken).toBe('some-token'); 23 return { 24 StackEvents: [event(101)], 25 }; 26 }, 27 ]); 28 // Printer sees them in chronological order 29 expect(printer.eventIds).toEqual(['101', '102']); 30 }); 31 test('do not page further if we already saw the last event', async () => { 32 await testMonitorWithEventCalls([ 33 (request) => { 34 expect(request.NextToken).toBeUndefined(); 35 return { 36 StackEvents: [event(101)], 37 }; 38 }, 39 (request) => { 40 expect(request.NextToken).toBeUndefined(); 41 return { 42 StackEvents: [event(102), event(101)], 43 NextToken: 'some-token', 44 }; 45 }, 46 (request) => { 47 // Did not use the token 48 expect(request.NextToken).toBeUndefined(); 49 return {}; 50 }, 51 ]); 52 // Seen in chronological order 53 expect(printer.eventIds).toEqual(['101', '102']); 54 }); 55 test('do not page further if the last event is too old', async () => { 56 await testMonitorWithEventCalls([ 57 (request) => { 58 expect(request.NextToken).toBeUndefined(); 59 return { 60 StackEvents: [event(101), event(95)], 61 NextToken: 'some-token', 62 }; 63 }, 64 (request) => { 65 // Start again from the top 66 expect(request.NextToken).toBeUndefined(); 67 return {}; 68 }, 69 ]); 70 // Seen only the new one 71 expect(printer.eventIds).toEqual(['101']); 72 }); 73 test('do a final request after the monitor is stopped', async () => { 74 await testMonitorWithEventCalls([ 75 // Before stop 76 (request) => { 77 expect(request.NextToken).toBeUndefined(); 78 return { 79 StackEvents: [event(101)], 80 }; 81 }, 82 ], 83 // After stop 84 [ 85 (request) => { 86 expect(request.NextToken).toBeUndefined(); 87 return { 88 StackEvents: [event(102), event(101)], 89 }; 90 }, 91 ]); 92 // Seen both 93 expect(printer.eventIds).toEqual(['101', '102']); 94 }); 95 const T0 = 1597837230504; 96 // Events 0-99 are before we started paying attention 97 const T100 = T0 + 100 * 1000; 98 function event(nr) { 99 return { 100 EventId: `${nr}`, 101 StackId: 'StackId', 102 StackName: 'StackName', 103 Timestamp: new Date(T0 + nr * 1000), 104 }; 105 } 106 async function testMonitorWithEventCalls(beforeStopInvocations, afterStopInvocations = []) { 107 let describeStackEvents = jest.fn(); 108 let finished = false; 109 for (const invocation of beforeStopInvocations) { 110 const invocation_ = invocation; // Capture loop variable in local because of closure semantics 111 const isLast = invocation === beforeStopInvocations[beforeStopInvocations.length - 1]; 112 describeStackEvents = describeStackEvents.mockImplementationOnce(request => { 113 const ret = invocation_(request); 114 if (isLast) { 115 finished = true; 116 } 117 return ret; 118 }); 119 } 120 for (const invocation of afterStopInvocations) { 121 describeStackEvents = describeStackEvents.mockImplementationOnce(invocation); 122 } 123 describeStackEvents.mockImplementation(() => { return {}; }); 124 sdk.stubCloudFormation({ describeStackEvents }); 125 const monitor = new stack_activity_monitor_1.StackActivityMonitor(sdk.cloudFormation(), 'StackName', printer, undefined, new Date(T100)).start(); 126 await waitForCondition(() => finished); 127 await monitor.stop(); 128 } 129 class FakePrinter { 130 constructor() { 131 this.updateSleep = 0; 132 this.activities = []; 133 } 134 get eventIds() { 135 return this.activities.map(a => a.event.EventId); 136 } 137 addActivity(activity) { 138 this.activities.push(activity); 139 } 140 print() { } 141 start() { } 142 stop() { } 143 } 144 async function waitForCondition(cb) { 145 while (!cb()) { 146 await aws_1.sleep(10); 147 } 148 } 149 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stbW9uaXRvci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhY2stbW9uaXRvci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEscUdBQWlJO0FBQ2pJLDhDQUE2QztBQUM3Qyx5Q0FBcUM7QUFFckMsSUFBSSxHQUFZLENBQUM7QUFDakIsSUFBSSxPQUFvQixDQUFDO0FBQ3pCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxHQUFHLEdBQUcsSUFBSSxrQkFBTyxFQUFFLENBQUM7SUFDcEIsT0FBTyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFDOUIsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsd0NBQXdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDeEQsTUFBTSx5QkFBeUIsQ0FBQztRQUM5QixDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ1YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUMxQyxPQUFPO2dCQUNMLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDekIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztRQUNKLENBQUM7UUFDRCxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ1YsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDN0MsT0FBTztnQkFDTCxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDMUIsQ0FBQztRQUNKLENBQUM7S0FDRixDQUFDLENBQUM7SUFFSCwyQ0FBMkM7SUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUNuRCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxzREFBc0QsRUFBRSxLQUFL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QztJQUU3RCxHQUFHLENBQUMsa0JBQWtCLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLENBQUM7SUFFaEQsTUFBTSxPQUFPLEdBQUcsSUFBSSw2Q0FBb0IsQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUN4SCxNQUFNLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ3ZCLENBQUM7QUFHRCxNQUFNLFdBQVc7SUFBakI7UUFDUyxnQkFBVyxHQUFXLENBQUMsQ0FBQztRQUNmLGVBQVUsR0FBb0IsRUFBRSxDQUFDO0lBYW5ELENBQUM7SUFYQyxJQUFXLFFBQVE7UUFDakIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVNLFdBQVcsQ0FBQyxRQUF1QjtRQUN4QyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRU0sS0FBSyxLQUFXLENBQUM7SUFDakIsS0FBSyxLQUFXLENBQUM7SUFDakIsSUFBSSxLQUFXLENBQUM7Q0FDeEI7QUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsRUFBaUI7SUFDL0MsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUFFO1FBQ1osTUFBTSxXQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDakI7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2tBY3Rpdml0eU1vbml0b3IsIElBY3Rpdml0eVByaW50ZXIsIFN0YWNrQWN0aXZpdHkgfSBmcm9tICcuLi8uLi9saWIvYXBpL3V0aWwvY2xvdWRmb3JtYXRpb24vc3RhY2stYWN0aXZpdHktbW9uaXRvcic7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJy4uL2ludGVnL2hlbHBlcnMvYXdzJztcbmltcG9ydCB7IE1vY2tTZGsgfSBmcm9tICcuL21vY2stc2RrJztcblxubGV0IHNkazogTW9ja1NkaztcbmxldCBwcmludGVyOiBGYWtlUHJpbnRlcjtcbmJlZm9yZUVhY2goKCkgPT4ge1xuICBzZGsgPSBuZXcgTW9ja1NkaygpO1xuICBwcmludGVyID0gbmV3IEZha2VQcmludGVyKCk7XG59KTtcblxudGVzdCgnY29udGludWUgdG8gdGhlIG5leHQgcGFnZSBpZiBpdCBleGlzdHMnLCBhc3luYyAoKSA9PiB7XG4gIGF3YWl0IHRlc3RNb25pdG9yV2l0aEV2ZW50Q2FsbHMoW1xuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAyKV0sXG4gICAgICAgIE5leHRUb2tlbjogJ3NvbWUtdG9rZW4nLFxuICAgICAgfTtcbiAgICB9LFxuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmUoJ3NvbWUtdG9rZW4nKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKV0sXG4gICAgICB9O1xuICAgIH0sXG4gIF0pO1xuXG4gIC8vIFByaW50ZXIgc2VlcyB0aGVtIGluIGNocm9ub2xvZ2ljYWwgb3JkZXJcbiAgZXhwZWN0KHByaW50ZXIuZXZlbnRJZHMpLnRvRXF1YWwoWycxMDEnLCAnMTAyJ10pO1xufSk7XG5cbnRlc3QoJ2RvIG5vdCBwYWdlIGZ1cnRoZXIgaWYgd2UgYWxyZWFkeSBzYXcgdGhlIGxhc3QgZXZlbnQnLCBhc3luYyAoKSA9PiB7XG4gIGF3YWl0IHRlc3RNb25pdG9yV2l0aEV2ZW50Q2FsbHMoW1xuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKV0sXG4gICAgICB9O1xuICAgIH0sXG4gICAgKHJlcXVlc3QpID0+IHtcbiAgICAgIGV4cGVjdChyZXF1ZXN0Lk5leHRUb2tlbikudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgU3RhY2tFdmVudHM6IFtldmVudCgxMDIpLCBldmVudCgxMDEpXSxcbiAgICAgICAgTmV4dFRva2VuOiAnc29tZS10b2tlbicsXG4gICAgICB9O1xuICAgIH0sXG4gICAgKHJlcXVlc3QpID0+IHtcbiAgICAgIC8vIERpZCBub3QgdXNlIHRoZSB0b2tlblxuICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgXSk7XG5cbiAgLy8gU2VlbiBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyXG4gIGV4cGVjdChwcmludGVyLmV2ZW50SWRzKS50b0VxdWFsKFsnMTAxJywgJzEwMiddKTtcbn0pO1xuXG50ZXN0KCdkbyBub3QgcGFnZSBmdXJ0aGVyIGlmIHRoZSBsYXN0IGV2ZW50IGlzIHRvbyBvbGQnLCBhc3luYyAoKSA9PiB7XG4gIGF3YWl0IHRlc3RNb25pdG9yV2l0aEV2ZW50Q2FsbHMoW1xuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKSwgZXZlbnQoOTUpXSxcbiAgICAgICAgTmV4dFRva2VuOiAnc29tZS10b2tlbicsXG4gICAgICB9O1xuICAgIH0sXG4gICAgKHJlcXVlc3QpID0+IHtcbiAgICAgIC8vIFN0YXJ0IGFnYWluIGZyb20gdGhlIHRvcFxuICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgXSk7XG5cbiAgLy8gU2VlbiBvbmx5IHRoZSBuZXcgb25lXG4gIGV4cGVjdChwcmludGVyLmV2ZW50SWRzKS50b0VxdWFsKFsnMTAxJ10pO1xufSk7XG5cbnRlc3QoJ2RvIGEgZmluYWwgcmVxdWVzdCBhZnRlciB0aGUgbW9uaXRvciBpcyBzdG9wcGVkJywgYXN5bmMgKCkgPT4ge1xuICBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAvLyBCZWZvcmUgc3RvcFxuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKV0sXG4gICAgICB9O1xuICAgIH0sXG4gIF0sXG4gIC8vIEFmdGVyIHN0b3BcbiAgW1xuICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAyKSwgZXZlbnQoMTAxKV0sXG4gICAgICB9O1xuICAgIH0sXG4gIF0pO1xuXG4gIC8vIFNlZW4gYm90aFxuICBleHBlY3QocHJpbnRlci5ldmVudElkcykudG9FcXVhbChbJzEwMScsICcxMDInXSk7XG59KTtcblxuY29uc3QgVDAgPSAxNTk3ODM3MjMwNTA0O1xuXG4vLyBFdmVudHMgMC05OSBhcmUgYmVmb3JlIHdlIHN0YXJ0ZWQgcGF5aW5nIGF0dGVudGlvblxuY29uc3QgVDEwMCA9IFQwICsgMTAwICogMTAwMDtcblxuZnVuY3Rpb24gZXZlbnQobnI6IG51bWJlcik6IEFXUy5DbG91ZEZvcm1hdGlvbi5TdGFja0V2ZW50IHtcbiAgcmV0dXJuIHtcbiAgICBFdmVudElkOiBgJHtucn1gLFxuICAgIFN0YWNrSWQ6ICdTdGFja0lkJyxcbiAgICBTdGFja05hbWU6ICdTdGFja05hbWUnLFxuICAgIFRpbWVzdGFtcDogbmV3IERhdGUoVDAgKyBuciAqIDEwMDApLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFxuICBiZWZvcmVTdG9wSW52b2NhdGlvbnM6IEFycmF5PCh4OiBBV1MuQ2xvdWRGb3JtYXRpb24uRGVzY3JpYmVTdGFja0V2ZW50c0lucHV0KSA9PiBBV1MuQ2xvdWRGb3JtYXRpb24uRGVzY3JpYmVTdGFja0V2ZW50c091dHB1dD4sXG4gIGFmdGVyU3RvcEludm9jYXRpb25zOiBBcnJheTwoeDogQVdTLkNsb3VkRm9ybWF0aW9uLkRlc2NyaWJlU3RhY2tFdmVudHNJbnB1dCkgPT4gQVdTLkNsb3VkRm9ybWF0aW9uLkRlc2NyaWJlU3RhY2tFdmVudHNPdXRwdXQ+ID0gW10sXG4pIHtcbiAgbGV0IGRlc2NyaWJlU3RhY2tFdmVudHMgPSAoamVzdC5mbigpIGFzIGplc3QuTW9jazxBV1MuQ2xvdWRGb3JtYXRpb24uRGVzY3JpYmVTdGFja0V2ZW50c091dHB1dCwgW0FXUy5DbG91ZEZvcm1hdGlvbi5EZXNjcmliZVN0YWNrRXZlbnRzSW5wdXRdPik7XG5cbiAgbGV0IGZpbmlzaGVkID0gZmFsc2U7XG5cbiAgZm9yIChjb25zdCBpbnZvY2F0aW9uIG9mIGJlZm9yZVN0b3BJbnZvY2F0aW9ucykge1xuICAgIGNvbnN0IGludm9jYXRpb25fID0gaW52b2NhdGlvbjsgLy8gQ2FwdHVyZSBsb29wIHZhcmlhYmxlIGluIGxvY2FsIGJlY2F1c2Ugb2YgY2xvc3VyZSBzZW1hbnRpY3NcbiAgICBjb25zdCBpc0xhc3QgPSBpbnZvY2F0aW9uID09PSBiZWZvcmVTdG9wSW52b2NhdGlvbnNbYmVmb3JlU3RvcEludm9jYXRpb25zLmxlbmd0aCAtIDFdO1xuICAgIGRlc2NyaWJlU3RhY2tFdmVudHMgPSBkZXNjcmliZVN0YWNrRXZlbnRzLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UocmVxdWVzdCA9PiB7XG4gICAgICBjb25zdCByZXQgPSBpbnZvY2F0aW9uXyhyZXF1ZXN0KTtcbiAgICAgIGlmIChpc0xhc3QpIHtcbiAgICAgICAgZmluaXNoZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJldDtcbiAgICB9KTtcbiAgfVxuICBmb3IgKGNvbnN0IGludm9jYXRpb24gb2YgYWZ0ZXJTdG9wSW52b2NhdGlvbnMpIHtcbiAgICBkZXNjcmliZVN0YWNrRXZlbnRzID0gZGVzY3JpYmVTdGFja0V2ZW50cy5tb2NrSW1wbGVtZW50YXRpb25PbmNlKGludm9jYXRpb24pO1xuICB9XG4gIGRlc2NyaWJlU3RhY2tFdmVudHMubW9ja0ltcGxlbWVudGF0aW9uKCgpID0+IHsgcmV0dXJuIHt9OyB9KTtcblxuICBzZGsuc3R1YkNsb3VkRm9ybWF0aW9uKHsgZGVzY3JpYmVTdGFja0V2ZW50cyB9KTtcblxuICBjb25zdCBtb25pdG9yID0gbmV3IFN0YWNrQWN0aXZpdHlNb25pdG9yKHNkay5jbG91ZEZvcm1hdGlvbigpLCAnU3RhY2tOYW1lJywgcHJpbnRlciwgdW5kZWZpbmVkLCBuZXcgRGF0ZShUMTAwKSkuc3RhcnQoKTtcbiAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbigoKSA9PiBmaW5pc2hlZCk7XG4gIGF3YWl0IG1vbml0b3Iuc3RvcCgpO1xufVxuXG5cbmNsYXNzIEZha2VQcmludGVyIGltcGxlbWVudHMgSUFjdGl2aXR5UHJpbnRlciB7XG4gIHB1YmxpYyB1cGRhdGVTbGVlcDogbnVtYmVyID0gMDtcbiAgcHVibGljIHJlYWRvbmx5IGFjdGl2aXRpZXM6IFN0YWNrQWN0aXZpdHlbXSA9IFtdO1xuXG4gIHB1YmxpYyBnZXQgZXZlbnRJZHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWN0aXZpdGllcy5tYXAoYSA9PiBhLmV2ZW50LkV2ZW50SWQpO1xuICB9XG5cbiAgcHVibGljIGFkZEFjdGl2aXR5KGFjdGl2aXR5OiBTdGFja0FjdGl2aXR5KTogdm9pZCB7XG4gICAgdGhpcy5hY3Rpdml0aWVzLnB1c2goYWN0aXZpdHkpO1xuICB9XG5cbiAgcHVibGljIHByaW50KCk6IHZvaWQgeyB9XG4gIHB1YmxpYyBzdGFydCgpOiB2b2lkIHsgfVxuICBwdWJsaWMgc3RvcCgpOiB2b2lkIHsgfVxufVxuXG5hc3luYyBmdW5jdGlvbiB3YWl0Rm9yQ29uZGl0aW9uKGNiOiAoKSA9PiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gIHdoaWxlICghY2IoKSkge1xuICAgIGF3YWl0IHNsZWVwKDEwKTtcbiAgfVxufVxuIl19