appium 2.0.0-beta.24 → 2.0.0-beta.27

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 (124) hide show
  1. package/build/lib/appium-config.schema.json +278 -0
  2. package/build/lib/appium.js +45 -66
  3. package/build/lib/cli/args.js +19 -39
  4. package/build/lib/cli/driver-command.js +5 -9
  5. package/build/lib/cli/extension-command.js +73 -64
  6. package/build/lib/cli/extension.js +10 -23
  7. package/build/lib/cli/parser.js +9 -19
  8. package/build/lib/cli/plugin-command.js +5 -9
  9. package/build/lib/cli/utils.js +2 -4
  10. package/build/lib/config-file.js +5 -10
  11. package/build/lib/config.js +50 -20
  12. package/build/lib/constants.js +60 -0
  13. package/build/lib/extension/driver-config.js +190 -0
  14. package/build/lib/extension/extension-config.js +297 -0
  15. package/build/lib/extension/index.js +77 -0
  16. package/build/lib/extension/manifest.js +246 -0
  17. package/build/lib/extension/package-changed.js +68 -0
  18. package/build/lib/extension/plugin-config.js +87 -0
  19. package/build/lib/grid-register.js +2 -4
  20. package/build/lib/logger.js +2 -4
  21. package/build/lib/logsink.js +2 -4
  22. package/build/lib/main.js +42 -71
  23. package/build/lib/schema/appium-config-schema.js +2 -4
  24. package/build/lib/schema/arg-spec.js +11 -14
  25. package/build/lib/schema/cli-args.js +2 -4
  26. package/build/lib/schema/cli-transformers.js +2 -4
  27. package/build/lib/schema/index.js +2 -4
  28. package/build/lib/schema/keywords.js +2 -4
  29. package/build/lib/schema/schema.js +61 -37
  30. package/build/lib/utils.js +1 -32
  31. package/lib/appium.js +50 -68
  32. package/lib/cli/args.js +19 -23
  33. package/lib/cli/driver-command.js +10 -2
  34. package/lib/cli/extension-command.js +216 -135
  35. package/lib/cli/extension.js +7 -15
  36. package/lib/cli/parser.js +6 -14
  37. package/lib/cli/plugin-command.js +1 -2
  38. package/lib/config-file.js +12 -15
  39. package/lib/config.js +55 -24
  40. package/lib/constants.js +79 -0
  41. package/lib/extension/driver-config.js +230 -0
  42. package/lib/extension/extension-config.js +459 -0
  43. package/lib/extension/index.js +103 -0
  44. package/lib/extension/manifest.js +590 -0
  45. package/lib/extension/package-changed.js +64 -0
  46. package/lib/extension/plugin-config.js +111 -0
  47. package/lib/grid-register.js +4 -4
  48. package/lib/main.js +57 -93
  49. package/lib/schema/arg-spec.js +3 -3
  50. package/lib/schema/cli-args.js +1 -0
  51. package/lib/schema/keywords.js +1 -1
  52. package/lib/schema/schema.js +67 -29
  53. package/lib/utils.js +2 -32
  54. package/package.json +29 -21
  55. package/{postinstall.js → scripts/postinstall.js} +1 -1
  56. package/types/types.d.ts +70 -31
  57. package/bin/ios-webkit-debug-proxy-launcher.js +0 -71
  58. package/build/check-npm-pack-files.js +0 -23
  59. package/build/commands-yml/parse.js +0 -319
  60. package/build/commands-yml/validator.js +0 -130
  61. package/build/index.js +0 -19
  62. package/build/lib/cli/npm.js +0 -220
  63. package/build/lib/driver-config.js +0 -100
  64. package/build/lib/drivers.js +0 -100
  65. package/build/lib/ext-config-io.js +0 -165
  66. package/build/lib/extension-config.js +0 -320
  67. package/build/lib/plugin-config.js +0 -69
  68. package/build/lib/plugins.js +0 -18
  69. package/build/postinstall.js +0 -90
  70. package/build/test/cli/cli-e2e-specs.js +0 -221
  71. package/build/test/cli/cli-helpers.js +0 -86
  72. package/build/test/cli/cli-specs.js +0 -71
  73. package/build/test/cli/fixtures/test-driver/package.json +0 -27
  74. package/build/test/cli/schema-args-specs.js +0 -48
  75. package/build/test/cli/schema-e2e-specs.js +0 -47
  76. package/build/test/config-e2e-specs.js +0 -112
  77. package/build/test/config-file-e2e-specs.js +0 -209
  78. package/build/test/config-file-specs.js +0 -281
  79. package/build/test/config-specs.js +0 -246
  80. package/build/test/driver-e2e-specs.js +0 -435
  81. package/build/test/driver-specs.js +0 -386
  82. package/build/test/ext-config-io-specs.js +0 -181
  83. package/build/test/extension-config-specs.js +0 -365
  84. package/build/test/fixtures/allow-feat.txt +0 -5
  85. package/build/test/fixtures/caps.json +0 -3
  86. package/build/test/fixtures/config/allow-insecure.txt +0 -3
  87. package/build/test/fixtures/config/appium.config.bad-nodeconfig.json +0 -5
  88. package/build/test/fixtures/config/appium.config.bad.json +0 -32
  89. package/build/test/fixtures/config/appium.config.ext-good.json +0 -9
  90. package/build/test/fixtures/config/appium.config.ext-unknown-props.json +0 -10
  91. package/build/test/fixtures/config/appium.config.good.js +0 -40
  92. package/build/test/fixtures/config/appium.config.good.json +0 -33
  93. package/build/test/fixtures/config/appium.config.good.yaml +0 -30
  94. package/build/test/fixtures/config/appium.config.invalid.json +0 -31
  95. package/build/test/fixtures/config/appium.config.security-array.json +0 -5
  96. package/build/test/fixtures/config/appium.config.security-delimited.json +0 -5
  97. package/build/test/fixtures/config/appium.config.security-path.json +0 -5
  98. package/build/test/fixtures/config/driver-fake.config.json +0 -8
  99. package/build/test/fixtures/config/nodeconfig.json +0 -3
  100. package/build/test/fixtures/config/plugin-fake.config.json +0 -0
  101. package/build/test/fixtures/default-args.js +0 -35
  102. package/build/test/fixtures/deny-feat.txt +0 -5
  103. package/build/test/fixtures/driver.schema.js +0 -20
  104. package/build/test/fixtures/extensions.yaml +0 -27
  105. package/build/test/fixtures/flattened-schema.js +0 -532
  106. package/build/test/fixtures/plugin.schema.js +0 -20
  107. package/build/test/fixtures/schema-with-extensions.js +0 -28
  108. package/build/test/grid-register-specs.js +0 -74
  109. package/build/test/helpers.js +0 -75
  110. package/build/test/logger-specs.js +0 -76
  111. package/build/test/npm-specs.js +0 -20
  112. package/build/test/parser-specs.js +0 -319
  113. package/build/test/plugin-e2e-specs.js +0 -316
  114. package/build/test/schema/arg-spec-specs.js +0 -70
  115. package/build/test/schema/cli-args-specs.js +0 -408
  116. package/build/test/schema/schema-specs.js +0 -407
  117. package/build/test/utils-specs.js +0 -288
  118. package/lib/cli/npm.js +0 -251
  119. package/lib/driver-config.js +0 -101
  120. package/lib/drivers.js +0 -84
  121. package/lib/ext-config-io.js +0 -287
  122. package/lib/extension-config.js +0 -366
  123. package/lib/plugin-config.js +0 -63
  124. package/lib/plugins.js +0 -13
@@ -1,386 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- require("source-map-support/register");
6
-
7
- var _baseDriver = require("@appium/base-driver");
8
-
9
- var _fakeDriver = require("@appium/fake-driver");
10
-
11
- var _asyncbox = require("asyncbox");
12
-
13
- var _lodash = _interopRequireDefault(require("lodash"));
14
-
15
- var _sinon = _interopRequireDefault(require("sinon"));
16
-
17
- var _appium = require("../lib/appium");
18
-
19
- var _schema = require("../lib/schema/schema");
20
-
21
- var _utils = require("../lib/utils");
22
-
23
- var _helpers = require("./helpers");
24
-
25
- const SESSION_ID = 1;
26
- describe('AppiumDriver', function () {
27
- beforeEach(function () {
28
- (0, _schema.resetSchema)();
29
- (0, _schema.finalizeSchema)();
30
- });
31
- describe('instance method', function () {
32
- function getDriverAndFakeDriver(appiumArgs = {}, DriverClass = _fakeDriver.FakeDriver) {
33
- const appium = new _appium.AppiumDriver(appiumArgs);
34
- const fakeDriver = new DriverClass();
35
-
36
- const mockFakeDriver = _sinon.default.mock(fakeDriver);
37
-
38
- mockFakeDriver._fakeDriver = fakeDriver;
39
-
40
- const mockedDriverReturnerClass = function Driver() {
41
- return fakeDriver;
42
- };
43
-
44
- appium._findMatchingDriver = function () {
45
- return {
46
- driver: mockedDriverReturnerClass,
47
- version: '1.2.3',
48
- driverName: 'fake'
49
- };
50
- };
51
-
52
- return [appium, mockFakeDriver];
53
- }
54
-
55
- describe('createSession', function () {
56
- let appium;
57
- let mockFakeDriver;
58
- beforeEach(function () {
59
- [appium, mockFakeDriver] = getDriverAndFakeDriver();
60
- });
61
- afterEach(async function () {
62
- mockFakeDriver.restore();
63
- await appium.deleteSession(SESSION_ID);
64
- });
65
- it(`should call inner driver's createSession with desired capabilities`, async function () {
66
- mockFakeDriver.expects('createSession').once().withExactArgs(null, null, _helpers.W3C_CAPS, []).returns([SESSION_ID, (0, _utils.removeAppiumPrefixes)(_helpers.W3C_PREFIXED_CAPS)]);
67
- await appium.createSession(null, null, _helpers.W3C_CAPS);
68
- mockFakeDriver.verify();
69
- });
70
- it(`should call inner driver's createSession with desired and default capabilities`, async function () {
71
- let defaultCaps = {
72
- 'appium:someCap': 'hello'
73
- };
74
- let allCaps = { ..._helpers.W3C_CAPS,
75
- alwaysMatch: { ..._helpers.W3C_CAPS.alwaysMatch,
76
- ...defaultCaps
77
- }
78
- };
79
- appium.args.defaultCapabilities = defaultCaps;
80
- mockFakeDriver.expects('createSession').once().withArgs(null, null, allCaps).returns([SESSION_ID, (0, _utils.removeAppiumPrefixes)(allCaps.alwaysMatch)]);
81
- await appium.createSession(null, null, _helpers.W3C_CAPS);
82
- mockFakeDriver.verify();
83
- });
84
- it(`should call inner driver's createSession with desired and default capabilities without overriding caps`, async function () {
85
- let defaultCaps = {
86
- platformName: 'Ersatz'
87
- };
88
- appium.args.defaultCapabilities = defaultCaps;
89
- mockFakeDriver.expects('createSession').once().withArgs(null, null, _helpers.W3C_CAPS).returns([SESSION_ID, (0, _utils.removeAppiumPrefixes)(_helpers.W3C_PREFIXED_CAPS)]);
90
- await appium.createSession(null, null, _helpers.W3C_CAPS);
91
- mockFakeDriver.verify();
92
- });
93
- it('should kill all other sessions if sessionOverride is on', async function () {
94
- appium.args.sessionOverride = true;
95
- let fakeDrivers = [new _fakeDriver.FakeDriver(), new _fakeDriver.FakeDriver(), new _fakeDriver.FakeDriver()];
96
-
97
- let mockFakeDrivers = _lodash.default.map(fakeDrivers, fd => _sinon.default.mock(fd));
98
-
99
- mockFakeDrivers[0].expects('deleteSession').once();
100
- mockFakeDrivers[1].expects('deleteSession').once().throws('Cannot shut down Android driver; it has already shut down');
101
- mockFakeDrivers[2].expects('deleteSession').once();
102
- appium.sessions['abc-123-xyz'] = fakeDrivers[0];
103
- appium.sessions['xyz-321-abc'] = fakeDrivers[1];
104
- appium.sessions['123-abc-xyz'] = fakeDrivers[2];
105
- let sessions = await appium.getSessions();
106
- sessions.should.have.length(3);
107
- mockFakeDriver.expects('createSession').once().withExactArgs(null, null, _helpers.W3C_CAPS, []).returns([SESSION_ID, (0, _utils.removeAppiumPrefixes)(_helpers.W3C_PREFIXED_CAPS)]);
108
- await appium.createSession(null, null, _helpers.W3C_CAPS);
109
- sessions = await appium.getSessions();
110
- sessions.should.have.length(1);
111
-
112
- for (let mfd of mockFakeDrivers) {
113
- mfd.verify();
114
- }
115
-
116
- mockFakeDriver.verify();
117
- });
118
- it('should call "createSession" with W3C capabilities argument, if provided', async function () {
119
- mockFakeDriver.expects('createSession').once().withArgs(null, undefined, _helpers.W3C_CAPS).returns([SESSION_ID, _helpers.BASE_CAPS]);
120
- await appium.createSession(undefined, undefined, _helpers.W3C_CAPS);
121
- mockFakeDriver.verify();
122
- });
123
- it('should call "createSession" with W3C capabilities argument with additional provided parameters', async function () {
124
- let w3cCaps = { ..._helpers.W3C_CAPS,
125
- alwaysMatch: { ..._helpers.W3C_CAPS.alwaysMatch,
126
- 'appium:someOtherParm': 'someOtherParm'
127
- }
128
- };
129
- mockFakeDriver.expects('createSession').once().withArgs(null, undefined, {
130
- alwaysMatch: { ...w3cCaps.alwaysMatch,
131
- 'appium:someOtherParm': 'someOtherParm'
132
- },
133
- firstMatch: [{}]
134
- }).returns([SESSION_ID, (0, _utils.insertAppiumPrefixes)(_helpers.BASE_CAPS)]);
135
- await appium.createSession(undefined, undefined, w3cCaps);
136
- mockFakeDriver.verify();
137
- });
138
- it('should not call "createSession" with JSONWP capabilities if W3C has incomplete capabilities', async function () {
139
- const w3cCaps = { ..._helpers.W3C_CAPS,
140
- alwaysMatch: {
141
- 'appium:someOtherParm': 'someOtherParm'
142
- }
143
- };
144
- const jsonwpCaps = { ..._helpers.BASE_CAPS,
145
- automationName: 'Fake',
146
- someOtherParam: 'someOtherParam'
147
- };
148
- mockFakeDriver.expects('createSession').never();
149
- await appium.createSession(jsonwpCaps, undefined, w3cCaps);
150
- mockFakeDriver.verify();
151
- });
152
- it('should assign args to property `cliArgs`', async function () {
153
- class ArgsDriver extends _baseDriver.BaseDriver {}
154
-
155
- const args = {
156
- driver: {
157
- fake: {
158
- randomArg: 1234
159
- }
160
- }
161
- };
162
- [appium, mockFakeDriver] = getDriverAndFakeDriver(args, ArgsDriver);
163
- const {
164
- value
165
- } = await appium.createSession(undefined, undefined, _helpers.W3C_CAPS);
166
-
167
- try {
168
- mockFakeDriver._fakeDriver.cliArgs.should.eql({
169
- randomArg: 1234
170
- });
171
- } finally {
172
- await appium.deleteSession(value[0]);
173
- }
174
- });
175
- });
176
- describe('deleteSession', function () {
177
- let appium;
178
- let mockFakeDriver;
179
- beforeEach(function () {
180
- [appium, mockFakeDriver] = getDriverAndFakeDriver();
181
- });
182
- afterEach(function () {
183
- mockFakeDriver.restore();
184
- });
185
- it('should remove the session if it is found', async function () {
186
- let [sessionId] = (await appium.createSession(null, null, _helpers.W3C_CAPS)).value;
187
- let sessions = await appium.getSessions();
188
- sessions.should.have.length(1);
189
- await appium.deleteSession(sessionId);
190
- sessions = await appium.getSessions();
191
- sessions.should.have.length(0);
192
- });
193
- it('should call inner driver\'s deleteSession method', async function () {
194
- const [sessionId] = (await appium.createSession(null, null, _helpers.W3C_CAPS)).value;
195
- mockFakeDriver.expects('deleteSession').once().withExactArgs(sessionId, []).returns();
196
- await appium.deleteSession(sessionId);
197
- mockFakeDriver.verify();
198
- await mockFakeDriver.object.deleteSession();
199
- });
200
- });
201
- describe('getSessions', function () {
202
- let appium, mockFakeDriver;
203
- let sessions;
204
- before(function () {
205
- [appium, mockFakeDriver] = getDriverAndFakeDriver();
206
- });
207
- afterEach(async function () {
208
- for (let session of sessions) {
209
- await appium.deleteSession(session.id);
210
- }
211
-
212
- mockFakeDriver.restore();
213
- });
214
- it('should return an empty array of sessions', async function () {
215
- sessions = await appium.getSessions();
216
- sessions.should.be.an('array');
217
- sessions.should.be.empty;
218
- });
219
- it('should return sessions created', async function () {
220
- let caps1 = {
221
- alwaysMatch: { ..._helpers.W3C_PREFIXED_CAPS,
222
- 'appium:cap': 'value'
223
- }
224
- };
225
- let caps2 = {
226
- alwaysMatch: { ..._helpers.W3C_PREFIXED_CAPS,
227
- 'appium:cap': 'other value'
228
- }
229
- };
230
- mockFakeDriver.expects('createSession').once().returns(['fake-session-id-1', (0, _utils.removeAppiumPrefixes)(caps1.alwaysMatch)]);
231
- let [session1Id, session1Caps] = (await appium.createSession(null, null, caps1)).value;
232
- mockFakeDriver.expects('createSession').once().returns(['fake-session-id-2', (0, _utils.removeAppiumPrefixes)(caps2.alwaysMatch)]);
233
- let [session2Id, session2Caps] = (await appium.createSession(null, null, caps2)).value;
234
- sessions = await appium.getSessions();
235
- sessions.should.be.an('array');
236
- sessions.should.have.length(2);
237
- sessions[0].id.should.equal(session1Id);
238
- (0, _utils.removeAppiumPrefixes)(caps1.alwaysMatch).should.eql(session1Caps);
239
- sessions[1].id.should.equal(session2Id);
240
- (0, _utils.removeAppiumPrefixes)(caps2.alwaysMatch).should.eql(session2Caps);
241
- });
242
- });
243
- describe('getStatus', function () {
244
- let appium;
245
- before(function () {
246
- appium = new _appium.AppiumDriver({});
247
- });
248
- it('should return a status', async function () {
249
- let status = await appium.getStatus();
250
- status.build.should.exist;
251
- status.build.version.should.exist;
252
- });
253
- });
254
- describe('sessionExists', function () {});
255
- describe('attachUnexpectedShutdownHandler', function () {
256
- let appium;
257
- let mockFakeDriver;
258
- beforeEach(function () {
259
- [appium, mockFakeDriver] = getDriverAndFakeDriver();
260
- });
261
- afterEach(async function () {
262
- await mockFakeDriver.object.deleteSession();
263
- mockFakeDriver.restore();
264
- appium.args.defaultCapabilities = {};
265
- });
266
- it('should remove session if inner driver unexpectedly exits with an error', async function () {
267
- let [sessionId] = (await appium.createSession(null, null, _lodash.default.clone(_helpers.W3C_CAPS))).value;
268
-
269
- _lodash.default.keys(appium.sessions).should.contain(sessionId);
270
-
271
- appium.sessions[sessionId].eventEmitter.emit('onUnexpectedShutdown', new Error('Oops'));
272
- await (0, _asyncbox.sleep)(1);
273
-
274
- _lodash.default.keys(appium.sessions).should.not.contain(sessionId);
275
- });
276
- it('should remove session if inner driver unexpectedly exits with no error', async function () {
277
- let [sessionId] = (await appium.createSession(null, null, _lodash.default.clone(_helpers.W3C_CAPS))).value;
278
-
279
- _lodash.default.keys(appium.sessions).should.contain(sessionId);
280
-
281
- appium.sessions[sessionId].eventEmitter.emit('onUnexpectedShutdown');
282
- await (0, _asyncbox.sleep)(1);
283
-
284
- _lodash.default.keys(appium.sessions).should.not.contain(sessionId);
285
- });
286
- });
287
- describe('createPluginInstances', function () {
288
- class NoArgsPlugin {}
289
-
290
- NoArgsPlugin.pluginName = 'noargs';
291
-
292
- class ArgsPlugin {}
293
-
294
- ArgsPlugin.pluginName = 'args';
295
-
296
- class ArrayArgPlugin {}
297
-
298
- ArrayArgPlugin.pluginName = 'arrayarg';
299
- beforeEach(function () {
300
- (0, _schema.resetSchema)();
301
- (0, _schema.registerSchema)('plugin', ArgsPlugin.pluginName, {
302
- type: 'object',
303
- properties: {
304
- randomArg: {
305
- type: 'number',
306
- default: 2000
307
- }
308
- }
309
- });
310
- (0, _schema.registerSchema)('plugin', ArrayArgPlugin.pluginName, {
311
- type: 'object',
312
- properties: {
313
- arr: {
314
- type: 'array',
315
- default: []
316
- }
317
- }
318
- });
319
- (0, _schema.finalizeSchema)();
320
- });
321
- describe('when args are not present', function () {
322
- it('should not set CLI args', function () {
323
- const appium = new _appium.AppiumDriver({});
324
- appium.pluginClasses = [NoArgsPlugin, ArgsPlugin];
325
-
326
- for (const plugin of appium.createPluginInstances()) {
327
- should.not.exist(plugin.cliArgs);
328
- }
329
- });
330
- });
331
- describe('when args are equal to the schema defaults', function () {
332
- it('should not set CLI args', function () {
333
- const appium = new _appium.AppiumDriver({
334
- plugin: {
335
- [ArgsPlugin.pluginName]: {
336
- randomArg: 2000
337
- }
338
- }
339
- });
340
- appium.pluginClasses = [NoArgsPlugin, ArgsPlugin];
341
-
342
- for (const plugin of appium.createPluginInstances()) {
343
- should.not.exist(plugin.cliArgs);
344
- }
345
- });
346
- describe('when the default is an "object"', function () {
347
- it('should not set CLI args', function () {
348
- const appium = new _appium.AppiumDriver({
349
- plugin: {
350
- [ArrayArgPlugin.pluginName]: {
351
- arr: []
352
- }
353
- }
354
- });
355
- appium.pluginClasses = [NoArgsPlugin, ArgsPlugin, ArrayArgPlugin];
356
-
357
- for (const plugin of appium.createPluginInstances()) {
358
- should.not.exist(plugin.cliArgs);
359
- }
360
- });
361
- });
362
- });
363
- describe('when args are not equal to the schema defaults', function () {
364
- it('should add cliArgs to the plugin', function () {
365
- const appium = new _appium.AppiumDriver({
366
- plugin: {
367
- args: {
368
- randomArg: 1234
369
- }
370
- }
371
- });
372
- appium.pluginClasses = [ArgsPlugin];
373
-
374
- const plugin = _lodash.default.first(appium.createPluginInstances());
375
-
376
- plugin.cliArgs.should.eql({
377
- randomArg: 1234
378
- });
379
- });
380
- });
381
- });
382
- });
383
- });require('source-map-support').install();
384
-
385
-
386
- //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvZHJpdmVyLXNwZWNzLmpzIl0sIm5hbWVzIjpbIlNFU1NJT05fSUQiLCJkZXNjcmliZSIsImJlZm9yZUVhY2giLCJnZXREcml2ZXJBbmRGYWtlRHJpdmVyIiwiYXBwaXVtQXJncyIsIkRyaXZlckNsYXNzIiwiRmFrZURyaXZlciIsImFwcGl1bSIsIkFwcGl1bURyaXZlciIsImZha2VEcml2ZXIiLCJtb2NrRmFrZURyaXZlciIsInNpbm9uIiwibW9jayIsIl9mYWtlRHJpdmVyIiwibW9ja2VkRHJpdmVyUmV0dXJuZXJDbGFzcyIsIkRyaXZlciIsIl9maW5kTWF0Y2hpbmdEcml2ZXIiLCJkcml2ZXIiLCJ2ZXJzaW9uIiwiZHJpdmVyTmFtZSIsImFmdGVyRWFjaCIsInJlc3RvcmUiLCJkZWxldGVTZXNzaW9uIiwiaXQiLCJleHBlY3RzIiwib25jZSIsIndpdGhFeGFjdEFyZ3MiLCJXM0NfQ0FQUyIsInJldHVybnMiLCJXM0NfUFJFRklYRURfQ0FQUyIsImNyZWF0ZVNlc3Npb24iLCJ2ZXJpZnkiLCJkZWZhdWx0Q2FwcyIsImFsbENhcHMiLCJhbHdheXNNYXRjaCIsImFyZ3MiLCJkZWZhdWx0Q2FwYWJpbGl0aWVzIiwid2l0aEFyZ3MiLCJwbGF0Zm9ybU5hbWUiLCJzZXNzaW9uT3ZlcnJpZGUiLCJmYWtlRHJpdmVycyIsIm1vY2tGYWtlRHJpdmVycyIsIl8iLCJtYXAiLCJmZCIsInRocm93cyIsInNlc3Npb25zIiwiZ2V0U2Vzc2lvbnMiLCJzaG91bGQiLCJoYXZlIiwibGVuZ3RoIiwibWZkIiwidW5kZWZpbmVkIiwiQkFTRV9DQVBTIiwidzNjQ2FwcyIsImZpcnN0TWF0Y2giLCJqc29ud3BDYXBzIiwiYXV0b21hdGlvbk5hbWUiLCJzb21lT3RoZXJQYXJhbSIsIm5ldmVyIiwiQXJnc0RyaXZlciIsIkJhc2VEcml2ZXIiLCJmYWtlIiwicmFuZG9tQXJnIiwidmFsdWUiLCJjbGlBcmdzIiwiZXFsIiwic2Vzc2lvbklkIiwib2JqZWN0IiwiYmVmb3JlIiwic2Vzc2lvbiIsImlkIiwiYmUiLCJhbiIsImVtcHR5IiwiY2FwczEiLCJjYXBzMiIsInNlc3Npb24xSWQiLCJzZXNzaW9uMUNhcHMiLCJzZXNzaW9uMklkIiwic2Vzc2lvbjJDYXBzIiwiZXF1YWwiLCJzdGF0dXMiLCJnZXRTdGF0dXMiLCJidWlsZCIsImV4aXN0IiwiY2xvbmUiLCJrZXlzIiwiY29udGFpbiIsImV2ZW50RW1pdHRlciIsImVtaXQiLCJFcnJvciIsIm5vdCIsIk5vQXJnc1BsdWdpbiIsInBsdWdpbk5hbWUiLCJBcmdzUGx1Z2luIiwiQXJyYXlBcmdQbHVnaW4iLCJ0eXBlIiwicHJvcGVydGllcyIsImRlZmF1bHQiLCJhcnIiLCJwbHVnaW5DbGFzc2VzIiwicGx1Z2luIiwiY3JlYXRlUGx1Z2luSW5zdGFuY2VzIiwiZmlyc3QiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBLE1BQU1BLFVBQVUsR0FBRyxDQUFuQjtBQUVBQyxRQUFRLENBQUMsY0FBRCxFQUFpQixZQUFZO0FBQ25DQyxFQUFBQSxVQUFVLENBQUMsWUFBWTtBQUNyQjtBQUNBO0FBQ0QsR0FIUyxDQUFWO0FBSUFELEVBQUFBLFFBQVEsQ0FBQyxpQkFBRCxFQUFvQixZQUFZO0FBQ3RDLGFBQVNFLHNCQUFULENBQWlDQyxVQUFVLEdBQUcsRUFBOUMsRUFBa0RDLFdBQVcsR0FBR0Msc0JBQWhFLEVBQTRFO0FBQzFFLFlBQU1DLE1BQU0sR0FBRyxJQUFJQyxvQkFBSixDQUFpQkosVUFBakIsQ0FBZjtBQUNBLFlBQU1LLFVBQVUsR0FBRyxJQUFJSixXQUFKLEVBQW5COztBQUNBLFlBQU1LLGNBQWMsR0FBR0MsZUFBTUMsSUFBTixDQUFXSCxVQUFYLENBQXZCOztBQUNBQyxNQUFBQSxjQUFjLENBQUNHLFdBQWYsR0FBNkJKLFVBQTdCOztBQUNBLFlBQU1LLHlCQUF5QixHQUFHLFNBQVNDLE1BQVQsR0FBbUI7QUFDbkQsZUFBT04sVUFBUDtB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RjtBQU9ELFNBUk8sQ0FBUjtBQVNELE9BbEJPLENBQVI7QUFvQkFoRSxNQUFBQSxRQUFRLENBQUMsZ0RBQUQsRUFBbUQsWUFBWTtBQUNyRXNCLFFBQUFBLEVBQUUsQ0FBQyxrQ0FBRCxFQUFxQyxZQUFZO0FBQ2pELGdCQUFNaEIsTUFBTSxHQUFHLElBQUlDLG9CQUFKLENBQWlCO0FBQUM4RixZQUFBQSxNQUFNLEVBQUU7QUFBQ25FLGNBQUFBLElBQUksRUFBRTtBQUFDNEIsZ0JBQUFBLFNBQVMsRUFBRTtBQUFaO0FBQVA7QUFBVCxXQUFqQixDQUFmO0FBQ0F4RCxVQUFBQSxNQUFNLENBQUM4RixhQUFQLEdBQXVCLENBQUNOLFVBQUQsQ0FBdkI7O0FBQ0EsZ0JBQU1PLE1BQU0sR0FBRzVELGdCQUFFOEQsS0FBRixDQUFRakcsTUFBTSxDQUFDZ0cscUJBQVAsRUFBUixDQUFmOztBQUNBRCxVQUFBQSxNQUFNLENBQUNyQyxPQUFQLENBQWVqQixNQUFmLENBQXNCa0IsR0FBdEIsQ0FBMEI7QUFBQ0gsWUFBQUEsU0FBUyxFQUFFO0FBQVosV0FBMUI7QUFDRCxTQUxDLENBQUY7QUFNRCxPQVBPLENBQVI7QUFRRCxLQTFFTyxDQUFSO0FBMkVELEdBalZPLENBQVI7QUFrVkQsQ0F2Vk8sQ0FBUiIsInNvdXJjZXNDb250ZW50IjpbIi8vIHRyYW5zcGlsZTptb2NoYVxuXG5pbXBvcnQgeyBCYXNlRHJpdmVyIH0gZnJvbSAnQGFwcGl1bS9iYXNlLWRyaXZlcic7XG5pbXBvcnQgeyBGYWtlRHJpdmVyIH0gZnJvbSAnQGFwcGl1bS9mYWtlLWRyaXZlcic7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJ2FzeW5jYm94JztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgQXBwaXVtRHJpdmVyIH0gZnJvbSAnLi4vbGliL2FwcGl1bSc7XG5pbXBvcnQgeyBmaW5hbGl6ZVNjaGVtYSwgcmVnaXN0ZXJTY2hlbWEsIHJlc2V0U2NoZW1hIH0gZnJvbSAnLi4vbGliL3NjaGVtYS9zY2hlbWEnO1xuaW1wb3J0IHsgaW5zZXJ0QXBwaXVtUHJlZml4ZXMsIHJlbW92ZUFwcGl1bVByZWZpeGVzIH0gZnJvbSAnLi4vbGliL3V0aWxzJztcbmltcG9ydCB7IEJBU0VfQ0FQUywgVzNDX0NBUFMsIFczQ19QUkVGSVhFRF9DQVBTIH0gZnJvbSAnLi9oZWxwZXJzJztcblxuXG5jb25zdCBTRVNTSU9OX0lEID0gMTtcblxuZGVzY3JpYmUoJ0FwcGl1bURyaXZlcicsIGZ1bmN0aW9uICgpIHtcbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgcmVzZXRTY2hlbWEoKTtcbiAgICBmaW5hbGl6ZVNjaGVtYSgpO1xuICB9KTtcbiAgZGVzY3JpYmUoJ2luc3RhbmNlIG1ldGhvZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBnZXREcml2ZXJBbmRGYWtlRHJpdmVyIChhcHBpdW1BcmdzID0ge30sIERyaXZlckNsYXNzID0gRmFrZURyaXZlcikge1xuICAgICAgY29uc3QgYXBwaXVtID0gbmV3IEFwcGl1bURyaXZlcihhcHBpdW1BcmdzKTtcbiAgICAgIGNvbnN0IGZha2VEcml2ZXIgPSBuZXcgRHJpdmVyQ2xhc3MoKTtcbiAgICAgIGNvbnN0IG1vY2tGYWtlRHJpdmVyID0gc2lub24ubW9jayhmYWtlRHJpdmVyKTtcbiAgICAgIG1vY2tGYWtlRHJpdmVyLl9mYWtlRHJpdmVyID0gZmFrZURyaXZlcjtcbiAgICAgIGNvbnN0IG1vY2tlZERyaXZlclJldHVybmVyQ2xhc3MgPSBmdW5jdGlvbiBEcml2ZXIgKCkge1xuICAgICAgICByZXR1cm4gZmFrZURyaXZlcjtcbiAgICAgIH07XG5cbiAgICAgIGFwcGl1bS5fZmluZE1hdGNoaW5nRHJpdmVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGRyaXZlcjogbW9ja2VkRHJpdmVyUmV0dXJuZXJDbGFzcyxcbiAgICAgICAgICB2ZXJzaW9uOiAnMS4yLjMnLFxuICAgICAgICAgIGRyaXZlck5hbWU6ICdmYWtlJyxcbiAgICAgICAgfTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gW2FwcGl1bSwgbW9ja0Zha2VEcml2ZXJdO1xuICAgIH1cbiAgICBkZXNjcmliZSgnY3JlYXRlU2Vzc2lvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBhcHBpdW07XG4gICAgICBsZXQgbW9ja0Zha2VEcml2ZXI7XG4gICAgICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgW2FwcGl1bSwgbW9ja0Zha2VEcml2ZXJdID0gZ2V0RHJpdmVyQW5kRmFrZURyaXZlcigpO1xuICAgICAgfSk7XG4gICAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBtb2NrRmFrZURyaXZlci5yZXN0b3JlKCk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5kZWxldGVTZXNzaW9uKFNFU1NJT05fSUQpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KGBzaG91bGQgY2FsbCBpbm5lciBkcml2ZXIncyBjcmVhdGVTZXNzaW9uIHdpdGggZGVzaXJlZCBjYXBhYmlsaXRpZXNgLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhudWxsLCBudWxsLCBXM0NfQ0FQUywgW10pXG4gICAgICAgICAgLnJldHVybnMoW1NFU1NJT05fSUQsIHJlbW92ZUFwcGl1bVByZWZpeGVzKFczQ19QUkVGSVhFRF9DQVBTKV0pO1xuICAgICAgICBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihudWxsLCBudWxsLCBXM0NfQ0FQUyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdChgc2hvdWxkIGNhbGwgaW5uZXIgZHJpdmVyJ3MgY3JlYXRlU2Vzc2lvbiB3aXRoIGRlc2lyZWQgYW5kIGRlZmF1bHQgY2FwYWJpbGl0aWVzYCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgZGVmYXVsdENhcHMgPSB7J2FwcGl1bTpzb21lQ2FwJzogJ2hlbGxvJ307XG4gICAgICAgIGxldCBhbGxDYXBzID0gey4uLlczQ19DQVBTLCBhbHdheXNNYXRjaDogey4uLlczQ19DQVBTLmFsd2F5c01hdGNoLCAuLi5kZWZhdWx0Q2Fwc319O1xuICAgICAgICBhcHBpdW0uYXJncy5kZWZhdWx0Q2FwYWJpbGl0aWVzID0gZGVmYXVsdENhcHM7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEFyZ3MobnVsbCwgbnVsbCwgYWxsQ2FwcylcbiAgICAgICAgICAucmV0dXJucyhbU0VTU0lPTl9JRCwgcmVtb3ZlQXBwaXVtUHJlZml4ZXMoYWxsQ2Fwcy5hbHdheXNNYXRjaCldKTtcbiAgICAgICAgYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24obnVsbCwgbnVsbCwgVzNDX0NBUFMpO1xuICAgICAgICBtb2NrRmFrZURyaXZlci52ZXJpZnkoKTtcbiAgICAgIH0pO1xuICAgICAgaXQoYHNob3VsZCBjYWxsIGlubmVyIGRyaXZlcidzIGNyZWF0ZVNlc3Npb24gd2l0aCBkZXNpcmVkIGFuZCBkZWZhdWx0IGNhcGFiaWxpdGllcyB3aXRob3V0IG92ZXJyaWRpbmcgY2Fwc2AsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gYSBkZWZhdWx0IGNhcGFiaWxpdHkgd2l0aCB0aGUgc2FtZSBrZXkgYXMgYSBkZXNpcmVkIGNhcGFiaWxpdHlcbiAgICAgICAgLy8gc2hvdWxkIGRvIG5vdGhpbmdcbiAgICAgICAgbGV0IGRlZmF1bHRDYXBzID0ge3BsYXRmb3JtTmFtZTogJ0Vyc2F0eid9O1xuICAgICAgICBhcHBpdW0uYXJncy5kZWZhdWx0Q2FwYWJpbGl0aWVzID0gZGVmYXVsdENhcHM7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEFyZ3MobnVsbCwgbnVsbCwgVzNDX0NBUFMpXG4gICAgICAgICAgLnJldHVybnMoW1NFU1NJT05fSUQsIHJlbW92ZUFwcGl1bVByZWZpeGVzKFczQ19QUkVGSVhFRF9DQVBTKV0pO1xuICAgICAgICBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihudWxsLCBudWxsLCBXM0NfQ0FQUyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIGtpbGwgYWxsIG90aGVyIHNlc3Npb25zIGlmIHNlc3Npb25PdmVycmlkZSBpcyBvbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXBwaXVtLmFyZ3Muc2Vzc2lvbk92ZXJyaWRlID0gdHJ1ZTtcblxuICAgICAgICAvLyBtb2NrIHRocmVlIHNlc3Npb25zIHRoYXQgc2hvdWxkIGJlIHJlbW92ZWQgd2hlbiB0aGUgbmV3IG9uZSBpcyBjcmVhdGVkXG4gICAgICAgIGxldCBmYWtlRHJpdmVycyA9IFtcbiAgICAgICAgICBuZXcgRmFrZURyaXZlcigpLFxuICAgICAgICAgIG5ldyBGYWtlRHJpdmVyKCksXG4gICAgICAgICAgbmV3IEZha2VEcml2ZXIoKSxcbiAgICAgICAgXTtcbiAgICAgICAgbGV0IG1vY2tGYWtlRHJpdmVycyA9IF8ubWFwKGZha2VEcml2ZXJzLCAoZmQpID0+IHNpbm9uLm1vY2soZmQpKTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXJzWzBdLmV4cGVjdHMoJ2RlbGV0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyc1sxXS5leHBlY3RzKCdkZWxldGVTZXNzaW9uJylcbiAgICAgICAgICAub25jZSgpXG4gICAgICAgICAgLnRocm93cygnQ2Fubm90IHNodXQgZG93biBBbmRyb2lkIGRyaXZlcjsgaXQgaGFzIGFscmVhZHkgc2h1dCBkb3duJyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyc1syXS5leHBlY3RzKCdkZWxldGVTZXNzaW9uJylcbiAgICAgICAgICAub25jZSgpO1xuICAgICAgICBhcHBpdW0uc2Vzc2lvbnNbJ2FiYy0xMjMteHl6J10gPSBmYWtlRHJpdmVyc1swXTtcbiAgICAgICAgYXBwaXVtLnNlc3Npb25zWyd4eXotMzIxLWFiYyddID0gZmFrZURyaXZlcnNbMV07XG4gICAgICAgIGFwcGl1bS5zZXNzaW9uc1snMTIzLWFiYy14eXonXSA9IGZha2VEcml2ZXJzWzJdO1xuXG4gICAgICAgIGxldCBzZXNzaW9ucyA9IGF3YWl0IGFwcGl1bS5nZXRTZXNzaW9ucygpO1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuaGF2ZS5sZW5ndGgoMyk7XG5cbiAgICAgICAgbW9ja0Zha2VEcml2ZXIuZXhwZWN0cygnY3JlYXRlU2Vzc2lvbicpXG4gICAgICAgICAgLm9uY2UoKS53aXRoRXhhY3RBcmdzKG51bGwsIG51bGwsIFczQ19DQVBTLCBbXSlcbiAgICAgICAgICAucmV0dXJucyhbU0VTU0lPTl9JRCwgcmVtb3ZlQXBwaXVtUHJlZml4ZXMoVzNDX1BSRUZJWEVEX0NBUFMpXSk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKG51bGwsIG51bGwsIFczQ19DQVBTKTtcblxuICAgICAgICBzZXNzaW9ucyA9IGF3YWl0IGFwcGl1bS5nZXRTZXNzaW9ucygpO1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuaGF2ZS5sZW5ndGgoMSk7XG5cbiAgICAgICAgZm9yIChsZXQgbWZkIG9mIG1vY2tGYWtlRHJpdmVycykge1xuICAgICAgICAgIG1mZC52ZXJpZnkoKTtcbiAgICAgICAgfVxuICAgICAgICBtb2NrRmFrZURyaXZlci52ZXJpZnkoKTtcbiAgICAgIH0pO1xuICAgICAgaXQoJ3Nob3VsZCBjYWxsIFwiY3JlYXRlU2Vzc2lvblwiIHdpdGggVzNDIGNhcGFiaWxpdGllcyBhcmd1bWVudCwgaWYgcHJvdmlkZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEFyZ3MobnVsbCwgdW5kZWZpbmVkLCBXM0NfQ0FQUylcbiAgICAgICAgICAucmV0dXJucyhbU0VTU0lPTl9JRCwgQkFTRV9DQVBTXSk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBXM0NfQ0FQUyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIGNhbGwgXCJjcmVhdGVTZXNzaW9uXCIgd2l0aCBXM0MgY2FwYWJpbGl0aWVzIGFyZ3VtZW50IHdpdGggYWRkaXRpb25hbCBwcm92aWRlZCBwYXJhbWV0ZXJzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgdzNjQ2FwcyA9IHtcbiAgICAgICAgICAuLi5XM0NfQ0FQUyxcbiAgICAgICAgICBhbHdheXNNYXRjaDoge1xuICAgICAgICAgICAgLi4uVzNDX0NBUFMuYWx3YXlzTWF0Y2gsXG4gICAgICAgICAgICAnYXBwaXVtOnNvbWVPdGhlclBhcm0nOiAnc29tZU90aGVyUGFybScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXIuZXhwZWN0cygnY3JlYXRlU2Vzc2lvbicpXG4gICAgICAgICAgLm9uY2UoKS53aXRoQXJncyhudWxsLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICAgIGFsd2F5c01hdGNoOiB7XG4gICAgICAgICAgICAgIC4uLnczY0NhcHMuYWx3YXlzTWF0Y2gsXG4gICAgICAgICAgICAgICdhcHBpdW06c29tZU90aGVyUGFybSc6ICdzb21lT3RoZXJQYXJtJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmaXJzdE1hdGNoOiBbe31dLFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJldHVybnMoW1NFU1NJT05fSUQsIGluc2VydEFwcGl1bVByZWZpeGVzKEJBU0VfQ0FQUyldKTtcblxuICAgICAgICBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbih1bmRlZmluZWQsIHVuZGVmaW5lZCwgdzNjQ2Fwcyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIG5vdCBjYWxsIFwiY3JlYXRlU2Vzc2lvblwiIHdpdGggSlNPTldQIGNhcGFiaWxpdGllcyBpZiBXM0MgaGFzIGluY29tcGxldGUgY2FwYWJpbGl0aWVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCB3M2NDYXBzID0ge1xuICAgICAgICAgIC4uLlczQ19DQVBTLFxuICAgICAgICAgIGFsd2F5c01hdGNoOiB7XG4gICAgICAgICAgICAnYXBwaXVtOnNvbWVPdGhlclBhcm0nOiAnc29tZU90aGVyUGFybScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBqc29ud3BDYXBzID0ge1xuICAgICAgICAgIC4uLkJBU0VfQ0FQUyxcbiAgICAgICAgICBhdXRvbWF0aW9uTmFtZTogJ0Zha2UnLFxuICAgICAgICAgIHNvbWVPdGhlclBhcmFtOiAnc29tZU90aGVyUGFyYW0nLFxuICAgICAgICB9O1xuXG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKS5uZXZlcigpO1xuICAgICAgICBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihqc29ud3BDYXBzLCB1bmRlZmluZWQsIHczY0NhcHMpO1xuICAgICAgICBtb2NrRmFrZURyaXZlci52ZXJpZnkoKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGFzc2lnbiBhcmdzIHRvIHByb3BlcnR5IGBjbGlBcmdzYCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2xhc3MgQXJnc0RyaXZlciBleHRlbmRzIEJhc2VEcml2ZXIge1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFyZ3MgPSB7ZHJpdmVyOiB7ZmFrZToge3JhbmRvbUFyZzogMTIzNH19fTtcbiAgICAgICAgW2FwcGl1bSwgbW9ja0Zha2VEcml2ZXJdID0gZ2V0RHJpdmVyQW5kRmFrZURyaXZlcihhcmdzLCBBcmdzRHJpdmVyKTtcbiAgICAgICAgY29uc3Qge3ZhbHVlfSA9IGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBXM0NfQ0FQUyk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbW9ja0Zha2VEcml2ZXIuX2Zha2VEcml2ZXIuY2xpQXJncy5zaG91bGQuZXFsKHtyYW5kb21Bcmc6IDEyMzR9KTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbih2YWx1ZVswXSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGRlc2NyaWJlKCdkZWxldGVTZXNzaW9uJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGFwcGl1bTtcbiAgICAgIGxldCBtb2NrRmFrZURyaXZlcjtcbiAgICAgIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBbYXBwaXVtLCBtb2NrRmFrZURyaXZlcl0gPSBnZXREcml2ZXJBbmRGYWtlRHJpdmVyKCk7XG4gICAgICB9KTtcbiAgICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnJlc3RvcmUoKTtcbiAgICAgIH0pO1xuICAgICAgaXQoJ3Nob3VsZCByZW1vdmUgdGhlIHNlc3Npb24gaWYgaXQgaXMgZm91bmQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBbc2Vzc2lvbklkXSA9IChhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihudWxsLCBudWxsLCBXM0NfQ0FQUykpLnZhbHVlO1xuICAgICAgICBsZXQgc2Vzc2lvbnMgPSBhd2FpdCBhcHBpdW0uZ2V0U2Vzc2lvbnMoKTtcbiAgICAgICAgc2Vzc2lvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDEpO1xuICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbihzZXNzaW9uSWQpO1xuICAgICAgICBzZXNzaW9ucyA9IGF3YWl0IGFwcGl1bS5nZXRTZXNzaW9ucygpO1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuaGF2ZS5sZW5ndGgoMCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgY2FsbCBpbm5lciBkcml2ZXJcXCdzIGRlbGV0ZVNlc3Npb24gbWV0aG9kJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBbc2Vzc2lvbklkXSA9IChhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihudWxsLCBudWxsLCBXM0NfQ0FQUykpLnZhbHVlO1xuICAgICAgICBtb2NrRmFrZURyaXZlci5leHBlY3RzKCdkZWxldGVTZXNzaW9uJylcbiAgICAgICAgICAub25jZSgpLndpdGhFeGFjdEFyZ3Moc2Vzc2lvbklkLCBbXSlcbiAgICAgICAgICAucmV0dXJucygpO1xuICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbihzZXNzaW9uSWQpO1xuICAgICAgICBtb2NrRmFrZURyaXZlci52ZXJpZnkoKTtcblxuICAgICAgICAvLyBjbGVhbnVwLCBzaW5jZSB3ZSBmYWtlZCB0aGUgZGVsZXRlIHNlc3Npb24gY2FsbFxuICAgICAgICBhd2FpdCBtb2NrRmFrZURyaXZlci5vYmplY3QuZGVsZXRlU2Vzc2lvbigpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgZGVzY3JpYmUoJ2dldFNlc3Npb25zJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGFwcGl1bSwgbW9ja0Zha2VEcml2ZXI7XG4gICAgICBsZXQgc2Vzc2lvbnM7XG4gICAgICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgICAgICBbYXBwaXVtLCBtb2NrRmFrZURyaXZlcl0gPSBnZXREcml2ZXJBbmRGYWtlRHJpdmVyKCk7XG4gICAgICB9KTtcbiAgICAgIGFmdGVyRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvciAobGV0IHNlc3Npb24gb2Ygc2Vzc2lvbnMpIHtcbiAgICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbihzZXNzaW9uLmlkKTtcbiAgICAgICAgfVxuICAgICAgICBtb2NrRmFrZURyaXZlci5yZXN0b3JlKCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIGFuIGVtcHR5IGFycmF5IG9mIHNlc3Npb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBzZXNzaW9ucyA9IGF3YWl0IGFwcGl1bS5nZXRTZXNzaW9ucygpO1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuYmUuYW4oJ2FycmF5Jyk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5iZS5lbXB0eTtcbiAgICAgIH0pO1xuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gc2Vzc2lvbnMgY3JlYXRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IGNhcHMxID0ge2Fsd2F5c01hdGNoOiB7Li4uVzNDX1BSRUZJWEVEX0NBUFMsICdhcHBpdW06Y2FwJzogJ3ZhbHVlJ319O1xuICAgICAgICBsZXQgY2FwczIgPSB7YWx3YXlzTWF0Y2g6IHsuLi5XM0NfUFJFRklYRURfQ0FQUywgJ2FwcGl1bTpjYXAnOiAnb3RoZXIgdmFsdWUnfX07XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoJ2NyZWF0ZVNlc3Npb24nKS5vbmNlKClcbiAgICAgICAgICAucmV0dXJucyhbJ2Zha2Utc2Vzc2lvbi1pZC0xJywgcmVtb3ZlQXBwaXVtUHJlZml4ZXMoY2FwczEuYWx3YXlzTWF0Y2gpXSk7XG4gICAgICAgIGxldCBbc2Vzc2lvbjFJZCwgc2Vzc2lvbjFDYXBzXSA9IChhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihudWxsLCBudWxsLCBjYXBzMSkpLnZhbHVlO1xuICAgICAgICBtb2NrRmFrZURyaXZlci5leHBlY3RzKCdjcmVhdGVTZXNzaW9uJykub25jZSgpXG4gICAgICAgICAgLnJldHVybnMoWydmYWtlLXNlc3Npb24taWQtMicsIHJlbW92ZUFwcGl1bVByZWZpeGVzKGNhcHMyLmFsd2F5c01hdGNoKV0pO1xuICAgICAgICBsZXQgW3Nlc3Npb24ySWQsIHNlc3Npb24yQ2Fwc10gPSAoYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24obnVsbCwgbnVsbCwgY2FwczIpKS52YWx1ZTtcblxuICAgICAgICBzZXNzaW9ucyA9IGF3YWl0IGFwcGl1bS5nZXRTZXNzaW9ucygpO1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuYmUuYW4oJ2FycmF5Jyk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5oYXZlLmxlbmd0aCgyKTtcbiAgICAgICAgc2Vzc2lvbnNbMF0uaWQuc2hvdWxkLmVxdWFsKHNlc3Npb24xSWQpO1xuICAgICAgICByZW1vdmVBcHBpdW1QcmVmaXhlcyhjYXBzMS5hbHdheXNNYXRjaCkuc2hvdWxkLmVxbChzZXNzaW9uMUNhcHMpO1xuICAgICAgICBzZXNzaW9uc1sxXS5pZC5zaG91bGQuZXF1YWwoc2Vzc2lvbjJJZCk7XG4gICAgICAgIHJlbW92ZUFwcGl1bVByZWZpeGVzKGNhcHMyLmFsd2F5c01hdGNoKS5zaG91bGQuZXFsKHNlc3Npb24yQ2Fwcyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBkZXNjcmliZSgnZ2V0U3RhdHVzJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGFwcGl1bTtcbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFwcGl1bSA9IG5ldyBBcHBpdW1Ecml2ZXIoe30pO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIHJldHVybiBhIHN0YXR1cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IHN0YXR1cyA9IGF3YWl0IGFwcGl1bS5nZXRTdGF0dXMoKTtcbiAgICAgICAgc3RhdHVzLmJ1aWxkLnNob3VsZC5leGlzdDtcbiAgICAgICAgc3RhdHVzLmJ1aWxkLnZlcnNpb24uc2hvdWxkLmV4aXN0O1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgZGVzY3JpYmUoJ3Nlc3Npb25FeGlzdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgfSk7XG4gICAgZGVzY3JpYmUoJ2F0dGFjaFVuZXhwZWN0ZWRTaHV0ZG93bkhhbmRsZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICBsZXQgYXBwaXVtO1xuICAgICAgbGV0IG1vY2tGYWtlRHJpdmVyO1xuICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIFthcHBpdW0sIG1vY2tGYWtlRHJpdmVyXSA9IGdldERyaXZlckFuZEZha2VEcml2ZXIoKTtcbiAgICAgIH0pO1xuICAgICAgYWZ0ZXJFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgbW9ja0Zha2VEcml2ZXIub2JqZWN0LmRlbGV0ZVNlc3Npb24oKTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXIucmVzdG9yZSgpO1xuICAgICAgICBhcHBpdW0uYXJncy5kZWZhdWx0Q2FwYWJpbGl0aWVzID0ge307XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZW1vdmUgc2Vzc2lvbiBpZiBpbm5lciBkcml2ZXIgdW5leHBlY3RlZGx5IGV4aXRzIHdpdGggYW4gZXJyb3InLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBbc2Vzc2lvbklkLF0gPSAoYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24obnVsbCwgbnVsbCwgXy5jbG9uZShXM0NfQ0FQUykpKS52YWx1ZTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb21tYS1zcGFjaW5nXG4gICAgICAgIF8ua2V5cyhhcHBpdW0uc2Vzc2lvbnMpLnNob3VsZC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICAgIGFwcGl1bS5zZXNzaW9uc1tzZXNzaW9uSWRdLmV2ZW50RW1pdHRlci5lbWl0KCdvblVuZXhwZWN0ZWRTaHV0ZG93bicsIG5ldyBFcnJvcignT29wcycpKTtcbiAgICAgICAgLy8gbGV0IGV2ZW50IGxvb3Agc3BpbiBzbyByZWplY3Rpb24gaXMgaGFuZGxlZFxuICAgICAgICBhd2FpdCBzbGVlcCgxKTtcbiAgICAgICAgXy5rZXlzKGFwcGl1bS5zZXNzaW9ucykuc2hvdWxkLm5vdC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgcmVtb3ZlIHNlc3Npb24gaWYgaW5uZXIgZHJpdmVyIHVuZXhwZWN0ZWRseSBleGl0cyB3aXRoIG5vIGVycm9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgW3Nlc3Npb25JZCxdID0gKGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKG51bGwsIG51bGwsIF8uY2xvbmUoVzNDX0NBUFMpKSkudmFsdWU7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY29tbWEtc3BhY2luZ1xuICAgICAgICBfLmtleXMoYXBwaXVtLnNlc3Npb25zKS5zaG91bGQuY29udGFpbihzZXNzaW9uSWQpO1xuICAgICAgICBhcHBpdW0uc2Vzc2lvbnNbc2Vzc2lvbklkXS5ldmVudEVtaXR0ZXIuZW1pdCgnb25VbmV4cGVjdGVkU2h1dGRvd24nKTtcbiAgICAgICAgLy8gbGV0IGV2ZW50IGxvb3Agc3BpbiBzbyByZWplY3Rpb24gaXMgaGFuZGxlZFxuICAgICAgICBhd2FpdCBzbGVlcCgxKTtcbiAgICAgICAgXy5rZXlzKGFwcGl1bS5zZXNzaW9ucykuc2hvdWxkLm5vdC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBkZXNjcmliZSgnY3JlYXRlUGx1Z2luSW5zdGFuY2VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY2xhc3MgTm9BcmdzUGx1Z2luIHt9XG4gICAgICBOb0FyZ3NQbHVnaW4ucGx1Z2luTmFtZSA9ICdub2FyZ3MnO1xuXG4gICAgICBjbGFzcyBBcmdzUGx1Z2luIHt9XG4gICAgICBBcmdzUGx1Z2luLnBsdWdpbk5hbWUgPSAnYXJncyc7XG5cbiAgICAgIGNsYXNzIEFycmF5QXJnUGx1Z2luIHt9XG4gICAgICBBcnJheUFyZ1BsdWdpbi5wbHVnaW5OYW1lID0gJ2FycmF5YXJnJztcblxuICAgICAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc2V0U2NoZW1hKCk7XG4gICAgICAgIC8vIHRvIGVzdGFibGlzaCBkZWZhdWx0cywgd2UgbmVlZCB0byByZWdpc3RlciBhIHNjaGVtYSBmb3IgdGhlIHBsdWdpbi5cbiAgICAgICAgLy8gbm90ZSB0aGF0IHRoZSBgbm9hcmdzYCBwbHVnaW4gZG9lcyBub3QgbmVlZCBhIHNjaGVtYSwgYmVjYXVzZSBpdFxuICAgICAgICAvLyBhY2NlcHRzIG5vIGFyZ3VtZW50cy5cbiAgICAgICAgcmVnaXN0ZXJTY2hlbWEoJ3BsdWdpbicsIEFyZ3NQbHVnaW4ucGx1Z2luTmFtZSwge1xuICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIHJhbmRvbUFyZzoge1xuICAgICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgZGVmYXVsdDogMjAwMFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJlZ2lzdGVyU2NoZW1hKCdwbHVnaW4nLCBBcnJheUFyZ1BsdWdpbi5wbHVnaW5OYW1lLCB7XG4gICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgYXJyOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdhcnJheScsXG4gICAgICAgICAgICAgIGRlZmF1bHQ6IFtdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZmluYWxpemVTY2hlbWEoKTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnd2hlbiBhcmdzIGFyZSBub3QgcHJlc2VudCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBub3Qgc2V0IENMSSBhcmdzJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGFwcGl1bSA9IG5ldyBBcHBpdW1Ecml2ZXIoe30pO1xuICAgICAgICAgIGFwcGl1bS5wbHVnaW5DbGFzc2VzID0gW05vQXJnc1BsdWdpbiwgQXJnc1BsdWdpbl07XG4gICAgICAgICAgZm9yIChjb25zdCBwbHVnaW4gb2YgYXBwaXVtLmNyZWF0ZVBsdWdpbkluc3RhbmNlcygpKSB7XG4gICAgICAgICAgICBzaG91bGQubm90LmV4aXN0KHBsdWdpbi5jbGlBcmdzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGRlc2NyaWJlKCd3aGVuIGFyZ3MgYXJlIGVxdWFsIHRvIHRoZSBzY2hlbWEgZGVmYXVsdHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgbm90IHNldCBDTEkgYXJncycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjb25zdCBhcHBpdW0gPSBuZXcgQXBwaXVtRHJpdmVyKHtwbHVnaW46IHtbQXJnc1BsdWdpbi5wbHVnaW5OYW1lXToge3JhbmRvbUFyZzogMjAwMH19fSk7XG4gICAgICAgICAgYXBwaXVtLnBsdWdpbkNsYXNzZXMgPSBbTm9BcmdzUGx1Z2luLCBBcmdzUGx1Z2luXTtcbiAgICAgICAgICBmb3IgKGNvbnN0IHBsdWdpbiBvZiBhcHBpdW0uY3JlYXRlUGx1Z2luSW5zdGFuY2VzKCkpIHtcbiAgICAgICAgICAgIHNob3VsZC5ub3QuZXhpc3QocGx1Z2luLmNsaUFyZ3MpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgZGVzY3JpYmUoJ3doZW4gdGhlIGRlZmF1bHQgaXMgYW4gXCJvYmplY3RcIicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpdCgnc2hvdWxkIG5vdCBzZXQgQ0xJIGFyZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBhcHBpdW0gPSBuZXcgQXBwaXVtRHJpdmVyKHtwbHVnaW46IHtbQXJyYXlBcmdQbHVnaW4ucGx1Z2luTmFtZV06IHthcnI6IFtdfX19KTtcbiAgICAgICAgICAgIGFwcGl1bS5wbHVnaW5DbGFzc2VzID0gW05vQXJnc1BsdWdpbiwgQXJnc1BsdWdpbiwgQXJyYXlBcmdQbHVnaW5dO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwbHVnaW4gb2YgYXBwaXVtLmNyZWF0ZVBsdWdpbkluc3RhbmNlcygpKSB7XG4gICAgICAgICAgICAgIHNob3VsZC5ub3QuZXhpc3QocGx1Z2luLmNsaUFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBkZXNjcmliZSgnd2hlbiBhcmdzIGFyZSBub3QgZXF1YWwgdG8gdGhlIHNjaGVtYSBkZWZhdWx0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaXQoJ3Nob3VsZCBhZGQgY2xpQXJncyB0byB0aGUgcGx1Z2luJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGNvbnN0IGFwcGl1bSA9IG5ldyBBcHBpdW1Ecml2ZXIoe3BsdWdpbjoge2FyZ3M6IHtyYW5kb21Bcmc6IDEyMzR9fX0pO1xuICAgICAgICAgIGFwcGl1bS5wbHVnaW5DbGFzc2VzID0gW0FyZ3NQbHVnaW5dO1xuICAgICAgICAgIGNvbnN0IHBsdWdpbiA9IF8uZmlyc3QoYXBwaXVtLmNyZWF0ZVBsdWdpbkluc3RhbmNlcygpKTtcbiAgICAgICAgICBwbHVnaW4uY2xpQXJncy5zaG91bGQuZXFsKHtyYW5kb21Bcmc6IDEyMzR9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdLCJmaWxlIjoidGVzdC9kcml2ZXItc3BlY3MuanMiLCJzb3VyY2VSb290IjoiLi4vLi4ifQ==