@appium/support 2.55.2 → 2.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/build/lib/env.js +102 -0
  2. package/build/lib/fs.js +74 -56
  3. package/build/lib/image-util.js +4 -332
  4. package/build/lib/index.js +18 -6
  5. package/build/lib/log-internal.js +2 -4
  6. package/build/lib/logger.js +2 -4
  7. package/build/lib/logging.js +2 -4
  8. package/build/lib/mjpeg.js +2 -4
  9. package/build/lib/mkdirp.js +7 -11
  10. package/build/lib/net.js +2 -4
  11. package/build/lib/node.js +99 -2
  12. package/build/lib/npm.js +240 -0
  13. package/build/lib/plist.js +2 -4
  14. package/build/lib/process.js +2 -4
  15. package/build/lib/system.js +2 -4
  16. package/build/lib/tempdir.js +2 -4
  17. package/build/lib/timing.js +2 -4
  18. package/build/lib/util.js +6 -8
  19. package/build/lib/zip.js +4 -8
  20. package/lib/env.js +162 -0
  21. package/lib/fs.js +193 -69
  22. package/lib/image-util.js +3 -570
  23. package/lib/index.js +8 -2
  24. package/lib/log-internal.js +2 -2
  25. package/lib/logging.js +1 -1
  26. package/lib/mkdirp.js +3 -6
  27. package/lib/net.js +4 -4
  28. package/lib/node.js +104 -1
  29. package/lib/npm.js +335 -0
  30. package/lib/tempdir.js +6 -6
  31. package/lib/util.js +28 -24
  32. package/lib/zip.js +7 -8
  33. package/package.json +20 -9
  34. package/build/test/assets/sample_binary.plist +0 -0
  35. package/build/test/assets/sample_text.plist +0 -28
  36. package/build/test/fs-specs.js +0 -264
  37. package/build/test/helpers.js +0 -35
  38. package/build/test/image-util-e2e-specs.js +0 -227
  39. package/build/test/index-specs.js +0 -49
  40. package/build/test/log-internals-specs.js +0 -97
  41. package/build/test/logger/helpers.js +0 -71
  42. package/build/test/logger/logger-force-specs.js +0 -41
  43. package/build/test/logger/logger-normal-specs.js +0 -113
  44. package/build/test/logger/logger-test-specs.js +0 -40
  45. package/build/test/mjpeg-e2e-specs.js +0 -96
  46. package/build/test/net-e2e-specs.js +0 -32
  47. package/build/test/node-e2e-specs.js +0 -22
  48. package/build/test/plist-specs.js +0 -54
  49. package/build/test/process-specs.js +0 -104
  50. package/build/test/system-specs.js +0 -136
  51. package/build/test/tempdir-specs.js +0 -86
  52. package/build/test/timing-specs.js +0 -125
  53. package/build/test/util-e2e-specs.js +0 -136
  54. package/build/test/util-specs.js +0 -537
  55. package/build/test/zip-e2e-specs.js +0 -233
@@ -1,233 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- require("source-map-support/register");
6
-
7
- var _path = _interopRequireDefault(require("path"));
8
-
9
- var zip = _interopRequireWildcard(require("../lib/zip"));
10
-
11
- var _index = require("../lib/index");
12
-
13
- var _helpers = require("./helpers");
14
-
15
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
-
17
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
-
19
- describe('#zip', function () {
20
- const optionMap = new Map([['native JS unzip', {}], ['system unzip', {
21
- useSystemUnzip: true
22
- }]]);
23
- optionMap.forEach((options, desc) => {
24
- describe(desc, function () {
25
- let assetsPath;
26
- let zippedFilePath;
27
- let tmpRoot;
28
- beforeEach(async function () {
29
- assetsPath = await _index.tempDir.openDir();
30
- tmpRoot = await _index.tempDir.openDir();
31
- const zippedBase64 = 'UEsDBAoAAAAAALlzk0oAAAAAAAAAAAAAAAAJABAAdW56aXBwZWQvVVgMANBO+VjO1vdY9QEUAFBLAwQKAAAAAADAc5NKAAAAAAAAAAAAAAAAEgAQAHVuemlwcGVkL3Rlc3QtZGlyL1VYDADQTvlY19b3WPUBFABQSwMEFAAIAAgAwnOTSgAAAAAAAAAAAAAAABcAEAB1bnppcHBlZC90ZXN0LWRpci9hLnR4dFVYDACDTvlY3Nb3WPUBFADzSM3JyVcIzy/KSQEAUEsHCFaxF0oNAAAACwAAAFBLAwQUAAgACADEc5NKAAAAAAAAAAAAAAAAFwAQAHVuemlwcGVkL3Rlc3QtZGlyL2IudHh0VVgMAINO+Vjf1vdY9QEUAHPLz1dwSiwCAFBLBwhIfrZJCQAAAAcAAABQSwECFQMKAAAAAAC5c5NKAAAAAAAAAAAAAAAACQAMAAAAAAAAAABA7UEAAAAAdW56aXBwZWQvVVgIANBO+VjO1vdYUEsBAhUDCgAAAAAAwHOTSgAAAAAAAAAAAAAAABIADAAAAAAAAAAAQO1BNwAAAHVuemlwcGVkL3Rlc3QtZGlyL1VYCADQTvlY19b3WFBLAQIVAxQACAAIAMJzk0pWsRdKDQAAAAsAAAAXAAwAAAAAAAAAAECkgXcAAAB1bnppcHBlZC90ZXN0LWRpci9hLnR4dFVYCACDTvlY3Nb3WFBLAQIVAxQACAAIAMRzk0pIfrZJCQAAAAcAAAAXAAwAAAAAAAAAAECkgdkAAAB1bnppcHBlZC90ZXN0LWRpci9iLnR4dFVYCACDTvlY39b3WFBLBQYAAAAABAAEADEBAAA3AQAAAAA=';
32
- zippedFilePath = _path.default.resolve(tmpRoot, 'zipped.zip');
33
- await _index.fs.writeFile(zippedFilePath, zippedBase64, 'base64');
34
- await zip.extractAllTo(zippedFilePath, assetsPath, options);
35
- });
36
- afterEach(async function () {
37
- for (const tmpPath of [assetsPath, tmpRoot]) {
38
- if (!(await _index.fs.exists(tmpPath))) {
39
- continue;
40
- }
41
-
42
- await _index.fs.rimraf(tmpPath);
43
- }
44
- });
45
- describe('extractAllTo()', function () {
46
- it('should extract contents of a .zip file to a directory', async function () {
47
- await _index.fs.readFile(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt'), {
48
- encoding: 'utf8'
49
- }).should.eventually.equal('Hello World');
50
- await _index.fs.readFile(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'b.txt'), {
51
- encoding: 'utf8'
52
- }).should.eventually.equal('Foo Bar');
53
- });
54
- });
55
- describe('assertValidZip', function () {
56
- it('should not throw an error if a valid ZIP file is passed', async function () {
57
- await zip.assertValidZip(zippedFilePath).should.eventually.be.fulfilled;
58
- });
59
- it('should throw an error if the file does not exist', async function () {
60
- await zip.assertValidZip('blabla').should.eventually.be.rejected;
61
- });
62
- it('should throw an error if the file is invalid', async function () {
63
- await zip.assertValidZip(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt')).should.eventually.be.rejected;
64
- });
65
- });
66
- describe('readEntries()', function () {
67
- const expectedEntries = [{
68
- name: 'unzipped/'
69
- }, {
70
- name: 'unzipped/test-dir/'
71
- }, {
72
- name: 'unzipped/test-dir/a.txt',
73
- contents: 'Hello World'
74
- }, {
75
- name: 'unzipped/test-dir/b.txt',
76
- contents: 'Foo Bar'
77
- }];
78
- it('should iterate entries (directories and files) of zip file', async function () {
79
- let i = 0;
80
- await zip.readEntries(zippedFilePath, async ({
81
- entry,
82
- extractEntryTo
83
- }) => {
84
- entry.fileName.should.equal(expectedEntries[i].name);
85
-
86
- if (expectedEntries[i].contents) {
87
- await extractEntryTo(tmpRoot);
88
- await _index.fs.readFile(_path.default.resolve(tmpRoot, entry.fileName), {
89
- flags: 'r',
90
- encoding: 'utf8'
91
- }).should.eventually.equal(expectedEntries[i].contents);
92
- }
93
-
94
- i++;
95
- });
96
- });
97
- it('should stop iterating zipFile if onEntry callback returns false', async function () {
98
- let i = 0;
99
- await zip.readEntries(zippedFilePath, async () => {
100
- i++;
101
- return false;
102
- });
103
- i.should.equal(1);
104
- });
105
- it('should be rejected if it uses a non-zip file', async function () {
106
- let promise = zip.readEntries(_path.default.resolve(assetsPath, 'unzipped', 'test-dir', 'a.txt'), async () => {});
107
- await promise.should.eventually.be.rejected;
108
- });
109
- });
110
- describe('toInMemoryZip()', function () {
111
- it('should convert a local file to an in-memory zip buffer', async function () {
112
- const testFolder = _path.default.resolve(assetsPath, 'unzipped');
113
-
114
- const buffer = await zip.toInMemoryZip(testFolder);
115
- Buffer.isBuffer(buffer).should.be.true;
116
- await _index.fs.writeFile(_path.default.resolve(tmpRoot, 'test.zip'), buffer);
117
- await zip.extractAllTo(_path.default.resolve(tmpRoot, 'test.zip'), _path.default.resolve(tmpRoot, 'output'), {
118
- fileNamesEncoding: 'utf8'
119
- });
120
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
121
- encoding: 'utf8'
122
- }).should.eventually.equal('Hello World');
123
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
124
- encoding: 'utf8'
125
- }).should.eventually.equal('Foo Bar');
126
- });
127
- it('should convert a local folder to an in-memory base64-encoded zip buffer', async function () {
128
- const testFolder = _path.default.resolve(assetsPath, 'unzipped');
129
-
130
- const buffer = await zip.toInMemoryZip(testFolder, {
131
- encodeToBase64: true
132
- });
133
- await _index.fs.writeFile(_path.default.resolve(tmpRoot, 'test.zip'), Buffer.from(buffer.toString(), 'base64'));
134
- await zip.extractAllTo(_path.default.resolve(tmpRoot, 'test.zip'), _path.default.resolve(tmpRoot, 'output'));
135
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
136
- encoding: 'utf8'
137
- }).should.eventually.equal('Hello World');
138
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
139
- encoding: 'utf8'
140
- }).should.eventually.equal('Foo Bar');
141
- });
142
- it('should be rejected if use a bad path', async function () {
143
- await zip.toInMemoryZip(_path.default.resolve(assetsPath, 'bad_path')).should.be.rejectedWith(/no such/i);
144
- });
145
- it('should be rejected if max size is exceeded', async function () {
146
- const testFolder = _path.default.resolve(assetsPath, 'unzipped');
147
-
148
- await zip.toInMemoryZip(testFolder, {
149
- maxSize: 1
150
- }).should.be.rejectedWith(/must not be greater/);
151
- });
152
- });
153
- describe('_extractEntryTo()', function () {
154
- let entry, mockZipFile, mockZipStream;
155
- beforeEach(async function () {
156
- entry = {
157
- fileName: _path.default.resolve(await _index.tempDir.openDir(), 'temp', 'file')
158
- };
159
- mockZipStream = new _helpers.MockReadWriteStream();
160
- mockZipFile = {
161
- openReadStream: (entry, cb) => cb(null, mockZipStream)
162
- };
163
- });
164
- it('should be rejected if zip stream emits an error', async function () {
165
- mockZipStream.pipe = () => {
166
- mockZipStream.emit('error', new Error('zip stream error'));
167
- };
168
-
169
- await zip._extractEntryTo(mockZipFile, entry).should.be.rejectedWith('zip stream error');
170
- });
171
- it('should be rejected if write stream emits an error', async function () {
172
- mockZipStream.pipe = writeStream => {
173
- writeStream.emit('error', new Error('write stream error'));
174
- mockZipStream.end();
175
- writeStream.end();
176
- };
177
-
178
- await zip._extractEntryTo(mockZipFile, entry).should.be.rejectedWith('write stream error');
179
- });
180
- });
181
- describe('toArchive', function () {
182
- it('should zip all files into an archive', async function () {
183
- const testFolder = _path.default.resolve(assetsPath, 'unzipped');
184
-
185
- const dstPath = _path.default.resolve(tmpRoot, 'test.zip');
186
-
187
- await zip.toArchive(dstPath, {
188
- cwd: testFolder
189
- });
190
- await zip.extractAllTo(dstPath, _path.default.resolve(tmpRoot, 'output'));
191
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'a.txt'), {
192
- encoding: 'utf8'
193
- }).should.eventually.equal('Hello World');
194
- await _index.fs.readFile(_path.default.resolve(tmpRoot, 'output', 'test-dir', 'b.txt'), {
195
- encoding: 'utf8'
196
- }).should.eventually.equal('Foo Bar');
197
- });
198
- });
199
- });
200
- });
201
- describe('unicode filename handling', function () {
202
- let zippedFilePath, assetsPath, tmpRoot;
203
- beforeEach(async function () {
204
- assetsPath = await _index.tempDir.openDir();
205
- tmpRoot = await _index.tempDir.openDir();
206
- const zippedBase64 = 'UEsDBBQACAAIABF8/EYAAAAAAAAAABoAAAATACAAa2Fuamkt5q2j5LiW5LiVLmFwcFVUDQAHAgO4VVpX+GBZV/hgdXgLAAEE9QEAAAQUAAAAK8nILFYAorz8EoWi1MScnEqFxDyFxIICLgBQSwcIR93jPhoAAAAaAAAAUEsBAhQDFAAIAAgAEXz8Rkfd4z4aAAAAGgAAABMAIAAAAAAAAAAAAKSBAAAAAGthbmppLeato+S4luS4lS5hcHBVVA0ABwIDuFVaV/hgWVf4YHV4CwABBPUBAAAEFAAAAFBLBQYAAAAAAQABAGEAAAB7AAAAAAA=';
207
- zippedFilePath = _path.default.resolve(tmpRoot, 'zipped.zip');
208
- await _index.fs.writeFile(zippedFilePath, zippedBase64, 'base64');
209
- await zip.extractAllTo(zippedFilePath, assetsPath, {
210
- useSystemUnzip: true
211
- });
212
- });
213
- afterEach(async function () {
214
- for (const tmpPath of [assetsPath, tmpRoot]) {
215
- if (!(await _index.fs.exists(tmpPath))) {
216
- continue;
217
- }
218
-
219
- await _index.fs.rimraf(tmpPath);
220
- }
221
- });
222
- it('should retain the proper filenames', async function () {
223
- const expectedPath = _path.default.join(assetsPath, 'kanji-正世丕.app');
224
-
225
- if (!(await _index.fs.exists(expectedPath))) {
226
- throw new chai.AssertionError(`Expected ${expectedPath} to exist, but it does not`);
227
- }
228
- });
229
- });
230
- });require('source-map-support').install();
231
-
232
-
233
- //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvemlwLWUyZS1zcGVjcy5qcyJdLCJuYW1lcyI6WyJkZXNjcmliZSIsIm9wdGlvbk1hcCIsIk1hcCIsInVzZVN5c3RlbVVuemlwIiwiZm9yRWFjaCIsIm9wdGlvbnMiLCJkZXNjIiwiYXNzZXRzUGF0aCIsInppcHBlZEZpbGVQYXRoIiwidG1wUm9vdCIsImJlZm9yZUVhY2giLCJ0ZW1wRGlyIiwib3BlbkRpciIsInppcHBlZEJhc2U2NCIsInBhdGgiLCJyZXNvbHZlIiwiZnMiLCJ3cml0ZUZpbGUiLCJ6aXAiLCJleHRyYWN0QWxsVG8iLCJhZnRlckVhY2giLCJ0bXBQYXRoIiwiZXhpc3RzIiwicmltcmFmIiwiaXQiLCJyZWFkRmlsZSIsImVuY29kaW5nIiwic2hvdWxkIiwiZXZlbnR1YWxseSIsImVxdWFsIiwiYXNzZXJ0VmFsaWRaaXAiLCJiZSIsImZ1bGZpbGxlZCIsInJlamVjdGVkIiwiZXhwZWN0ZWRFbnRyaWVzIiwibmFtZSIsImNvbnRlbnRzIiwiaSIsInJlYWRFbnRyaWVzIiwiZW50cnkiLCJleHRyYWN0RW50cnlUbyIsImZpbGVOYW1lIiwiZmxhZ3MiLCJwcm9taXNlIiwidGVzdEZvbGRlciIsImJ1ZmZlciIsInRvSW5NZW1vcnlaaXAiLCJCdWZmZXIiLCJpc0J1ZmZlciIsInRydWUiLCJmaWxlTmFtZXNFbmNvZGluZyIsImVuY29kZVRvQmFzZTY0IiwiZnJvbSIsInRvU3RyaW5nIiwicmVqZWN0ZWRXaXRoIiwibWF4U2l6ZSIsIm1vY2taaXBGaWxlIiwibW9ja1ppcFN0cmVhbSIsIk1vY2tSZWFkV3JpdGVTdHJlYW0iLCJvcGVuUmVhZFN0cmVhbSIsImNiIiwicGlwZSIsImVtaXQiLCJFcnJvciIsIl9leHRyYWN0RW50cnlUbyIsIndyaXRlU3RyZWFtIiwiZW5kIiwiZHN0UGF0aCIsInRvQXJjaGl2ZSIsImN3ZCIsImV4cGVjdGVkUGF0aCIsImpvaW4iLCJjaGFpIiwiQXNzZXJ0aW9uRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFB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QUFTLENBQUMsa0JBQWtCO0FBQzFCLFdBQUssTUFBTUMsT0FBWCxJQUFzQixDQUFDZCxVQUFELEVBQWFFLE9BQWIsQ0FBdEIsRUFBNkM7QUFDM0MsWUFBSSxFQUFDLE1BQU1PLFVBQUdNLE1BQUgsQ0FBVUQsT0FBVixDQUFQLENBQUosRUFBK0I7QUFDN0I7QUFDRDs7QUFDRCxjQUFNTCxVQUFHTyxNQUFILENBQVVGLE9BQVYsQ0FBTjtBQUNEO0FBQ0YsS0FQUSxDQUFUO0FBU0FHLElBQUFBLEVBQUUsQ0FBQyxvQ0FBRCxFQUF1QyxrQkFBa0I7QUFDekQsWUFBTThDLFlBQVksR0FBR3hELGNBQUt5RCxJQUFMLENBQVVoRSxVQUFWLEVBQXNCLGVBQXRCLENBQXJCOztBQUVBLFVBQUksRUFBQyxNQUFNUyxVQUFHTSxNQUFILENBQVVnRCxZQUFWLENBQVAsQ0FBSixFQUFvQztBQUNsQyxjQUFNLElBQUlFLElBQUksQ0FBQ0MsY0FBVCxDQUF5QixZQUFXSCxZQUFhLDRCQUFqRCxDQUFOO0FBQ0Q7QUFDRixLQU5DLENBQUY7QUFPRCxHQTdCTyxDQUFSO0FBOEJELENBNU5PLENBQVIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIHppcCBmcm9tICcuLi9saWIvemlwJztcbmltcG9ydCB7IHRlbXBEaXIsIGZzIH0gZnJvbSAnLi4vbGliL2luZGV4JztcbmltcG9ydCB7IE1vY2tSZWFkV3JpdGVTdHJlYW0gfSBmcm9tICcuL2hlbHBlcnMnO1xuXG5cbmRlc2NyaWJlKCcjemlwJywgZnVuY3Rpb24gKCkge1xuXG4gIGNvbnN0IG9wdGlvbk1hcCA9IG5ldyBNYXAoW1snbmF0aXZlIEpTIHVuemlwJywge31dLCBbJ3N5c3RlbSB1bnppcCcsIHt1c2VTeXN0ZW1VbnppcDogdHJ1ZX1dXSk7XG5cbiAgb3B0aW9uTWFwLmZvckVhY2goKG9wdGlvbnMsIGRlc2MpID0+IHtcbiAgICBkZXNjcmliZShkZXNjLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgYXNzZXRzUGF0aDtcbiAgICAgIGxldCB6aXBwZWRGaWxlUGF0aDtcbiAgICAgIGxldCB0bXBSb290O1xuXG4gICAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXNzZXRzUGF0aCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuICAgICAgICB0bXBSb290ID0gYXdhaXQgdGVtcERpci5vcGVuRGlyKCk7XG4gICAgICAgIGNvbnN0IHppcHBlZEJhc2U2NCA9ICdVRXNEQkFvQUFBQUFBTGx6azBvQUFBQUFBQUFBQUFBQUFBQUpBQkFBZFc1NmFYQndaV1F2VlZnTUFOQk8rVmpPMXZkWTlRRVVBRkJMQXdRS0FBQUFBQURBYzVOS0FBQUFBQUFBQUFBQUFBQUFFZ0FRQUhWdWVtbHdjR1ZrTDNSbGMzUXRaR2x5TDFWWURBRFFUdmxZMTliM1dQVUJGQUJRU3dNRUZBQUlBQWdBd25PVFNnQUFBQUFBQUFBQUFBQUFBQmNBRUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aExuUjRkRlZZREFDRFR2bFkzTmIzV1BVQkZBRHpTTTNKeVZjSXp5L0tTUUVBVUVzSENGYXhGMG9OQUFBQUN3QUFBRkJMQXdRVUFBZ0FDQURFYzVOS0FBQUFBQUFBQUFBQUFBQUFGd0FRQUhWdWVtbHdjR1ZrTDNSbGMzUXRaR2x5TDJJdWRIaDBWVmdNQUlOTytWamYxdmRZOVFFVUFIUEx6MWR3U2l3Q0FGQkxCd2hJZnJaSkNRQUFBQWNBQUFCUVN3RUNGUU1LQUFBQUFBQzVjNU5LQUFBQUFBQUFBQUFBQUFBQUNRQU1BQUFBQUFBQUFBQkE3VUVBQUFBQWRXNTZhWEJ3WldRdlZWZ0lBTkJPK1ZqTzF2ZFlVRXNCQWhVRENnQUFBQUFBd0hPVFNnQUFBQUFBQUFBQUFBQUFBQklBREFBQUFBQUFBQUFBUU8xQk53QUFBSFZ1ZW1sd2NHVmtMM1JsYzNRdFpHbHlMMVZZQ0FEUVR2bFkxOWIzV0ZCTEFRSVZBeFFBQ0FBSUFNSnprMHBXc1JkS0RRQUFBQXNBQUFBWEFBd0FBQUFBQUFBQUFFQ2tnWGNBQUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aExuUjRkRlZZQ0FDRFR2bFkzTmIzV0ZCTEFRSVZBeFFBQ0FBSUFNUnprMHBJZnJaSkNRQUFBQWNBQUFBWEFBd0FBQUFBQUFBQUFFQ2tnZGtBQUFCMWJucHBjSEJsWkM5MFpYTjBMV1JwY2k5aUxuUjRkRlZZQ0FDRFR2bFkzOWIzV0ZCTEJRWUFBQUFBQkFBRUFERUJBQUEzQVFBQUFBQT0nO1xuICAgICAgICB6aXBwZWRGaWxlUGF0aCA9IHBhdGgucmVzb2x2ZSh0bXBSb290LCAnemlwcGVkLnppcCcpO1xuICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUoemlwcGVkRmlsZVBhdGgsIHppcHBlZEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKHppcHBlZEZpbGVQYXRoLCBhc3NldHNQYXRoLCBvcHRpb25zKTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBmb3IgKGNvbnN0IHRtcFBhdGggb2YgW2Fzc2V0c1BhdGgsIHRtcFJvb3RdKSB7XG4gICAgICAgICAgaWYgKCFhd2FpdCBmcy5leGlzdHModG1wUGF0aCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBhd2FpdCBmcy5yaW1yYWYodG1wUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnZXh0cmFjdEFsbFRvKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgZXh0cmFjdCBjb250ZW50cyBvZiBhIC56aXAgZmlsZSB0byBhIGRpcmVjdG9yeScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtlbmNvZGluZzogJ3V0ZjgnfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0hlbGxvIFdvcmxkJyk7XG4gICAgICAgICAgYXdhaXQgZnMucmVhZEZpbGUocGF0aC5yZXNvbHZlKGFzc2V0c1BhdGgsICd1bnppcHBlZCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7ZW5jb2Rpbmc6ICd1dGY4J30pLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKCdGb28gQmFyJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdhc3NlcnRWYWxpZFppcCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBub3QgdGhyb3cgYW4gZXJyb3IgaWYgYSB2YWxpZCBaSVAgZmlsZSBpcyBwYXNzZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgemlwLmFzc2VydFZhbGlkWmlwKHppcHBlZEZpbGVQYXRoKS5zaG91bGQuZXZlbnR1YWxseS5iZS5mdWxmaWxsZWQ7XG4gICAgICAgIH0pO1xuICAgICAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZSBmaWxlIGRvZXMgbm90IGV4aXN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IHppcC5hc3NlcnRWYWxpZFppcCgnYmxhYmxhJykuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIGlmIHRoZSBmaWxlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgemlwLmFzc2VydFZhbGlkWmlwKHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnLCAndGVzdC1kaXInLCAnYS50eHQnKSkuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCdyZWFkRW50cmllcygpJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBleHBlY3RlZEVudHJpZXMgPSBbXG4gICAgICAgICAge25hbWU6ICd1bnppcHBlZC8nfSxcbiAgICAgICAgICB7bmFtZTogJ3VuemlwcGVkL3Rlc3QtZGlyLyd9LFxuICAgICAgICAgIHtuYW1lOiAndW56aXBwZWQvdGVzdC1kaXIvYS50eHQnLCBjb250ZW50czogJ0hlbGxvIFdvcmxkJ30sXG4gICAgICAgICAge25hbWU6ICd1bnppcHBlZC90ZXN0LWRpci9iLnR4dCcsIGNvbnRlbnRzOiAnRm9vIEJhcid9LFxuICAgICAgICBdO1xuXG4gICAgICAgIGl0KCdzaG91bGQgaXRlcmF0ZSBlbnRyaWVzIChkaXJlY3RvcmllcyBhbmQgZmlsZXMpIG9mIHppcCBmaWxlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgICBhd2FpdCB6aXAucmVhZEVudHJpZXMoemlwcGVkRmlsZVBhdGgsIGFzeW5jICh7ZW50cnksIGV4dHJhY3RFbnRyeVRvfSkgPT4ge1xuICAgICAgICAgICAgZW50cnkuZmlsZU5hbWUuc2hvdWxkLmVxdWFsKGV4cGVjdGVkRW50cmllc1tpXS5uYW1lKTtcblxuICAgICAgICAgICAgLy8gSWYgaXQncyBhIGZpbGUsIHRlc3QgdGhhdCB3ZSBjYW4gZXh0cmFjdCBpdCB0byBhIHRlbXBvcmFyeSBkaXJlY3RvcnkgYW5kIHRoYXQgdGhlIGNvbnRlbnRzIGFyZSBjb3JyZWN0XG4gICAgICAgICAgICBpZiAoZXhwZWN0ZWRFbnRyaWVzW2ldLmNvbnRlbnRzKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGV4dHJhY3RFbnRyeVRvKHRtcFJvb3QpO1xuICAgICAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgZW50cnkuZmlsZU5hbWUpLCB7XG4gICAgICAgICAgICAgICAgZmxhZ3M6ICdyJyxcbiAgICAgICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgICAgIH0pLnNob3VsZC5ldmVudHVhbGx5LmVxdWFsKGV4cGVjdGVkRW50cmllc1tpXS5jb250ZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpKys7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGl0KCdzaG91bGQgc3RvcCBpdGVyYXRpbmcgemlwRmlsZSBpZiBvbkVudHJ5IGNhbGxiYWNrIHJldHVybnMgZmFsc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgIGF3YWl0IHppcC5yZWFkRW50cmllcyh6aXBwZWRGaWxlUGF0aCwgYXN5bmMgKCkgPT4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBpLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiBpdCB1c2VzIGEgbm9uLXppcCBmaWxlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGxldCBwcm9taXNlID0gemlwLnJlYWRFbnRyaWVzKHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnLCAndGVzdC1kaXInLCAnYS50eHQnKSwgYXN5bmMgKCkgPT4ge30pO1xuICAgICAgICAgIGF3YWl0IHByb21pc2Uuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWQ7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd0b0luTWVtb3J5WmlwKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgY29udmVydCBhIGxvY2FsIGZpbGUgdG8gYW4gaW4tbWVtb3J5IHppcCBidWZmZXInLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgLy8gQ29udmVydCBkaXJlY3RvcnkgdG8gaW4tbWVtb3J5IGJ1ZmZlclxuICAgICAgICAgIGNvbnN0IHRlc3RGb2xkZXIgPSBwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJyk7XG4gICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgemlwLnRvSW5NZW1vcnlaaXAodGVzdEZvbGRlcik7XG4gICAgICAgICAgQnVmZmVyLmlzQnVmZmVyKGJ1ZmZlcikuc2hvdWxkLmJlLnRydWU7XG5cbiAgICAgICAgICAvLyBXcml0ZSB0aGUgYnVmZmVyIHRvIGEgemlwIGZpbGVcbiAgICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpLCBidWZmZXIpO1xuXG4gICAgICAgICAgLy8gVW56aXAgdGhlIGZpbGUgYW5kIHRlc3QgdGhhdCBpdCBoYXMgdGhlIHNhbWUgY29udGVudHMgYXMgdGhlIGRpcmVjdG9yeSB0aGF0IHdhcyB6aXBwZWRcbiAgICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKHBhdGgucmVzb2x2ZSh0bXBSb290LCAndGVzdC56aXAnKSwgcGF0aC5yZXNvbHZlKHRtcFJvb3QsICdvdXRwdXQnKSwge1xuICAgICAgICAgICAgZmlsZU5hbWVzRW5jb2Rpbmc6ICd1dGY4J1xuICAgICAgICAgIH0pO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBjb252ZXJ0IGEgbG9jYWwgZm9sZGVyIHRvIGFuIGluLW1lbW9yeSBiYXNlNjQtZW5jb2RlZCB6aXAgYnVmZmVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IHRlc3RGb2xkZXIgPSBwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ3VuemlwcGVkJyk7XG4gICAgICAgICAgY29uc3QgYnVmZmVyID0gYXdhaXQgemlwLnRvSW5NZW1vcnlaaXAodGVzdEZvbGRlciwge1xuICAgICAgICAgICAgZW5jb2RlVG9CYXNlNjQ6IHRydWUsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUocGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpLCBCdWZmZXIuZnJvbShidWZmZXIudG9TdHJpbmcoKSwgJ2Jhc2U2NCcpKTtcblxuICAgICAgICAgIC8vIFVuemlwIHRoZSBmaWxlIGFuZCB0ZXN0IHRoYXQgaXQgaGFzIHRoZSBzYW1lIGNvbnRlbnRzIGFzIHRoZSBkaXJlY3RvcnkgdGhhdCB3YXMgemlwcGVkXG4gICAgICAgICAgYXdhaXQgemlwLmV4dHJhY3RBbGxUbyhwYXRoLnJlc29sdmUodG1wUm9vdCwgJ3Rlc3QuemlwJyksIHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JykpO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiB1c2UgYSBiYWQgcGF0aCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBhd2FpdCB6aXAudG9Jbk1lbW9yeVppcChwYXRoLnJlc29sdmUoYXNzZXRzUGF0aCwgJ2JhZF9wYXRoJykpXG4gICAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbm8gc3VjaC9pKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiBtYXggc2l6ZSBpcyBleGNlZWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCB0ZXN0Rm9sZGVyID0gcGF0aC5yZXNvbHZlKGFzc2V0c1BhdGgsICd1bnppcHBlZCcpO1xuICAgICAgICAgIGF3YWl0IHppcC50b0luTWVtb3J5WmlwKHRlc3RGb2xkZXIsIHtcbiAgICAgICAgICAgIG1heFNpemU6IDEsXG4gICAgICAgICAgfSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvbXVzdCBub3QgYmUgZ3JlYXRlci8pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnX2V4dHJhY3RFbnRyeVRvKCknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBlbnRyeSwgbW9ja1ppcEZpbGUsIG1vY2taaXBTdHJlYW07XG4gICAgICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGVudHJ5ID0ge2ZpbGVOYW1lOiBwYXRoLnJlc29sdmUoYXdhaXQgdGVtcERpci5vcGVuRGlyKCksICd0ZW1wJywgJ2ZpbGUnKX07XG4gICAgICAgICAgbW9ja1ppcFN0cmVhbSA9IG5ldyBNb2NrUmVhZFdyaXRlU3RyZWFtKCk7XG4gICAgICAgICAgbW9ja1ppcEZpbGUgPSB7XG4gICAgICAgICAgICBvcGVuUmVhZFN0cmVhbTogKGVudHJ5LCBjYikgPT4gY2IobnVsbCwgbW9ja1ppcFN0cmVhbSksIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcHJvbWlzZS9wcmVmZXItYXdhaXQtdG8tY2FsbGJhY2tzXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaXQoJ3Nob3VsZCBiZSByZWplY3RlZCBpZiB6aXAgc3RyZWFtIGVtaXRzIGFuIGVycm9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIG1vY2taaXBTdHJlYW0ucGlwZSA9ICgpID0+IHtcbiAgICAgICAgICAgIG1vY2taaXBTdHJlYW0uZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ3ppcCBzdHJlYW0gZXJyb3InKSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB6aXAuX2V4dHJhY3RFbnRyeVRvKG1vY2taaXBGaWxlLCBlbnRyeSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnemlwIHN0cmVhbSBlcnJvcicpO1xuICAgICAgICB9KTtcblxuICAgICAgICBpdCgnc2hvdWxkIGJlIHJlamVjdGVkIGlmIHdyaXRlIHN0cmVhbSBlbWl0cyBhbiBlcnJvcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBtb2NrWmlwU3RyZWFtLnBpcGUgPSAod3JpdGVTdHJlYW0pID0+IHtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtLmVtaXQoJ2Vycm9yJywgbmV3IEVycm9yKCd3cml0ZSBzdHJlYW0gZXJyb3InKSk7XG4gICAgICAgICAgICBtb2NrWmlwU3RyZWFtLmVuZCgpO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW0uZW5kKCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBhd2FpdCB6aXAuX2V4dHJhY3RFbnRyeVRvKG1vY2taaXBGaWxlLCBlbnRyeSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnd3JpdGUgc3RyZWFtIGVycm9yJyk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd0b0FyY2hpdmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgemlwIGFsbCBmaWxlcyBpbnRvIGFuIGFyY2hpdmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgdGVzdEZvbGRlciA9IHBhdGgucmVzb2x2ZShhc3NldHNQYXRoLCAndW56aXBwZWQnKTtcbiAgICAgICAgICBjb25zdCBkc3RQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsICd0ZXN0LnppcCcpO1xuICAgICAgICAgIGF3YWl0IHppcC50b0FyY2hpdmUoZHN0UGF0aCwge1xuICAgICAgICAgICAgY3dkOiB0ZXN0Rm9sZGVyLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gVW56aXAgdGhlIGZpbGUgYW5kIHRlc3QgdGhhdCBpdCBoYXMgdGhlIHNhbWUgY29udGVudHMgYXMgdGhlIGRpcmVjdG9yeSB0aGF0IHdhcyB6aXBwZWRcbiAgICAgICAgICBhd2FpdCB6aXAuZXh0cmFjdEFsbFRvKGRzdFBhdGgsIHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JykpO1xuICAgICAgICAgIGF3YWl0IGZzLnJlYWRGaWxlKHBhdGgucmVzb2x2ZSh0bXBSb290LCAnb3V0cHV0JywgJ3Rlc3QtZGlyJywgJ2EudHh0JyksIHtcbiAgICAgICAgICAgIGVuY29kaW5nOiAndXRmOCdcbiAgICAgICAgICB9KS5zaG91bGQuZXZlbnR1YWxseS5lcXVhbCgnSGVsbG8gV29ybGQnKTtcbiAgICAgICAgICBhd2FpdCBmcy5yZWFkRmlsZShwYXRoLnJlc29sdmUodG1wUm9vdCwgJ291dHB1dCcsICd0ZXN0LWRpcicsICdiLnR4dCcpLCB7XG4gICAgICAgICAgICBlbmNvZGluZzogJ3V0ZjgnXG4gICAgICAgICAgfSkuc2hvdWxkLmV2ZW50dWFsbHkuZXF1YWwoJ0ZvbyBCYXInKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuXG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd1bmljb2RlIGZpbGVuYW1lIGhhbmRsaW5nJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCB6aXBwZWRGaWxlUGF0aCwgYXNzZXRzUGF0aCwgdG1wUm9vdDtcblxuICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXRzUGF0aCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuICAgICAgdG1wUm9vdCA9IGF3YWl0IHRlbXBEaXIub3BlbkRpcigpO1xuXG4gICAgICBjb25zdCB6aXBwZWRCYXNlNjQgPSAnVUVzREJCUUFDQUFJQUJGOC9FWUFBQUFBQUFBQUFCb0FBQUFUQUNBQWEyRnVhbWt0NXEyajVMaVc1TGlWTG1Gd2NGVlVEUUFIQWdPNFZWcFgrR0JaVi9oZ2RYZ0xBQUVFOVFFQUFBUVVBQUFBSzhuSUxGWUFvcno4RW9XaTFNU2NuRXFGeER5RnhJSUNMZ0JRU3djSVI5M2pQaG9BQUFBYUFBQUFVRXNCQWhRREZBQUlBQWdBRVh6OFJrZmQ0ejRhQUFBQUdnQUFBQk1BSUFBQUFBQUFBQUFBQUtTQkFBQUFBR3RoYm1wcExlYXRvK1M0bHVTNGxTNWhjSEJWVkEwQUJ3SUR1RlZhVi9oZ1dWZjRZSFY0Q3dBQkJQVUJBQUFFRkFBQUFGQkxCUVlBQUFBQUFRQUJBR0VBQUFCN0FBQUFBQUE9JztcbiAgICAgIHppcHBlZEZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsICd6aXBwZWQuemlwJyk7XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUoemlwcGVkRmlsZVBhdGgsIHppcHBlZEJhc2U2NCwgJ2Jhc2U2NCcpO1xuICAgICAgYXdhaXQgemlwLmV4dHJhY3RBbGxUbyh6aXBwZWRGaWxlUGF0aCwgYXNzZXRzUGF0aCwge3VzZVN5c3RlbVVuemlwOiB0cnVlfSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgZm9yIChjb25zdCB0bXBQYXRoIG9mIFthc3NldHNQYXRoLCB0bXBSb290XSkge1xuICAgICAgICBpZiAoIWF3YWl0IGZzLmV4aXN0cyh0bXBQYXRoKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGZzLnJpbXJhZih0bXBQYXRoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0YWluIHRoZSBwcm9wZXIgZmlsZW5hbWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXhwZWN0ZWRQYXRoID0gcGF0aC5qb2luKGFzc2V0c1BhdGgsICdrYW5qaS3mraPkuJbkuJUuYXBwJyk7XG4gICAgICAvLyB3ZSBjYW5ub3QgdXNlIHRoZSBgc2hvdWxkYCBzeW50YXggYmVjYXVzZSBgZnMuZXhpc3RzYCByZXNvbHZlcyB0byBhIHByaW1pdGl2ZSAoYm9vbGVhbilcbiAgICAgIGlmICghYXdhaXQgZnMuZXhpc3RzKGV4cGVjdGVkUGF0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IGNoYWkuQXNzZXJ0aW9uRXJyb3IoYEV4cGVjdGVkICR7ZXhwZWN0ZWRQYXRofSB0byBleGlzdCwgYnV0IGl0IGRvZXMgbm90YCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXSwiZmlsZSI6InRlc3QvemlwLWUyZS1zcGVjcy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLiJ9