@appium/base-driver 8.5.7 → 8.7.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 (74) hide show
  1. package/build/lib/basedriver/capabilities.js +2 -2
  2. package/build/lib/basedriver/commands/execute.d.ts +11 -0
  3. package/build/lib/basedriver/commands/execute.d.ts.map +1 -0
  4. package/build/lib/basedriver/commands/execute.js +62 -0
  5. package/build/lib/basedriver/commands/index.d.ts +1 -1
  6. package/build/lib/basedriver/commands/index.d.ts.map +1 -1
  7. package/build/lib/basedriver/commands/index.js +5 -2
  8. package/build/lib/basedriver/commands/log.js +2 -4
  9. package/build/lib/basedriver/core.d.ts +11 -0
  10. package/build/lib/basedriver/core.d.ts.map +1 -1
  11. package/build/lib/basedriver/core.js +6 -1
  12. package/build/lib/basedriver/helpers.js +2 -2
  13. package/build/lib/express/server.d.ts +70 -7
  14. package/build/lib/express/server.d.ts.map +1 -1
  15. package/build/lib/express/server.js +19 -16
  16. package/build/lib/express/websocket.d.ts +12 -30
  17. package/build/lib/express/websocket.d.ts.map +1 -1
  18. package/build/lib/express/websocket.js +6 -4
  19. package/build/lib/index.d.ts +12 -180
  20. package/build/lib/index.d.ts.map +1 -1
  21. package/build/lib/index.js +107 -80
  22. package/build/lib/jsonwp-proxy/protocol-converter.js +2 -4
  23. package/build/lib/jsonwp-proxy/proxy.js +3 -7
  24. package/build/lib/protocol/index.d.ts +3 -1
  25. package/build/lib/protocol/index.js +13 -1
  26. package/build/lib/protocol/protocol.d.ts +8 -4
  27. package/build/lib/protocol/protocol.d.ts.map +1 -1
  28. package/build/lib/protocol/protocol.js +7 -7
  29. package/build/lib/protocol/routes.js +2 -6
  30. package/build/tsconfig.tsbuildinfo +1 -1
  31. package/lib/basedriver/commands/execute.js +65 -0
  32. package/lib/basedriver/commands/index.js +3 -1
  33. package/lib/basedriver/core.js +15 -0
  34. package/lib/express/server.js +126 -36
  35. package/lib/express/websocket.js +13 -11
  36. package/lib/index.js +19 -61
  37. package/lib/protocol/index.js +4 -0
  38. package/lib/protocol/protocol.js +10 -3
  39. package/package.json +17 -15
  40. package/build/test/basedriver/README.md +0 -5
  41. package/build/test/basedriver/driver-e2e-tests.js +0 -413
  42. package/build/test/basedriver/driver-tests.js +0 -572
  43. package/build/test/basedriver/index.js +0 -26
  44. package/build/test/e2e/basedriver/driver.e2e.spec.js +0 -15
  45. package/build/test/e2e/basedriver/helpers.e2e.spec.js +0 -192
  46. package/build/test/e2e/basedriver/websockets.e2e.spec.js +0 -87
  47. package/build/test/e2e/express/server.e2e.spec.js +0 -159
  48. package/build/test/e2e/jsonwp-proxy/proxy.e2e.spec.js +0 -59
  49. package/build/test/e2e/protocol/fake-driver.js +0 -163
  50. package/build/test/e2e/protocol/helpers.js +0 -25
  51. package/build/test/e2e/protocol/protocol.e2e.spec.js +0 -1186
  52. package/build/test/helpers.js +0 -55
  53. package/build/test/unit/basedriver/capabilities.spec.js +0 -672
  54. package/build/test/unit/basedriver/capability.spec.js +0 -353
  55. package/build/test/unit/basedriver/commands/event.spec.js +0 -110
  56. package/build/test/unit/basedriver/commands/log.spec.js +0 -92
  57. package/build/test/unit/basedriver/device-settings.spec.js +0 -97
  58. package/build/test/unit/basedriver/driver.spec.js +0 -15
  59. package/build/test/unit/basedriver/helpers.spec.js +0 -151
  60. package/build/test/unit/basedriver/timeout.spec.js +0 -135
  61. package/build/test/unit/express/server.spec.js +0 -155
  62. package/build/test/unit/express/static.spec.js +0 -26
  63. package/build/test/unit/jsonwp-proxy/mock-request.js +0 -91
  64. package/build/test/unit/jsonwp-proxy/protocol-converter.spec.js +0 -171
  65. package/build/test/unit/jsonwp-proxy/proxy.spec.js +0 -292
  66. package/build/test/unit/jsonwp-proxy/url.spec.js +0 -165
  67. package/build/test/unit/jsonwp-status/status.spec.js +0 -34
  68. package/build/test/unit/protocol/errors.spec.js +0 -390
  69. package/build/test/unit/protocol/routes.spec.js +0 -80
  70. package/build/test/unit/protocol/validator.spec.js +0 -149
  71. package/test/basedriver/README.md +0 -5
  72. package/test/basedriver/driver-e2e-tests.js +0 -386
  73. package/test/basedriver/driver-tests.js +0 -624
  74. package/test/basedriver/index.js +0 -6
@@ -1,413 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.default = void 0;
9
-
10
- require("source-map-support/register");
11
-
12
- var _lodash = _interopRequireDefault(require("lodash"));
13
-
14
- var _lib = require("../../lib");
15
-
16
- var _axios = _interopRequireDefault(require("axios"));
17
-
18
- var _bluebird = _interopRequireDefault(require("bluebird"));
19
-
20
- var _helpers = require("../helpers");
21
-
22
- var _capabilities = require("../../lib/basedriver/capabilities");
23
-
24
- const {
25
- POST,
26
- DELETE
27
- } = _helpers.METHODS;
28
-
29
- function baseDriverE2ETests(DriverClass, defaultCaps = {}) {
30
- var _defaultCaps$appiumA;
31
-
32
- let address = (_defaultCaps$appiumA = defaultCaps['appium:address']) !== null && _defaultCaps$appiumA !== void 0 ? _defaultCaps$appiumA : _helpers.TEST_HOST;
33
- let port = defaultCaps['appium:port'];
34
- const className = DriverClass.name || '(unknown driver)';
35
- describe(`BaseDriver E2E (as ${className})`, function () {
36
- let baseServer, d;
37
- let newSessionURL;
38
- let createAppiumTestURL;
39
- let createSessionURL;
40
- before(async function () {
41
- var _port;
42
-
43
- port = (_port = port) !== null && _port !== void 0 ? _port : await (0, _helpers.getTestPort)();
44
- defaultCaps = { ...defaultCaps,
45
- 'appium:port': port
46
- };
47
- d = new DriverClass({
48
- port,
49
- address
50
- });
51
- baseServer = await (0, _lib.server)({
52
- routeConfiguringFunction: (0, _lib.routeConfiguringFunction)(d),
53
- port,
54
- hostname: _helpers.TEST_HOST
55
- });
56
- createAppiumTestURL = (0, _helpers.createAppiumURL)(address, port);
57
- newSessionURL = createAppiumTestURL('', 'session');
58
- createSessionURL = createAppiumTestURL(_lodash.default, '');
59
- });
60
- after(async function () {
61
- await baseServer.close();
62
- });
63
-
64
- async function startSession(caps) {
65
- return (await (0, _axios.default)({
66
- url: newSessionURL,
67
- method: POST,
68
- data: {
69
- capabilities: {
70
- alwaysMatch: caps,
71
- firstMatch: [{}]
72
- }
73
- }
74
- })).data.value;
75
- }
76
-
77
- async function endSession(id) {
78
- return (await (0, _axios.default)({
79
- url: createSessionURL(id),
80
- method: DELETE,
81
- validateStatus: null
82
- })).data.value;
83
- }
84
-
85
- async function getSession(id) {
86
- return (await (0, _axios.default)({
87
- url: createSessionURL(id)
88
- })).data.value;
89
- }
90
-
91
- describe('session handling', function () {
92
- it('should handle idempotency while creating sessions', async function () {
93
- const sessionIds = [];
94
- let times = 0;
95
-
96
- do {
97
- const {
98
- sessionId
99
- } = (await (0, _axios.default)({
100
- url: newSessionURL,
101
- headers: {
102
- 'X-Idempotency-Key': '123456'
103
- },
104
- method: POST,
105
- data: {
106
- capabilities: {
107
- alwaysMatch: defaultCaps,
108
- firstMatch: [{}]
109
- }
110
- },
111
- simple: false,
112
- resolveWithFullResponse: true
113
- })).data.value;
114
- sessionIds.push(sessionId);
115
- times++;
116
- } while (times < 2);
117
-
118
- _lodash.default.uniq(sessionIds).length.should.equal(1);
119
-
120
- const {
121
- status,
122
- data
123
- } = await (0, _axios.default)({
124
- url: createSessionURL(sessionIds[0]),
125
- method: DELETE
126
- });
127
- status.should.equal(200);
128
- should.equal(data.value, null);
129
- });
130
- it('should handle idempotency while creating parallel sessions', async function () {
131
- const reqs = [];
132
- let times = 0;
133
-
134
- do {
135
- reqs.push((0, _axios.default)({
136
- url: newSessionURL,
137
- headers: {
138
- 'X-Idempotency-Key': '12345'
139
- },
140
- method: POST,
141
- data: {
142
- capabilities: {
143
- alwaysMatch: defaultCaps,
144
- firstMatch: [{}]
145
- }
146
- }
147
- }));
148
- times++;
149
- } while (times < 2);
150
-
151
- const sessionIds = (await _bluebird.default.all(reqs)).map(x => x.data.value.sessionId);
152
-
153
- _lodash.default.uniq(sessionIds).length.should.equal(1);
154
-
155
- const {
156
- status,
157
- data
158
- } = await (0, _axios.default)({
159
- url: createSessionURL(sessionIds[0]),
160
- method: DELETE
161
- });
162
- status.should.equal(200);
163
- should.equal(data.value, null);
164
- });
165
- it('should create session and retrieve a session id, then delete it', async function () {
166
- let {
167
- status,
168
- data
169
- } = await (0, _axios.default)({
170
- url: newSessionURL,
171
- method: POST,
172
- data: {
173
- capabilities: {
174
- alwaysMatch: defaultCaps,
175
- firstMatch: [{}]
176
- }
177
- }
178
- });
179
- status.should.equal(200);
180
- should.exist(data.value.sessionId);
181
- data.value.capabilities.platformName.should.equal(defaultCaps.platformName);
182
- data.value.capabilities.deviceName.should.equal(defaultCaps['appium:deviceName']);
183
- ({
184
- status,
185
- data
186
- } = await (0, _axios.default)({
187
- url: createSessionURL(d.sessionId),
188
- method: DELETE
189
- }));
190
- status.should.equal(200);
191
- should.equal(data.value, null);
192
- should.equal(d.sessionId, null);
193
- });
194
- });
195
- it.skip('should throw NYI for commands not implemented', async function () {});
196
- describe('command timeouts', function () {
197
- let originalFindElement, originalFindElements;
198
-
199
- async function startTimeoutSession(timeout) {
200
- const caps = _lodash.default.cloneDeep(defaultCaps);
201
-
202
- caps['appium:newCommandTimeout'] = timeout;
203
- return await startSession(caps);
204
- }
205
-
206
- before(function () {
207
- originalFindElement = d.findElement;
208
-
209
- d.findElement = function () {
210
- return 'foo';
211
- }.bind(d);
212
-
213
- originalFindElements = d.findElements;
214
-
215
- d.findElements = async function () {
216
- await _bluebird.default.delay(200);
217
- return ['foo'];
218
- }.bind(d);
219
- });
220
- after(function () {
221
- d.findElement = originalFindElement;
222
- d.findElements = originalFindElements;
223
- });
224
- it('should set a default commandTimeout', async function () {
225
- let newSession = await startTimeoutSession();
226
- d.newCommandTimeoutMs.should.be.above(0);
227
- await endSession(newSession.sessionId);
228
- });
229
- it('should timeout on commands using commandTimeout cap', async function () {
230
- let newSession = await startTimeoutSession(0.25);
231
- let sessionURL = createSessionURL(d.sessionId);
232
- await (0, _axios.default)({
233
- url: createAppiumTestURL(d.sessionId, 'element'),
234
- method: POST,
235
- data: {
236
- using: 'name',
237
- value: 'foo'
238
- }
239
- });
240
- await _bluebird.default.delay(400);
241
- const {
242
- data
243
- } = await (0, _axios.default)({
244
- url: sessionURL,
245
- validateStatus: null
246
- });
247
- should.equal(data.value.error, 'invalid session id');
248
- should.equal(d.sessionId, null);
249
- const resp = await endSession(newSession.sessionId);
250
- should.equal(resp.error, 'invalid session id');
251
- });
252
- it('should not timeout with commandTimeout of false', async function () {
253
- let newSession = await startTimeoutSession(0.1);
254
- let start = Date.now();
255
- const {
256
- value
257
- } = (await (0, _axios.default)({
258
- url: createAppiumTestURL(d.sessionId, 'elements'),
259
- method: POST,
260
- data: {
261
- using: 'name',
262
- value: 'foo'
263
- }
264
- })).data;
265
- (Date.now() - start).should.be.above(150);
266
- value.should.eql(['foo']);
267
- await endSession(newSession.sessionId);
268
- });
269
- it('should not timeout with commandTimeout of 0', async function () {
270
- d.newCommandTimeoutMs = 2;
271
- let newSession = await startTimeoutSession(0);
272
- await (0, _axios.default)({
273
- url: createAppiumTestURL(d.sessionId, 'element'),
274
- method: POST,
275
- data: {
276
- using: 'name',
277
- value: 'foo'
278
- }
279
- });
280
- await _bluebird.default.delay(400);
281
- const {
282
- value
283
- } = (await (0, _axios.default)({
284
- url: createSessionURL(d.sessionId)
285
- })).data;
286
- value.platformName.should.equal(defaultCaps.platformName);
287
- const resp = await endSession(newSession.sessionId);
288
- should.equal(resp, null);
289
- d.newCommandTimeoutMs = 60 * 1000;
290
- });
291
- it('should not timeout if its just the command taking awhile', async function () {
292
- let newSession = await startTimeoutSession(0.25);
293
- let sessionURL = createSessionURL(d.sessionId);
294
- await (0, _axios.default)({
295
- url: createAppiumTestURL(d.sessionId, 'element'),
296
- method: POST,
297
- data: {
298
- using: 'name',
299
- value: 'foo'
300
- }
301
- });
302
- await _bluebird.default.delay(400);
303
- const {
304
- value
305
- } = (await (0, _axios.default)({
306
- url: sessionURL,
307
- validateStatus: null
308
- })).data;
309
- value.error.should.equal('invalid session id');
310
- should.equal(d.sessionId, null);
311
- const resp = await endSession(newSession.sessionId);
312
- resp.error.should.equal('invalid session id');
313
- });
314
- it('should not have a timer running before or after a session', async function () {
315
- should.not.exist(d.noCommandTimer);
316
- let newSession = await startTimeoutSession(0.25);
317
- newSession.sessionId.should.equal(d.sessionId);
318
- should.exist(d.noCommandTimer);
319
- await endSession(newSession.sessionId);
320
- should.not.exist(d.noCommandTimer);
321
- });
322
- });
323
- describe('settings api', function () {
324
- before(function () {
325
- d.settings = new _lib.DeviceSettings({
326
- ignoreUnimportantViews: false
327
- });
328
- });
329
- it('should be able to get settings object', function () {
330
- d.settings.getSettings().ignoreUnimportantViews.should.be.false;
331
- });
332
- it('should not reject when `updateSettings` method is not provided', async function () {
333
- await d.settings.update({
334
- ignoreUnimportantViews: true
335
- }).should.not.be.rejected;
336
- });
337
- it('should reject for invalid update object', async function () {
338
- await d.settings.update('invalid json').should.eventually.be.rejectedWith('JSON');
339
- });
340
- });
341
- describe('unexpected exits', function () {
342
- it('should reject a current command when the driver crashes', async function () {
343
- d._oldGetStatus = d.getStatus;
344
-
345
- try {
346
- d.getStatus = async function () {
347
- await _bluebird.default.delay(5000);
348
- }.bind(d);
349
-
350
- const reqPromise = (0, _axios.default)({
351
- url: createAppiumTestURL('', 'status'),
352
- validateStatus: null
353
- });
354
- await _bluebird.default.delay(100);
355
- const shutdownEventPromise = new _bluebird.default((resolve, reject) => {
356
- setTimeout(() => reject(new Error('onUnexpectedShutdown event is expected to be fired within 5 seconds timeout')), 5000);
357
- d.onUnexpectedShutdown(resolve);
358
- });
359
- d.startUnexpectedShutdown(new Error('Crashytimes'));
360
- const {
361
- value
362
- } = (await reqPromise).data;
363
- value.message.should.contain('Crashytimes');
364
- await shutdownEventPromise;
365
- } finally {
366
- d.getStatus = d._oldGetStatus;
367
- }
368
- });
369
- });
370
- describe('event timings', function () {
371
- it('should not add timings if not using opt-in cap', async function () {
372
- const session = await startSession(defaultCaps);
373
- const res = await getSession(session.sessionId);
374
- should.not.exist(res.events);
375
- await endSession(session.sessionId);
376
- });
377
- it('should add start session timings', async function () {
378
- const caps = Object.assign({}, defaultCaps, {
379
- 'appium:eventTimings': true
380
- });
381
- const session = await startSession(caps);
382
- const res = await getSession(session.sessionId);
383
- should.exist(res.events);
384
- should.exist(res.events.newSessionRequested);
385
- should.exist(res.events.newSessionStarted);
386
- res.events.newSessionRequested[0].should.be.a('number');
387
- res.events.newSessionStarted[0].should.be.a('number');
388
- await endSession(session.sessionId);
389
- });
390
- });
391
-
392
- if (DriverClass === _lib.BaseDriver) {
393
- describe('special appium:options capability', function () {
394
- it('should be able to start a session with caps held in appium:options', async function () {
395
- const ret = await startSession({
396
- platformName: 'iOS',
397
- [_capabilities.PREFIXED_APPIUM_OPTS_CAP]: {
398
- platformVersion: '11.4',
399
- 'appium:deviceName': 'iPhone 11'
400
- }
401
- });
402
- d.opts.platformVersion.should.eql('11.4');
403
- d.opts.deviceName.should.eql('iPhone 11');
404
- await endSession(ret.sessionId);
405
- });
406
- });
407
- }
408
- });
409
- }
410
-
411
- var _default = baseDriverE2ETests;
412
- exports.default = _default;
413
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQT1NUIiwiREVMRVRFIiwiTUVUSE9EUyIsImJhc2VEcml2ZXJFMkVUZXN0cyIsIkRyaXZlckNsYXNzIiwiZGVmYXVsdENhcHMiLCJhZGRyZXNzIiwiVEVTVF9IT1NUIiwicG9ydCIsImNsYXNzTmFtZSIsIm5hbWUiLCJkZXNjcmliZSIsImJhc2VTZXJ2ZXIiLCJkIiwibmV3U2Vzc2lvblVSTCIsImNyZWF0ZUFwcGl1bVRlc3RVUkwiLCJjcmVhdGVTZXNzaW9uVVJMIiwiYmVmb3JlIiwiZ2V0VGVzdFBvcnQiLCJzZXJ2ZXIiLCJyb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb24iLCJob3N0bmFtZSIsImNyZWF0ZUFwcGl1bVVSTCIsIl8iLCJhZnRlciIsImNsb3NlIiwic3RhcnRTZXNzaW9uIiwiY2FwcyIsImF4aW9zIiwidXJsIiwibWV0aG9kIiwiZGF0YSIsImNhcGFiaWxpdGllcyIsImFsd2F5c01hdGNoIiwiZmlyc3RNYXRjaCIsInZhbHVlIiwiZW5kU2Vzc2lvbiIsImlkIiwidmFsaWRhdGVTdGF0dXMiLCJnZXRTZXNzaW9uIiwiaXQiLCJzZXNzaW9uSWRzIiwidGltZXMiLCJzZXNzaW9uSWQiLCJoZWFkZXJzIiwic2ltcGxlIiwicmVzb2x2ZVdpdGhGdWxsUmVzcG9uc2UiLCJwdXNoIiwidW5pcSIsImxlbmd0aCIsInNob3VsZCIsImVxdWFsIiwic3RhdHVzIiwicmVxcyIsIkIiLCJhbGwiLCJtYXAiLCJ4IiwiZXhpc3QiLCJwbGF0Zm9ybU5hbWUiLCJkZXZpY2VOYW1lIiwic2tpcCIsIm9yaWdpbmFsRmluZEVsZW1lbnQiLCJvcmlnaW5hbEZpbmRFbGVtZW50cyIsInN0YXJ0VGltZW91dFNlc3Npb24iLCJ0aW1lb3V0IiwiY2xvbmVEZWVwIiwiZmluZEVsZW1lbnQiLCJiaW5kIiwiZmluZEVsZW1lbnRzIiwiZGVsYXkiLCJuZXdTZXNzaW9uIiwibmV3Q29tbWFuZFRpbWVvdXRNcyIsImJlIiwiYWJvdmUiLCJzZXNzaW9uVVJMIiwidXNpbmciLCJlcnJvciIsInJlc3AiLCJzdGFydCIsIkRhdGUiLCJub3ciLCJlcWwiLCJub3QiLCJub0NvbW1hbmRUaW1lciIsInNldHRpbmdzIiwiRGV2aWNlU2V0dGluZ3MiLCJpZ25vcmVVbmltcG9ydGFudFZpZXdzIiwiZ2V0U2V0dGluZ3MiLCJmYWxzZSIsInVwZGF0ZSIsInJlamVjdGVkIiwiZXZlbnR1YWxseSIsInJlamVjdGVkV2l0aCIsIl9vbGRHZXRTdGF0dXMiLCJnZXRTdGF0dXMiLCJyZXFQcm9taXNlIiwic2h1dGRvd25FdmVudFByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0Iiwic2V0VGltZW91dCIsIkVycm9yIiwib25VbmV4cGVjdGVkU2h1dGRvd24iLCJzdGFydFVuZXhwZWN0ZWRTaHV0ZG93biIsIm1lc3NhZ2UiLCJjb250YWluIiwic2Vzc2lvbiIsInJlcyIsImV2ZW50cyIsIk9iamVjdCIsImFzc2lnbiIsIm5ld1Nlc3Npb25SZXF1ZXN0ZWQiLCJuZXdTZXNzaW9uU3RhcnRlZCIsImEiLCJCYXNlRHJpdmVyIiwicmV0IiwiUFJFRklYRURfQVBQSVVNX09QVFNfQ0FQIiwicGxhdGZvcm1WZXJzaW9uIiwib3B0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvYmFzZWRyaXZlci9kcml2ZXItZTJlLXRlc3RzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge0Jhc2VEcml2ZXIsIHNlcnZlciwgcm91dGVDb25maWd1cmluZ0Z1bmN0aW9uLCBEZXZpY2VTZXR0aW5nc30gZnJvbSAnLi4vLi4vbGliJztcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQgQiBmcm9tICdibHVlYmlyZCc7XG5pbXBvcnQge1RFU1RfSE9TVCwgZ2V0VGVzdFBvcnQsIGNyZWF0ZUFwcGl1bVVSTCwgTUVUSE9EU30gZnJvbSAnLi4vaGVscGVycyc7XG5pbXBvcnQge1BSRUZJWEVEX0FQUElVTV9PUFRTX0NBUH0gZnJvbSAnLi4vLi4vbGliL2Jhc2Vkcml2ZXIvY2FwYWJpbGl0aWVzJztcbmNvbnN0IHtQT1NULCBERUxFVEV9ID0gTUVUSE9EUztcblxuZnVuY3Rpb24gYmFzZURyaXZlckUyRVRlc3RzKERyaXZlckNsYXNzLCBkZWZhdWx0Q2FwcyA9IHt9KSB7XG4gIGxldCBhZGRyZXNzID0gZGVmYXVsdENhcHNbJ2FwcGl1bTphZGRyZXNzJ10gPz8gVEVTVF9IT1NUO1xuICBsZXQgcG9ydCA9IGRlZmF1bHRDYXBzWydhcHBpdW06cG9ydCddO1xuICBjb25zdCBjbGFzc05hbWUgPSBEcml2ZXJDbGFzcy5uYW1lIHx8ICcodW5rbm93biBkcml2ZXIpJztcblxuICBkZXNjcmliZShgQmFzZURyaXZlciBFMkUgKGFzICR7Y2xhc3NOYW1lfSlgLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGJhc2VTZXJ2ZXIsIGQ7XG4gICAgLyoqXG4gICAgICogVGhpcyBVUkwgY3JlYXRlcyBhIG5ldyBzZXNzaW9uXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKiovXG4gICAgbGV0IG5ld1Nlc3Npb25VUkw7XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgVVJMIHdpdGggYmFzZSBob3N0L3BvcnQuIFN1cHBseSBgc2Vzc2lvbmAgYW5kIGBwYXRobmFtZWBcbiAgICAgKiBAdHlwZSB7Xy5DdXJyaWVkRnVuY3Rpb24yPHN0cmluZyxzdHJpbmcsc3RyaW5nPn1cbiAgICAgKi9cbiAgICBsZXQgY3JlYXRlQXBwaXVtVGVzdFVSTDtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBVUkwgd2l0aCB0aGUgZ2l2ZW4gc2Vzc2lvbiBJRCBhbmQgYSBibGFuayBwYXRobmFtZTtcbiAgICAgKiBlLmcuLCBgaHR0cDovL2Zvby5iYXI6MTIzL3Nlc3Npb24vPHNlc3Npb24taWQ+YFxuICAgICAqICBAdHlwZSB7Xy5DdXJyaWVkRnVuY3Rpb24xPHN0cmluZyxzdHJpbmc+fVxuICAgICAqL1xuICAgIGxldCBjcmVhdGVTZXNzaW9uVVJMO1xuXG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHBvcnQgPSBwb3J0ID8/IChhd2FpdCBnZXRUZXN0UG9ydCgpKTtcbiAgICAgIGRlZmF1bHRDYXBzID0gey4uLmRlZmF1bHRDYXBzLCAnYXBwaXVtOnBvcnQnOiBwb3J0fTtcbiAgICAgIGQgPSBuZXcgRHJpdmVyQ2xhc3Moe3BvcnQsIGFkZHJlc3N9KTtcbiAgICAgIGJhc2VTZXJ2ZXIgPSBhd2FpdCBzZXJ2ZXIoe1xuICAgICAgICByb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb246IHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbihkKSxcbiAgICAgICAgcG9ydCxcbiAgICAgICAgaG9zdG5hbWU6IFRFU1RfSE9TVCxcbiAgICAgIH0pO1xuICAgICAgY3JlYXRlQXBwaXVtVGVzdFVSTCA9IGNyZWF0ZUFwcGl1bVVSTChhZGRyZXNzLCBwb3J0KTtcbiAgICAgIG5ld1Nlc3Npb25VUkwgPSBjcmVhdGVBcHBpdW1UZXN0VVJMKCcnLCAnc2Vzc2lvbicpO1xuICAgICAgY3JlYXRlU2Vzc2lvblVSTCA9IGNyZWF0ZUFwcGl1bVRlc3RVUkwoXywgJycpO1xuICAgIH0pO1xuXG4gICAgYWZ0ZXIoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYmFzZVNlcnZlci5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gc3RhcnRTZXNzaW9uKGNhcHMpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICB1cmw6IG5ld1Nlc3Npb25VUkwsXG4gICAgICAgICAgbWV0aG9kOiBQT1NULFxuICAgICAgICAgIGRhdGE6IHtjYXBhYmlsaXRpZXM6IHthbHdheXNNYXRjaDogY2FwcywgZmlyc3RNYXRjaDogW3t9XX19LFxuICAgICAgICB9KVxuICAgICAgKS5kYXRhLnZhbHVlO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGVuZFNlc3Npb24oaWQpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICB1cmw6IGNyZWF0ZVNlc3Npb25VUkwoaWQpLFxuICAgICAgICAgIG1ldGhvZDogREVMRVRFLFxuICAgICAgICAgIHZhbGlkYXRlU3RhdHVzOiBudWxsLFxuICAgICAgICB9KVxuICAgICAgKS5kYXRhLnZhbHVlO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIGdldFNlc3Npb24oaWQpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICB1cmw6IGNyZWF0ZVNlc3Npb25VUkwoaWQpLFxuICAgICAgICB9KVxuICAgICAgKS5kYXRhLnZhbHVlO1xuICAgIH1cblxuICAgIGRlc2NyaWJlKCdzZXNzaW9uIGhhbmRsaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCBoYW5kbGUgaWRlbXBvdGVuY3kgd2hpbGUgY3JlYXRpbmcgc2Vzc2lvbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHNlc3Npb25JZHMgPSBbXTtcbiAgICAgICAgbGV0IHRpbWVzID0gMDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIGNvbnN0IHtzZXNzaW9uSWR9ID0gKFxuICAgICAgICAgICAgYXdhaXQgYXhpb3Moe1xuICAgICAgICAgICAgICB1cmw6IG5ld1Nlc3Npb25VUkwsXG4gICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAnWC1JZGVtcG90ZW5jeS1LZXknOiAnMTIzNDU2JyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgbWV0aG9kOiBQT1NULFxuICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiB7YWx3YXlzTWF0Y2g6IGRlZmF1bHRDYXBzLCBmaXJzdE1hdGNoOiBbe31dfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgc2ltcGxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgcmVzb2x2ZVdpdGhGdWxsUmVzcG9uc2U6IHRydWUsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICkuZGF0YS52YWx1ZTtcblxuICAgICAgICAgIHNlc3Npb25JZHMucHVzaChzZXNzaW9uSWQpO1xuICAgICAgICAgIHRpbWVzKys7XG4gICAgICAgIH0gd2hpbGUgKHRpbWVzIDwgMik7XG4gICAgICAgIF8udW5pcShzZXNzaW9uSWRzKS5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIGNvbnN0IHtzdGF0dXMsIGRhdGF9ID0gYXdhaXQgYXhpb3Moe1xuICAgICAgICAgIHVybDogY3JlYXRlU2Vzc2lvblVSTChzZXNzaW9uSWRzWzBdKSxcbiAgICAgICAgICBtZXRob2Q6IERFTEVURSxcbiAgICAgICAgfSk7XG4gICAgICAgIHN0YXR1cy5zaG91bGQuZXF1YWwoMjAwKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKGRhdGEudmFsdWUsIG51bGwpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgaGFuZGxlIGlkZW1wb3RlbmN5IHdoaWxlIGNyZWF0aW5nIHBhcmFsbGVsIHNlc3Npb25zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCByZXFzID0gW107XG4gICAgICAgIGxldCB0aW1lcyA9IDA7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICByZXFzLnB1c2goXG4gICAgICAgICAgICBheGlvcyh7XG4gICAgICAgICAgICAgIHVybDogbmV3U2Vzc2lvblVSTCxcbiAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICdYLUlkZW1wb3RlbmN5LUtleSc6ICcxMjM0NScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG1ldGhvZDogUE9TVCxcbiAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGNhcGFiaWxpdGllczoge2Fsd2F5c01hdGNoOiBkZWZhdWx0Q2FwcywgZmlyc3RNYXRjaDogW3t9XX0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICk7XG4gICAgICAgICAgdGltZXMrKztcbiAgICAgICAgfSB3aGlsZSAodGltZXMgPCAyKTtcbiAgICAgICAgY29uc3Qgc2Vzc2lvbklkcyA9IChhd2FpdCBCLmFsbChyZXFzKSkubWFwKCh4KSA9PiB4LmRhdGEudmFsdWUuc2Vzc2lvbklkKTtcbiAgICAgICAgXy51bmlxKHNlc3Npb25JZHMpLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgY29uc3Qge3N0YXR1cywgZGF0YX0gPSBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgdXJsOiBjcmVhdGVTZXNzaW9uVVJMKHNlc3Npb25JZHNbMF0pLFxuICAgICAgICAgIG1ldGhvZDogREVMRVRFLFxuICAgICAgICB9KTtcbiAgICAgICAgc3RhdHVzLnNob3VsZC5lcXVhbCgyMDApO1xuICAgICAgICBzaG91bGQuZXF1YWwoZGF0YS52YWx1ZSwgbnVsbCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBjcmVhdGUgc2Vzc2lvbiBhbmQgcmV0cmlldmUgYSBzZXNzaW9uIGlkLCB0aGVuIGRlbGV0ZSBpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IHtzdGF0dXMsIGRhdGF9ID0gYXdhaXQgYXhpb3Moe1xuICAgICAgICAgIHVybDogbmV3U2Vzc2lvblVSTCxcbiAgICAgICAgICBtZXRob2Q6IFBPU1QsXG4gICAgICAgICAgZGF0YToge2NhcGFiaWxpdGllczoge2Fsd2F5c01hdGNoOiBkZWZhdWx0Q2FwcywgZmlyc3RNYXRjaDogW3t9XX19LFxuICAgICAgICB9KTtcblxuICAgICAgICBzdGF0dXMuc2hvdWxkLmVxdWFsKDIwMCk7XG4gICAgICAgIHNob3VsZC5leGlzdChkYXRhLnZhbHVlLnNlc3Npb25JZCk7XG4gICAgICAgIGRhdGEudmFsdWUuY2FwYWJpbGl0aWVzLnBsYXRmb3JtTmFtZS5zaG91bGQuZXF1YWwoZGVmYXVsdENhcHMucGxhdGZvcm1OYW1lKTtcbiAgICAgICAgZGF0YS52YWx1ZS5jYXBhYmlsaXRpZXMuZGV2aWNlTmFtZS5zaG91bGQuZXF1YWwoZGVmYXVsdENhcHNbJ2FwcGl1bTpkZXZpY2VOYW1lJ10pO1xuXG4gICAgICAgICh7c3RhdHVzLCBkYXRhfSA9IGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICB1cmw6IGNyZWF0ZVNlc3Npb25VUkwoZC5zZXNzaW9uSWQpLFxuICAgICAgICAgIG1ldGhvZDogREVMRVRFLFxuICAgICAgICB9KSk7XG5cbiAgICAgICAgc3RhdHVzLnNob3VsZC5lcXVhbCgyMDApO1xuICAgICAgICBzaG91bGQuZXF1YWwoZGF0YS52YWx1ZSwgbnVsbCk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0LnNraXAoJ3Nob3VsZCB0aHJvdyBOWUkgZm9yIGNvbW1hbmRzIG5vdCBpbXBsZW1lbnRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHt9KTtcblxuICAgIGRlc2NyaWJlKCdjb21tYW5kIHRpbWVvdXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IG9yaWdpbmFsRmluZEVsZW1lbnQsIG9yaWdpbmFsRmluZEVsZW1lbnRzO1xuXG4gICAgICBhc3luYyBmdW5jdGlvbiBzdGFydFRpbWVvdXRTZXNzaW9uKHRpbWVvdXQpIHtcbiAgICAgICAgY29uc3QgY2FwcyA9IF8uY2xvbmVEZWVwKGRlZmF1bHRDYXBzKTtcbiAgICAgICAgY2Fwc1snYXBwaXVtOm5ld0NvbW1hbmRUaW1lb3V0J10gPSB0aW1lb3V0O1xuICAgICAgICByZXR1cm4gYXdhaXQgc3RhcnRTZXNzaW9uKGNhcHMpO1xuICAgICAgfVxuXG4gICAgICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgICAgICBvcmlnaW5hbEZpbmRFbGVtZW50ID0gZC5maW5kRWxlbWVudDtcbiAgICAgICAgZC5maW5kRWxlbWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gJ2Zvbyc7XG4gICAgICAgIH0uYmluZChkKTtcblxuICAgICAgICBvcmlnaW5hbEZpbmRFbGVtZW50cyA9IGQuZmluZEVsZW1lbnRzO1xuICAgICAgICBkLmZpbmRFbGVtZW50cyA9IGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBhd2FpdCBCLmRlbGF5KDIwMCk7XG4gICAgICAgICAgcmV0dXJuIFsnZm9vJ107XG4gICAgICAgIH0uYmluZChkKTtcbiAgICAgIH0pO1xuXG4gICAgICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQuZmluZEVsZW1lbnQgPSBvcmlnaW5hbEZpbmRFbGVtZW50O1xuICAgICAgICBkLmZpbmRFbGVtZW50cyA9IG9yaWdpbmFsRmluZEVsZW1lbnRzO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgc2V0IGEgZGVmYXVsdCBjb21tYW5kVGltZW91dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IG5ld1Nlc3Npb24gPSBhd2FpdCBzdGFydFRpbWVvdXRTZXNzaW9uKCk7XG4gICAgICAgIGQubmV3Q29tbWFuZFRpbWVvdXRNcy5zaG91bGQuYmUuYWJvdmUoMCk7XG4gICAgICAgIGF3YWl0IGVuZFNlc3Npb24obmV3U2Vzc2lvbi5zZXNzaW9uSWQpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdGltZW91dCBvbiBjb21tYW5kcyB1c2luZyBjb21tYW5kVGltZW91dCBjYXAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjI1KTtcbiAgICAgICAgLy8gWFhYOiByYWNlIGNvbmRpdGlvbjogd2UgbXVzdCBidWlsZCB0aGlzIFVSTCBiZWZvcmUgLi4uc29tZXRoaW5nIGhhcHBlbnMuLi5cbiAgICAgICAgLy8gd2hpY2ggY2F1c2VzIGBkLnNlc3Npb25JZGAgdG8gYmUgbWlzc2luZ1xuICAgICAgICBsZXQgc2Vzc2lvblVSTCA9IGNyZWF0ZVNlc3Npb25VUkwoZC5zZXNzaW9uSWQpO1xuICAgICAgICBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgdXJsOiBjcmVhdGVBcHBpdW1UZXN0VVJMKGQuc2Vzc2lvbklkLCAnZWxlbWVudCcpLFxuICAgICAgICAgIG1ldGhvZDogUE9TVCxcbiAgICAgICAgICBkYXRhOiB7dXNpbmc6ICduYW1lJywgdmFsdWU6ICdmb28nfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IEIuZGVsYXkoNDAwKTtcbiAgICAgICAgY29uc3Qge2RhdGF9ID0gYXdhaXQgYXhpb3Moe1xuICAgICAgICAgIHVybDogc2Vzc2lvblVSTCxcbiAgICAgICAgICB2YWxpZGF0ZVN0YXR1czogbnVsbCxcbiAgICAgICAgfSk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkYXRhLnZhbHVlLmVycm9yLCAnaW52YWxpZCBzZXNzaW9uIGlkJyk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlc3AuZXJyb3IsICdpbnZhbGlkIHNlc3Npb24gaWQnKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IHdpdGggY29tbWFuZFRpbWVvdXQgb2YgZmFsc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjEpO1xuICAgICAgICBsZXQgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCB7dmFsdWV9ID0gKFxuICAgICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICAgIHVybDogY3JlYXRlQXBwaXVtVGVzdFVSTChkLnNlc3Npb25JZCwgJ2VsZW1lbnRzJyksXG4gICAgICAgICAgICBtZXRob2Q6IFBPU1QsXG4gICAgICAgICAgICBkYXRhOiB7dXNpbmc6ICduYW1lJywgdmFsdWU6ICdmb28nfSxcbiAgICAgICAgICB9KVxuICAgICAgICApLmRhdGE7XG4gICAgICAgIChEYXRlLm5vdygpIC0gc3RhcnQpLnNob3VsZC5iZS5hYm92ZSgxNTApO1xuICAgICAgICB2YWx1ZS5zaG91bGQuZXFsKFsnZm9vJ10pO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IHdpdGggY29tbWFuZFRpbWVvdXQgb2YgMCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZC5uZXdDb21tYW5kVGltZW91dE1zID0gMjtcbiAgICAgICAgbGV0IG5ld1Nlc3Npb24gPSBhd2FpdCBzdGFydFRpbWVvdXRTZXNzaW9uKDApO1xuXG4gICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICB1cmw6IGNyZWF0ZUFwcGl1bVRlc3RVUkwoZC5zZXNzaW9uSWQsICdlbGVtZW50JyksXG4gICAgICAgICAgbWV0aG9kOiBQT1NULFxuICAgICAgICAgIGRhdGE6IHt1c2luZzogJ25hbWUnLCB2YWx1ZTogJ2Zvbyd9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgQi5kZWxheSg0MDApO1xuICAgICAgICBjb25zdCB7dmFsdWV9ID0gKFxuICAgICAgICAgIGF3YWl0IGF4aW9zKHtcbiAgICAgICAgICAgIHVybDogY3JlYXRlU2Vzc2lvblVSTChkLnNlc3Npb25JZCksXG4gICAgICAgICAgfSlcbiAgICAgICAgKS5kYXRhO1xuICAgICAgICB2YWx1ZS5wbGF0Zm9ybU5hbWUuc2hvdWxkLmVxdWFsKGRlZmF1bHRDYXBzLnBsYXRmb3JtTmFtZSk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLmVxdWFsKHJlc3AsIG51bGwpO1xuXG4gICAgICAgIGQubmV3Q29tbWFuZFRpbWVvdXRNcyA9IDYwICogMTAwMDtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IGlmIGl0cyBqdXN0IHRoZSBjb21tYW5kIHRha2luZyBhd2hpbGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjI1KTtcbiAgICAgICAgLy8gWFhYOiByYWNlIGNvbmRpdGlvbjogd2UgbXVzdCBidWlsZCB0aGlzIFVSTCBiZWZvcmUgLi4uc29tZXRoaW5nIGhhcHBlbnMuLi5cbiAgICAgICAgLy8gd2hpY2ggY2F1c2VzIGBkLnNlc3Npb25JZGAgdG8gYmUgbWlzc2luZ1xuICAgICAgICBsZXQgc2Vzc2lvblVSTCA9IGNyZWF0ZVNlc3Npb25VUkwoZC5zZXNzaW9uSWQpO1xuICAgICAgICBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgdXJsOiBjcmVhdGVBcHBpdW1UZXN0VVJMKGQuc2Vzc2lvbklkLCAnZWxlbWVudCcpLFxuICAgICAgICAgIG1ldGhvZDogUE9TVCxcbiAgICAgICAgICBkYXRhOiB7dXNpbmc6ICduYW1lJywgdmFsdWU6ICdmb28nfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IEIuZGVsYXkoNDAwKTtcbiAgICAgICAgY29uc3Qge3ZhbHVlfSA9IChcbiAgICAgICAgICBhd2FpdCBheGlvcyh7XG4gICAgICAgICAgICB1cmw6IHNlc3Npb25VUkwsXG4gICAgICAgICAgICB2YWxpZGF0ZVN0YXR1czogbnVsbCxcbiAgICAgICAgICB9KVxuICAgICAgICApLmRhdGE7XG4gICAgICAgIHZhbHVlLmVycm9yLnNob3VsZC5lcXVhbCgnaW52YWxpZCBzZXNzaW9uIGlkJyk7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgcmVzcC5lcnJvci5zaG91bGQuZXF1YWwoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbm90IGhhdmUgYSB0aW1lciBydW5uaW5nIGJlZm9yZSBvciBhZnRlciBhIHNlc3Npb24nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNob3VsZC5ub3QuZXhpc3QoZC5ub0NvbW1hbmRUaW1lcik7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjI1KTtcbiAgICAgICAgbmV3U2Vzc2lvbi5zZXNzaW9uSWQuc2hvdWxkLmVxdWFsKGQuc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KGQubm9Db21tYW5kVGltZXIpO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLm5vdC5leGlzdChkLm5vQ29tbWFuZFRpbWVyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3NldHRpbmdzIGFwaScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQuc2V0dGluZ3MgPSBuZXcgRGV2aWNlU2V0dGluZ3Moe2lnbm9yZVVuaW1wb3J0YW50Vmlld3M6IGZhbHNlfSk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBnZXQgc2V0dGluZ3Mgb2JqZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBkLnNldHRpbmdzLmdldFNldHRpbmdzKCkuaWdub3JlVW5pbXBvcnRhbnRWaWV3cy5zaG91bGQuYmUuZmFsc2U7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgbm90IHJlamVjdCB3aGVuIGB1cGRhdGVTZXR0aW5nc2AgbWV0aG9kIGlzIG5vdCBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgZC5zZXR0aW5ncy51cGRhdGUoe2lnbm9yZVVuaW1wb3J0YW50Vmlld3M6IHRydWV9KS5zaG91bGQubm90LmJlLnJlamVjdGVkO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIHJlamVjdCBmb3IgaW52YWxpZCB1cGRhdGUgb2JqZWN0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBhd2FpdCBkLnNldHRpbmdzLnVwZGF0ZSgnaW52YWxpZCBqc29uJykuc2hvdWxkLmV2ZW50dWFsbHkuYmUucmVqZWN0ZWRXaXRoKCdKU09OJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCd1bmV4cGVjdGVkIGV4aXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCByZWplY3QgYSBjdXJyZW50IGNvbW1hbmQgd2hlbiB0aGUgZHJpdmVyIGNyYXNoZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQuX29sZEdldFN0YXR1cyA9IGQuZ2V0U3RhdHVzO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGQuZ2V0U3RhdHVzID0gYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYXdhaXQgQi5kZWxheSg1MDAwKTtcbiAgICAgICAgICB9LmJpbmQoZCk7XG4gICAgICAgICAgY29uc3QgcmVxUHJvbWlzZSA9IGF4aW9zKHtcbiAgICAgICAgICAgIHVybDogY3JlYXRlQXBwaXVtVGVzdFVSTCgnJywgJ3N0YXR1cycpLFxuICAgICAgICAgICAgdmFsaWRhdGVTdGF0dXM6IG51bGwsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgdGhlIHJlcXVlc3QgZ2V0cyB0byB0aGUgc2VydmVyIGJlZm9yZSBvdXIgc2h1dGRvd25cbiAgICAgICAgICBhd2FpdCBCLmRlbGF5KDEwMCk7XG4gICAgICAgICAgY29uc3Qgc2h1dGRvd25FdmVudFByb21pc2UgPSBuZXcgQigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICAgIHJlamVjdChcbiAgICAgICAgICAgICAgICAgIG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgJ29uVW5leHBlY3RlZFNodXRkb3duIGV2ZW50IGlzIGV4cGVjdGVkIHRvIGJlIGZpcmVkIHdpdGhpbiA1IHNlY29uZHMgdGltZW91dCdcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICA1MDAwXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZC5vblVuZXhwZWN0ZWRTaHV0ZG93bihyZXNvbHZlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkLnN0YXJ0VW5leHBlY3RlZFNodXRkb3duKG5ldyBFcnJvcignQ3Jhc2h5dGltZXMnKSk7XG4gICAgICAgICAgY29uc3Qge3ZhbHVlfSA9IChhd2FpdCByZXFQcm9taXNlKS5kYXRhO1xuICAgICAgICAgIHZhbHVlLm1lc3NhZ2Uuc2hvdWxkLmNvbnRhaW4oJ0NyYXNoeXRpbWVzJyk7XG4gICAgICAgICAgYXdhaXQgc2h1dGRvd25FdmVudFByb21pc2U7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgZC5nZXRTdGF0dXMgPSBkLl9vbGRHZXRTdGF0dXM7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ2V2ZW50IHRpbWluZ3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnc2hvdWxkIG5vdCBhZGQgdGltaW5ncyBpZiBub3QgdXNpbmcgb3B0LWluIGNhcCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IHN0YXJ0U2Vzc2lvbihkZWZhdWx0Q2Fwcyk7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGdldFNlc3Npb24oc2Vzc2lvbi5zZXNzaW9uSWQpO1xuICAgICAgICBzaG91bGQubm90LmV4aXN0KHJlcy5ldmVudHMpO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKHNlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgIH0pO1xuICAgICAgaXQoJ3Nob3VsZCBhZGQgc3RhcnQgc2Vzc2lvbiB0aW1pbmdzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjYXBzID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdENhcHMsIHtcbiAgICAgICAgICAnYXBwaXVtOmV2ZW50VGltaW5ncyc6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgc3RhcnRTZXNzaW9uKGNhcHMpO1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBnZXRTZXNzaW9uKHNlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHJlcy5ldmVudHMpO1xuICAgICAgICBzaG91bGQuZXhpc3QocmVzLmV2ZW50cy5uZXdTZXNzaW9uUmVxdWVzdGVkKTtcbiAgICAgICAgc2hvdWxkLmV4aXN0KHJlcy5ldmVudHMubmV3U2Vzc2lvblN0YXJ0ZWQpO1xuICAgICAgICByZXMuZXZlbnRzLm5ld1Nlc3Npb25SZXF1ZXN0ZWRbMF0uc2hvdWxkLmJlLmEoJ251bWJlcicpO1xuICAgICAgICByZXMuZXZlbnRzLm5ld1Nlc3Npb25TdGFydGVkWzBdLnNob3VsZC5iZS5hKCdudW1iZXInKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihzZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGlmIChEcml2ZXJDbGFzcyA9PT0gQmFzZURyaXZlcikge1xuICAgICAgLy8gb25seSBydW4gdGhpcyB0ZXN0IG9uIGJhc2Vkcml2ZXIsIG5vdCBvdGhlciBkcml2ZXJzIHdoaWNoIGFsc28gdXNlIHRoZXNlIHRlc3RzLCBzaW5jZSB3ZVxuICAgICAgLy8gZG9uJ3Qgd2FudCB0aGVtIHRvIHRyeSBhbmQgc3RhcnQgc2Vzc2lvbnMgd2l0aCB0aGVzZSByYW5kb20gY2FwYWJpbGl0aWVzIHRoYXQgYXJlXG4gICAgICAvLyBuZWNlc3NhcnkgdG8gdGVzdCB0aGUgYXBwaXVtIG9wdGlvbnMgbG9naWNcbiAgICAgIGRlc2NyaWJlKCdzcGVjaWFsIGFwcGl1bTpvcHRpb25zIGNhcGFiaWxpdHknLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBzdGFydCBhIHNlc3Npb24gd2l0aCBjYXBzIGhlbGQgaW4gYXBwaXVtOm9wdGlvbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgY29uc3QgcmV0ID0gYXdhaXQgc3RhcnRTZXNzaW9uKHtcbiAgICAgICAgICAgIHBsYXRmb3JtTmFtZTogJ2lPUycsXG4gICAgICAgICAgICBbUFJFRklYRURfQVBQSVVNX09QVFNfQ0FQXToge1xuICAgICAgICAgICAgICBwbGF0Zm9ybVZlcnNpb246ICcxMS40JyxcbiAgICAgICAgICAgICAgJ2FwcGl1bTpkZXZpY2VOYW1lJzogJ2lQaG9uZSAxMScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGQub3B0cy5wbGF0Zm9ybVZlcnNpb24uc2hvdWxkLmVxbCgnMTEuNCcpO1xuICAgICAgICAgIGQub3B0cy5kZXZpY2VOYW1lLnNob3VsZC5lcWwoJ2lQaG9uZSAxMScpO1xuICAgICAgICAgIGF3YWl0IGVuZFNlc3Npb24ocmV0LnNlc3Npb25JZCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9KTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgYmFzZURyaXZlckUyRVRlc3RzO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBLE1BQU07RUFBQ0EsSUFBRDtFQUFPQztBQUFQLElBQWlCQyxnQkFBdkI7O0FBRUEsU0FBU0Msa0JBQVQsQ0FBNEJDLFdBQTVCLEVBQXlDQyxXQUFXLEdBQUcsRUFBdkQsRUFBMkQ7RUFBQTs7RUFDekQsSUFBSUMsT0FBTywyQkFBR0QsV0FBVyxD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