oxygen-cli 1.37.8 → 1.38.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.
@@ -0,0 +1,376 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ require("source-map-support/register");
9
+
10
+ var _ReporterBase = _interopRequireDefault(require("../reporter/ReporterBase"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ const RPClient = require('@oxygenhq/rp-client-javascript');
15
+
16
+ const LAUNCH_MODES = {
17
+ DEFAULT: 'DEFAULT',
18
+ DEBUG: 'DEBUG'
19
+ };
20
+ const TEST_ITEM_TYPES = {
21
+ SUITE: 'SUITE',
22
+ TEST: 'TEST',
23
+ STEP: 'STEP'
24
+ };
25
+ const MAX_NAME_LENGTH = 128;
26
+
27
+ class ReportPortalReporter extends _ReporterBase.default {
28
+ constructor(options, reporterOpts, aggregator) {
29
+ super(options);
30
+ this.reporterOpts = reporterOpts || options.rp;
31
+ this.reportSteps = reporterOpts.reportSteps || false;
32
+ this.reportLogs = reporterOpts.reportLogs || false;
33
+ this.cbSuiteToRpIdHash = {};
34
+ this.cbCaseToRpIdHash = {};
35
+ this.cbStepToRpIdHash = {};
36
+
37
+ if (!this.reporterOpts || !this.reporterOpts.apiKey || !this.reporterOpts.endpoint || !this.reporterOpts.project) {
38
+ throw new Error('ReportPortal options are missing in oxygen.conf file.');
39
+ }
40
+
41
+ this.aggregator = aggregator;
42
+ this.rpClient = new RPClient({
43
+ launch: this.reporterOpts.launch || this.options.name,
44
+ ...this.reporterOpts
45
+ });
46
+ }
47
+
48
+ async init() {
49
+ try {
50
+ await this.rpClient.checkConnect();
51
+ } catch (e) {
52
+ throw new Error(`RP - Error connecting to the server: ${e.message}`);
53
+ }
54
+ }
55
+
56
+ async generate(results) {}
57
+
58
+ async onRunnerStart({
59
+ rid,
60
+ opts,
61
+ caps
62
+ }) {
63
+ const {
64
+ tempId,
65
+ promise
66
+ } = this.rpClient.startLaunch({
67
+ mode: this.reporterOpts.mode || LAUNCH_MODES.DEFAULT,
68
+ debug: false
69
+ });
70
+ this.tempLaunchId = tempId;
71
+ promise.then(response => {}, error => {
72
+ console.dir(`RP - Error at the start of launch: ${error}`);
73
+ });
74
+ }
75
+
76
+ async onRunnerEnd({
77
+ rid,
78
+ result
79
+ }) {
80
+ const {
81
+ promise
82
+ } = await this.rpClient.finishLaunch(this.tempLaunchId, {
83
+ status: result.status.toLowerCase()
84
+ });
85
+
86
+ try {
87
+ await this.promiseWithTimeout(promise);
88
+ } catch (e) {
89
+ console.dir(`RP - Failed to end launch: ${e}`);
90
+ }
91
+ }
92
+
93
+ async onSuiteStart({
94
+ rid,
95
+ suiteId,
96
+ suite: suiteDef
97
+ }) {
98
+ const startTestItemReq = {
99
+ name: suiteDef.name || this.options.name,
100
+ type: TEST_ITEM_TYPES.SUITE
101
+ };
102
+ const {
103
+ tempId,
104
+ promise
105
+ } = this.rpClient.startTestItem(startTestItemReq, this.tempLaunchId);
106
+ this.cbSuiteToRpIdHash[suiteId] = tempId;
107
+
108
+ try {
109
+ await this.promiseWithTimeout(promise);
110
+ } catch (e) {
111
+ console.dir(`RP - Failed to start suite item: ${e}`);
112
+ }
113
+ }
114
+
115
+ async onSuiteEnd({
116
+ rid,
117
+ suiteId,
118
+ result
119
+ }) {
120
+ if (!this.cbSuiteToRpIdHash[suiteId]) {
121
+ return;
122
+ }
123
+
124
+ const rpSuiteId = this.cbSuiteToRpIdHash[suiteId];
125
+ const finishTestItemReq = {
126
+ status: result.status.toLowerCase()
127
+ };
128
+ const {
129
+ promise
130
+ } = this.rpClient.finishTestItem(rpSuiteId, finishTestItemReq);
131
+
132
+ try {
133
+ await this.promiseWithTimeout(promise);
134
+ } catch (e) {
135
+ console.dir(`RP - Failed to finish suite item: ${e}`);
136
+ }
137
+ }
138
+
139
+ async onCaseStart({
140
+ rid,
141
+ suiteId,
142
+ caseId,
143
+ 'case': caseDef
144
+ }) {
145
+ const startTestItemReq = {
146
+ name: caseDef.name,
147
+ type: TEST_ITEM_TYPES.TEST,
148
+ codeRef: caseDef.path
149
+ };
150
+ const rpSuiteId = this.cbSuiteToRpIdHash[suiteId];
151
+
152
+ if (!rpSuiteId) {
153
+ return;
154
+ }
155
+
156
+ const {
157
+ tempId,
158
+ promise
159
+ } = this.rpClient.startTestItem(startTestItemReq, this.tempLaunchId, rpSuiteId);
160
+ this.cbCaseToRpIdHash[caseId] = tempId;
161
+
162
+ try {
163
+ await this.promiseWithTimeout(promise);
164
+ } catch (e) {
165
+ console.dir(`RP - Failed to start test item: ${e}`);
166
+ }
167
+ }
168
+
169
+ async onCaseEnd({
170
+ rid,
171
+ suiteId,
172
+ caseId,
173
+ result
174
+ }) {
175
+ const rpTestId = this.cbCaseToRpIdHash[caseId];
176
+
177
+ if (!rpTestId) {
178
+ return;
179
+ }
180
+
181
+ const status = result.status.toLowerCase();
182
+
183
+ if (status === 'failed' && result.failure) {
184
+ const rpFile = result.screenshot ? {
185
+ name: 'screenshot',
186
+ type: 'image/png',
187
+ content: result.screenshot
188
+ } : undefined;
189
+ const logReq = {
190
+ message: result.failure.message,
191
+ level: 'error'
192
+ };
193
+ const {
194
+ promise: sendLogPromise
195
+ } = rpFile ? this.rpClient.sendLogWithFile(rpTestId, logReq, rpFile) : this.rpClient.sendLog(rpTestId, logReq);
196
+ await this.promiseWithTimeout(sendLogPromise);
197
+ }
198
+
199
+ const finishTestItemReq = {
200
+ status: result.status.toLowerCase()
201
+ };
202
+ const {
203
+ promise
204
+ } = this.rpClient.finishTestItem(rpTestId, finishTestItemReq);
205
+
206
+ try {
207
+ await this.promiseWithTimeout(promise);
208
+ } catch (e) {
209
+ console.dir(`RP - Failed to finish test item: ${e}`);
210
+ }
211
+ }
212
+
213
+ async onStepStart({
214
+ rid,
215
+ caseId,
216
+ step
217
+ }) {
218
+ if (!this.reportSteps) {
219
+ return;
220
+ }
221
+
222
+ const rpCaseId = this.cbCaseToRpIdHash[caseId];
223
+
224
+ if (!rpCaseId) {
225
+ return;
226
+ }
227
+
228
+ const stepName = this._getStepName(step);
229
+
230
+ const startTestItemReq = {
231
+ name: stepName,
232
+ type: TEST_ITEM_TYPES.STEP,
233
+ codeRef: step.location,
234
+ testCaseId: rpCaseId,
235
+ hasStats: false
236
+ };
237
+ const {
238
+ tempId,
239
+ promise
240
+ } = this.rpClient.startTestItem(startTestItemReq, this.tempLaunchId, rpCaseId);
241
+ this.cbStepToRpIdHash[step.id] = tempId;
242
+
243
+ try {
244
+ await this.promiseWithTimeout(promise);
245
+ } catch (e) {
246
+ console.dir(`RP - Failed to start step item: ${e}`);
247
+ }
248
+ }
249
+
250
+ async onStepEnd({
251
+ rid,
252
+ step: result
253
+ }) {
254
+ if (!this.reportSteps) {
255
+ return;
256
+ }
257
+
258
+ const rpStepId = this.cbStepToRpIdHash[result.id];
259
+
260
+ if (!rpStepId) {
261
+ return;
262
+ }
263
+
264
+ const status = result.status.toLowerCase();
265
+
266
+ if (status === 'failed' && result.failure) {
267
+ const rpFile = result.screenshot ? {
268
+ name: 'screenshot',
269
+ type: 'image/png',
270
+ content: result.screenshot
271
+ } : undefined;
272
+ const logReq = {
273
+ message: result.failure.message,
274
+ level: 'error',
275
+ file: rpFile
276
+ };
277
+ const {
278
+ promise: sendLogPromise
279
+ } = this.rpClient.sendLog(rpStepId, logReq, rpFile);
280
+ await this.promiseWithTimeout(sendLogPromise);
281
+ }
282
+
283
+ const finishTestItemReq = {
284
+ status: result.status.toLowerCase()
285
+ };
286
+ const {
287
+ promise
288
+ } = this.rpClient.finishTestItem(rpStepId, finishTestItemReq);
289
+
290
+ try {
291
+ await this.promiseWithTimeout(promise);
292
+ } catch (e) {
293
+ console.dir(`RP - Failed to finish step item: ${e}`);
294
+ }
295
+ }
296
+
297
+ async onLog({
298
+ suiteId,
299
+ caseId,
300
+ stepId,
301
+ level,
302
+ msg,
303
+ time,
304
+ src
305
+ }) {
306
+ if (!this.reportLogs) {
307
+ return;
308
+ }
309
+
310
+ if (!this.tempLaunchId) {
311
+ return;
312
+ }
313
+
314
+ const rpParentId = stepId ? this.cbStepToRpIdHash[stepId] : caseId ? this.cbCaseToRpIdHash[caseId] : suiteId ? this.cbSuiteToRpIdHash[suiteId] : undefined;
315
+
316
+ const rpLevel = this._getRpLevel(level);
317
+
318
+ const logReq = {
319
+ message: msg,
320
+ level: rpLevel,
321
+ time: time
322
+ };
323
+ const {
324
+ promise
325
+ } = this.rpClient.sendLog(rpParentId || this.tempLaunchId, logReq);
326
+
327
+ try {
328
+ await this.promiseWithTimeout(promise);
329
+ } catch (e) {
330
+ console.dir(`RP - Failed to create log item: ${e}`);
331
+ }
332
+ }
333
+
334
+ _getRpLevel(oxLevel) {
335
+ if (oxLevel) {
336
+ return oxLevel.toLowerCase();
337
+ }
338
+
339
+ return 'info';
340
+ }
341
+
342
+ _getStepName(step) {
343
+ let name;
344
+
345
+ if (step.name === 'transaction' && step.args.length > 0) {
346
+ name = step.args[0];
347
+ } else if (step.signature) {
348
+ name = step.signature;
349
+ } else if (step.module) {
350
+ name = `${step.module}.${step.name}`;
351
+ } else {
352
+ name = step.name;
353
+ }
354
+
355
+ if (name.length > MAX_NAME_LENGTH) {
356
+ name = name.substring(0, MAX_NAME_LENGTH - 3) + '...';
357
+ }
358
+
359
+ return name;
360
+ }
361
+
362
+ promiseWithTimeout(promise, timeout = 10 * 1000) {
363
+ return new Promise((resolve, reject) => {
364
+ if (!promise || !promise.then) {
365
+ reject();
366
+ }
367
+
368
+ promise.then(resolve, reject);
369
+ setTimeout(reject, timeout);
370
+ });
371
+ }
372
+
373
+ }
374
+
375
+ exports.default = ReportPortalReporter;
376
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9veF9yZXBvcnRlcnMvcmVwb3J0ZXItcnAuanMiXSwibmFtZXMiOlsiUlBDbGllbnQiLCJyZXF1aXJlIiwiTEFVTkNIX01PREVTIiwiREVGQVVMVCIsIkRFQlVHIiwiVEVTVF9JVEVNX1RZUEVTIiwiU1VJVEUiLCJURVNUIiwiU1RFUCIsIk1BWF9OQU1FX0xFTkdUSCIsIlJlcG9ydFBvcnRhbFJlcG9ydGVyIiwiUmVwb3J0ZXJCYXNlIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwicmVwb3J0ZXJPcHRzIiwiYWdncmVnYXRvciIsInJwIiwicmVwb3J0U3RlcHMiLCJyZXBvcnRMb2dzIiwiY2JTdWl0ZVRvUnBJZEhhc2giLCJjYkNhc2VUb1JwSWRIYXNoIiwiY2JTdGVwVG9ScElkSGFzaCIsImFwaUtleSIsImVuZHBvaW50IiwicHJvamVjdCIsIkVycm9yIiwicnBDbGllbnQiLCJsYXVuY2giLCJuYW1lIiwiaW5pdCIsImNoZWNrQ29ubmVjdCIsImUiLCJtZXNzYWdlIiwiZ2VuZXJhdGUiLCJyZXN1bHRzIiwib25SdW5uZXJTdGFydCIsInJpZCIsIm9wdHMiLCJjYXBzIiwidGVtcElkIiwicHJvbWlzZSIsInN0YXJ0TGF1bmNoIiwibW9kZSIsImRlYnVnIiwidGVtcExhdW5jaElkIiwidGhlbiIsInJlc3BvbnNlIiwiZXJyb3IiLCJjb25zb2xlIiwiZGlyIiwib25SdW5uZXJFbmQiLCJyZXN1bHQiLCJmaW5pc2hMYXVuY2giLCJzdGF0dXMiLCJ0b0xvd2VyQ2FzZSIsInByb21pc2VXaXRoVGltZW91dCIsIm9uU3VpdGVTdGFydCIsInN1aXRlSWQiLCJzdWl0ZSIsInN1aXRlRGVmIiwic3RhcnRUZXN0SXRlbVJlcSIsInR5cGUiLCJzdGFydFRlc3RJdGVtIiwib25TdWl0ZUVuZCIsInJwU3VpdGVJZCIsImZpbmlzaFRlc3RJdGVtUmVxIiwiZmluaXNoVGVzdEl0ZW0iLCJvbkNhc2VTdGFydCIsImNhc2VJZCIsImNhc2VEZWYiLCJjb2RlUmVmIiwicGF0aCIsIm9uQ2FzZUVuZCIsInJwVGVzdElkIiwiZmFpbHVyZSIsInJwRmlsZSIsInNjcmVlbnNob3QiLCJjb250ZW50IiwidW5kZWZpbmVkIiwibG9nUmVxIiwibGV2ZWwiLCJzZW5kTG9nUHJvbWlzZSIsInNlbmRMb2dXaXRoRmlsZSIsInNlbmRMb2ciLCJvblN0ZXBTdGFydCIsInN0ZXAiLCJycENhc2VJZCIsInN0ZXBOYW1lIiwiX2dldFN0ZXBOYW1lIiwibG9jYXRpb24iLCJ0ZXN0Q2FzZUlkIiwiaGFzU3RhdHMiLCJpZCIsIm9uU3RlcEVuZCIsInJwU3RlcElkIiwiZmlsZSIsIm9uTG9nIiwic3RlcElkIiwibXNnIiwidGltZSIsInNyYyIsInJwUGFyZW50SWQiLCJycExldmVsIiwiX2dldFJwTGV2ZWwiLCJveExldmVsIiwiYXJncyIsImxlbmd0aCIsInNpZ25hdHVyZSIsIm1vZHVsZSIsInN1YnN0cmluZyIsInRpbWVvdXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInNldFRpbWVvdXQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQVlBOzs7O0FBQ0EsTUFBTUEsUUFBUSxHQUFHQyxPQUFPLENBQUMsZ0NBQUQsQ0FBeEI7O0FBQ0EsTUFBTUMsWUFBWSxHQUFHO0FBQ2pCQyxFQUFBQSxPQUFPLEVBQUUsU0FEUTtBQUVqQkMsRUFBQUEsS0FBSyxFQUFFO0FBRlUsQ0FBckI7QUFJQSxNQUFNQyxlQUFlLEdBQUc7QUFDcEJDLEVBQUFBLEtBQUssRUFBRSxPQURhO0FBRXBCQyxFQUFBQSxJQUFJLEVBQUUsTUFGYztBQUdwQkMsRUFBQUEsSUFBSSxFQUFFO0FBSGMsQ0FBeEI7QUFLQSxNQUFNQyxlQUFlLEdBQUcsR0FBeEI7O0FBRWUsTUFBTUMsb0JBQU4sU0FBbUNDLHFCQUFuQyxDQUFnRDtBQUMzREMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVVDLFlBQVYsRUFBd0JDLFVBQXhCLEVBQW9DO0FBQzNDLFVBQU1GLE9BQU47QUFDQSxTQUFLQyxZQUFMLEdBQW9CQSxZQUFZLElB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SyxJQUF6QixFQUErQjtBQUM3QyxXQUFPLElBQUlDLE9BQUosQ0FBWSxDQUFDQyxPQUFELEVBQVVDLE1BQVYsS0FBcUI7QUFDcEMsVUFBSSxDQUFDekUsT0FBRCxJQUFZLENBQUNBLE9BQU8sQ0FBQ0ssSUFBekIsRUFBK0I7QUFDM0JvRSxRQUFBQSxNQUFNO0FBQ1Q7O0FBQ0R6RSxNQUFBQSxPQUFPLENBQUNLLElBQVIsQ0FBYW1FLE9BQWIsRUFBc0JDLE1BQXRCO0FBQ0FDLE1BQUFBLFVBQVUsQ0FBQ0QsTUFBRCxFQUFTSCxPQUFULENBQVY7QUFDSCxLQU5NLENBQVA7QUFPSDs7QUE1UjBEIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogQ29weXJpZ2h0IChDKSAyMDE1LXByZXNlbnQgQ2xvdWRCZWF0IExpbWl0ZWRcclxuICpcclxuICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcclxuICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnlcclxuICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3JcclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cclxuICovXHJcblxyXG4vKlxyXG4gKiBPeHlnZW4gUmVwb3J0ZXIgZm9yIFJlcG9ydFBvcnRhbFxyXG4gKi9cclxuaW1wb3J0IFJlcG9ydGVyQmFzZSBmcm9tICcuLi9yZXBvcnRlci9SZXBvcnRlckJhc2UnO1xyXG5jb25zdCBSUENsaWVudCA9IHJlcXVpcmUoJ0BveHlnZW5ocS9ycC1jbGllbnQtamF2YXNjcmlwdCcpO1xyXG5jb25zdCBMQVVOQ0hfTU9ERVMgPSB7XHJcbiAgICBERUZBVUxUOiAnREVGQVVMVCcsXHJcbiAgICBERUJVRzogJ0RFQlVHJyxcclxufTtcclxuY29uc3QgVEVTVF9JVEVNX1RZUEVTID0ge1xyXG4gICAgU1VJVEU6ICdTVUlURScsXHJcbiAgICBURVNUOiAnVEVTVCcsXHJcbiAgICBTVEVQOiAnU1RFUCcsXHJcbn07XHJcbmNvbnN0IE1BWF9OQU1FX0xFTkdUSCA9IDEyODtcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlcG9ydFBvcnRhbFJlcG9ydGVyIGV4dGVuZHMgUmVwb3J0ZXJCYXNlIHtcclxuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMsIHJlcG9ydGVyT3B0cywgYWdncmVnYXRvcikge1xyXG4gICAgICAgIHN1cGVyKG9wdGlvbnMpO1xyXG4gICAgICAgIHRoaXMucmVwb3J0ZXJPcHRzID0gcmVwb3J0ZXJPcHRzIHx8IG9wdGlvbnMucnA7XHJcbiAgICAgICAgdGhpcy5yZXBvcnRTdGVwcyA9IHJlcG9ydGVyT3B0cy5yZXBvcnRTdGVwcyB8fCBmYWxzZTtcclxuICAgICAgICB0aGlzLnJlcG9ydExvZ3MgPSByZXBvcnRlck9wdHMucmVwb3J0TG9ncyB8fCBmYWxzZTtcclxuICAgICAgICB0aGlzLmNiU3VpdGVUb1JwSWRIYXNoID0ge307XHJcbiAgICAgICAgdGhpcy5jYkNhc2VUb1JwSWRIYXNoID0ge307XHJcbiAgICAgICAgdGhpcy5jYlN0ZXBUb1JwSWRIYXNoID0ge307XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAhdGhpcy5yZXBvcnRlck9wdHNcclxuICAgICAgICAgICAgfHwgIXRoaXMucmVwb3J0ZXJPcHRzLmFwaUtleVxyXG4gICAgICAgICAgICB8fCAhdGhpcy5yZXBvcnRlck9wdHMuZW5kcG9pbnRcclxuICAgICAgICAgICAgfHwgIXRoaXMucmVwb3J0ZXJPcHRzLnByb2plY3RcclxuICAgICAgICApIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSZXBvcnRQb3J0YWwgb3B0aW9ucyBhcmUgbWlzc2luZyBpbiBveHlnZW4uY29uZiBmaWxlLicpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmFnZ3JlZ2F0b3IgPSBhZ2dyZWdhdG9yO1xyXG4gICAgICAgIHRoaXMucnBDbGllbnQgPSBuZXcgUlBDbGllbnQoe1xyXG4gICAgICAgICAgICBsYXVuY2g6IHRoaXMucmVwb3J0ZXJPcHRzLmxhdW5jaCB8fCB0aGlzLm9wdGlvbnMubmFtZSxcclxuICAgICAgICAgICAgLi4udGhpcy5yZXBvcnRlck9wdHNcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBpbml0KCkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucnBDbGllbnQuY2hlY2tDb25uZWN0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUlAgLSBFcnJvciBjb25uZWN0aW5nIHRvIHRoZSBzZXJ2ZXI6ICR7ZS5tZXNzYWdlfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGFzeW5jIGdlbmVyYXRlKHJlc3VsdHMpIHtcclxuICAgIH1cclxuICAgIC8vIEV2ZW50c1xyXG4gICAgYXN5bmMgb25SdW5uZXJTdGFydCh7IHJpZCwgb3B0cywgY2FwcyB9KSB7XHJcbiAgICAgICAgY29uc3QgeyB0ZW1wSWQsIHByb21pc2UgfSA9IHRoaXMucnBDbGllbnQuc3RhcnRMYXVuY2goe1xyXG4gICAgICAgICAgICBtb2RlOiB0aGlzLnJlcG9ydGVyT3B0cy5tb2RlIHx8IExBVU5DSF9NT0RFUy5ERUZBVUxULFxyXG4gICAgICAgICAgICBkZWJ1ZzogZmFsc2UsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy50ZW1wTGF1bmNoSWQgPSB0ZW1wSWQ7XHJcbiAgICAgICAgcHJvbWlzZS50aGVuKChyZXNwb25zZSkgPT4ge1xyXG4gICAgICAgIH0sIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICBjb25zb2xlLmRpcihgUlAgLSBFcnJvciBhdCB0aGUgc3RhcnQgb2YgbGF1bmNoOiAke2Vycm9yfWApO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgYXN5bmMgb25SdW5uZXJFbmQoeyByaWQsIHJlc3VsdCB9KSB7XHJcbiAgICAgICAgLy8gYXdhaXQgdGhpcy5ycENsaWVudC5nZXRQcm9taXNlRmluaXNoQWxsSXRlbXModGhpcy50ZW1wTGF1bmNoSWQpO1xyXG4gICAgICAgIGNvbnN0IHsgcHJvbWlzZSB9ID0gYXdhaXQgdGhpcy5ycENsaWVudC5maW5pc2hMYXVuY2godGhpcy50ZW1wTGF1bmNoSWQsIHtcclxuICAgICAgICAgICAgc3RhdHVzOiByZXN1bHQuc3RhdHVzLnRvTG93ZXJDYXNlKCksXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm9taXNlV2l0aFRpbWVvdXQocHJvbWlzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZGlyKGBSUCAtIEZhaWxlZCB0byBlbmQgbGF1bmNoOiAke2V9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgYXN5bmMgb25TdWl0ZVN0YXJ0KHsgcmlkLCBzdWl0ZUlkLCBzdWl0ZTogc3VpdGVEZWYgfSkge1xyXG4gICAgICAgIGNvbnN0IHN0YXJ0VGVzdEl0ZW1SZXEgPSB7XHJcbiAgICAgICAgICAgIG5hbWU6IHN1aXRlRGVmLm5hbWUgfHwgdGhpcy5vcHRpb25zLm5hbWUsXHJcbiAgICAgICAgICAgIHR5cGU6IFRFU1RfSVRFTV9UWVBFUy5TVUlURSxcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHsgdGVtcElkLCBwcm9taXNlIH0gPSB0aGlzLnJwQ2xpZW50LnN0YXJ0VGVzdEl0ZW0oc3RhcnRUZXN0SXRlbVJlcSwgdGhpcy50ZW1wTGF1bmNoSWQpO1xyXG4gICAgICAgIHRoaXMuY2JTdWl0ZVRvUnBJZEhhc2hbc3VpdGVJZF0gPSB0ZW1wSWQ7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm9taXNlV2l0aFRpbWVvdXQocHJvbWlzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZGlyKGBSUCAtIEZhaWxlZCB0byBzdGFydCBzdWl0ZSBpdGVtOiAke2V9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgYXN5bmMgb25TdWl0ZUVuZCh7IHJpZCwgc3VpdGVJZCwgcmVzdWx0IH0pIHtcclxuICAgICAgICBpZiAoIXRoaXMuY2JTdWl0ZVRvUnBJZEhhc2hbc3VpdGVJZF0pIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBycFN1aXRlSWQgPSB0aGlzLmNiU3VpdGVUb1JwSWRIYXNoW3N1aXRlSWRdO1xyXG4gICAgICAgIGNvbnN0IGZpbmlzaFRlc3RJdGVtUmVxID0ge1xyXG4gICAgICAgICAgICBzdGF0dXM6IHJlc3VsdC5zdGF0dXMudG9Mb3dlckNhc2UoKSxcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHsgcHJvbWlzZSB9ID0gdGhpcy5ycENsaWVudC5maW5pc2hUZXN0SXRlbShycFN1aXRlSWQsIGZpbmlzaFRlc3RJdGVtUmVxKTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByb21pc2VXaXRoVGltZW91dChwcm9taXNlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgY29uc29sZS5kaXIoYFJQIC0gRmFpbGVkIHRvIGZpbmlzaCBzdWl0ZSBpdGVtOiAke2V9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgYXN5bmMgb25DYXNlU3RhcnQoeyByaWQsIHN1aXRlSWQsIGNhc2VJZCwgJ2Nhc2UnOiBjYXNlRGVmIH0pIHtcclxuICAgICAgICBjb25zdCBzdGFydFRlc3RJdGVtUmVxID0ge1xyXG4gICAgICAgICAgICBuYW1lOiBjYXNlRGVmLm5hbWUsXHJcbiAgICAgICAgICAgIHR5cGU6IFRFU1RfSVRFTV9UWVBFUy5URVNULFxyXG4gICAgICAgICAgICBjb2RlUmVmOiBjYXNlRGVmLnBhdGgsXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCBycFN1aXRlSWQgPSB0aGlzLmNiU3VpdGVUb1JwSWRIYXNoW3N1aXRlSWRdO1xyXG4gICAgICAgIGlmICghcnBTdWl0ZUlkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgeyB0ZW1wSWQsIHByb21pc2UgfSA9IHRoaXMucnBDbGllbnQuc3RhcnRUZXN0SXRlbShzdGFydFRlc3RJdGVtUmVxLCB0aGlzLnRlbXBMYXVuY2hJZCwgcnBTdWl0ZUlkKTtcclxuICAgICAgICB0aGlzLmNiQ2FzZVRvUnBJZEhhc2hbY2FzZUlkXSA9IHRlbXBJZDtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByb21pc2VXaXRoVGltZW91dChwcm9taXNlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgY29uc29sZS5kaXIoYFJQIC0gRmFpbGVkIHRvIHN0YXJ0IHRlc3QgaXRlbTogJHtlfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGFzeW5jIG9uQ2FzZUVuZCh7IHJpZCwgc3VpdGVJZCwgY2FzZUlkLCByZXN1bHQgfSkge1xyXG4gICAgICAgIGNvbnN0IHJwVGVzdElkID0gdGhpcy5jYkNhc2VUb1JwSWRIYXNoW2Nhc2VJZF07XHJcbiAgICAgICAgaWYgKCFycFRlc3RJZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHN0YXR1cyA9IHJlc3VsdC5zdGF0dXMudG9Mb3dlckNhc2UoKTtcclxuICAgICAgICBpZiAoc3RhdHVzID09PSAnZmFpbGVkJyAmJiByZXN1bHQuZmFpbHVyZSkge1xyXG4gICAgICAgICAgICBjb25zdCBycEZpbGUgPSByZXN1bHQuc2NyZWVuc2hvdCA/XHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIG5hbWU6ICdzY3JlZW5zaG90JyxcclxuICAgICAgICAgICAgICAgIHR5cGU6ICdpbWFnZS9wbmcnLFxyXG4gICAgICAgICAgICAgICAgY29udGVudDogcmVzdWx0LnNjcmVlbnNob3QsXHJcbiAgICAgICAgICAgIH0gOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgIGNvbnN0IGxvZ1JlcSA9IHtcclxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IHJlc3VsdC5mYWlsdXJlLm1lc3NhZ2UsXHJcbiAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJ1xyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjb25zdCB7IHByb21pc2U6IHNlbmRMb2dQcm9taXNlIH0gPSBycEZpbGUgP1xyXG4gICAgICAgICAgICAgICAgdGhpcy5ycENsaWVudC5zZW5kTG9nV2l0aEZpbGUocnBUZXN0SWQsIGxvZ1JlcSwgcnBGaWxlKVxyXG4gICAgICAgICAgICAgICAgOiB0aGlzLnJwQ2xpZW50LnNlbmRMb2cocnBUZXN0SWQsIGxvZ1JlcSk7XHJcblxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByb21pc2VXaXRoVGltZW91dChzZW5kTG9nUHJvbWlzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IGZpbmlzaFRlc3RJdGVtUmVxID0ge1xyXG4gICAgICAgICAgICBzdGF0dXM6IHJlc3VsdC5zdGF0dXMudG9Mb3dlckNhc2UoKSxcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHsgcHJvbWlzZSB9ID0gdGhpcy5ycENsaWVudC5maW5pc2hUZXN0SXRlbShycFRlc3RJZCwgZmluaXNoVGVzdEl0ZW1SZXEpO1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucHJvbWlzZVdpdGhUaW1lb3V0KHByb21pc2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmRpcihgUlAgLSBGYWlsZWQgdG8gZmluaXNoIHRlc3QgaXRlbTogJHtlfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGFzeW5jIG9uU3RlcFN0YXJ0KHsgcmlkLCBjYXNlSWQsIHN0ZXAgfSkge1xyXG4gICAgICAgIGlmICghdGhpcy5yZXBvcnRTdGVwcykge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHJwQ2FzZUlkID0gdGhpcy5jYkNhc2VUb1JwSWRIYXNoW2Nhc2VJZF07XHJcbiAgICAgICAgaWYgKCFycENhc2VJZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHN0ZXBOYW1lID0gdGhpcy5fZ2V0U3RlcE5hbWUoc3RlcCk7XHJcbiAgICAgICAgY29uc3Qgc3RhcnRUZXN0SXRlbVJlcSA9IHtcclxuICAgICAgICAgICAgbmFtZTogc3RlcE5hbWUsXHJcbiAgICAgICAgICAgIHR5cGU6IFRFU1RfSVRFTV9UWVBFUy5TVEVQLFxyXG4gICAgICAgICAgICAvLyBcImNvZGVSZWZcIiArIFwicGFyYW1ldGVyc1wiIHVzZWQgYnkgUlAgbGliIHRvIGdlbmVyYXRlIHRlc3RDYXNlSWQgaWYgdGVzdENhc2VJZCBpcyBub3QgZGVmaW5lZFxyXG4gICAgICAgICAgICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL3JlcG9ydHBvcnRhbC9jbGllbnQtamF2YXNjcmlwdC9ibG9iLzQ4NmVmNzBjNjM4YTlhMjMyNjcyOTBjNjJkZjFmYWY5MDBmN2RmNmEvbGliL3JlcG9ydC1wb3J0YWwtY2xpZW50LmpzI0w0OTdcclxuICAgICAgICAgICAgLy8gdGhpcyBpcyBkaXNhYmxlZCBmb3Igbm93LiBub3Qgc3VyZSBpZiBhY3R1YWxseSBuZWVkZWQuLi5cclxuICAgICAgICAgICAgLy9wYXJhbWV0ZXJzOiB0aGlzLl9nZXRScEFyZ3Moc3RlcC5hcmdzKSxcclxuICAgICAgICAgICAgY29kZVJlZjogc3RlcC5sb2NhdGlvbixcclxuICAgICAgICAgICAgdGVzdENhc2VJZDogcnBDYXNlSWQsXHJcbiAgICAgICAgICAgIGhhc1N0YXRzOiBmYWxzZSxcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHsgdGVtcElkLCBwcm9taXNlIH0gPSB0aGlzLnJwQ2xpZW50LnN0YXJ0VGVzdEl0ZW0oc3RhcnRUZXN0SXRlbVJlcSwgdGhpcy50ZW1wTGF1bmNoSWQsIHJwQ2FzZUlkKTtcclxuICAgICAgICB0aGlzLmNiU3RlcFRvUnBJZEhhc2hbc3RlcC5pZF0gPSB0ZW1wSWQ7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm9taXNlV2l0aFRpbWVvdXQocHJvbWlzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZGlyKGBSUCAtIEZhaWxlZCB0byBzdGFydCBzdGVwIGl0ZW06ICR7ZX1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBhc3luYyBvblN0ZXBFbmQoeyByaWQsIHN0ZXA6IHJlc3VsdCB9KSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnJlcG9ydFN0ZXBzKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgcnBTdGVwSWQgPSB0aGlzLmNiU3RlcFRvUnBJZEhhc2hbcmVzdWx0LmlkXTtcclxuICAgICAgICBpZiAoIXJwU3RlcElkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gcmVzdWx0LnN0YXR1cy50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgIGlmIChzdGF0dXMgPT09ICdmYWlsZWQnICYmIHJlc3VsdC5mYWlsdXJlKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHJwRmlsZSA9IHJlc3VsdC5zY3JlZW5zaG90ID9cclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgbmFtZTogJ3NjcmVlbnNob3QnLFxyXG4gICAgICAgICAgICAgICAgdHlwZTogJ2ltYWdlL3BuZycsXHJcbiAgICAgICAgICAgICAgICBjb250ZW50OiByZXN1bHQuc2NyZWVuc2hvdCxcclxuICAgICAgICAgICAgfSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgY29uc3QgbG9nUmVxID0ge1xyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogcmVzdWx0LmZhaWx1cmUubWVzc2FnZSxcclxuICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxyXG4gICAgICAgICAgICAgICAgZmlsZTogcnBGaWxlLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjb25zdCB7IHByb21pc2U6IHNlbmRMb2dQcm9taXNlIH0gPSB0aGlzLnJwQ2xpZW50LnNlbmRMb2cocnBTdGVwSWQsIGxvZ1JlcSwgcnBGaWxlKTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm9taXNlV2l0aFRpbWVvdXQoc2VuZExvZ1Byb21pc2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBmaW5pc2hUZXN0SXRlbVJlcSA9IHtcclxuICAgICAgICAgICAgc3RhdHVzOiByZXN1bHQuc3RhdHVzLnRvTG93ZXJDYXNlKCksXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCB7IHByb21pc2UgfSA9IHRoaXMucnBDbGllbnQuZmluaXNoVGVzdEl0ZW0ocnBTdGVwSWQsIGZpbmlzaFRlc3RJdGVtUmVxKTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByb21pc2VXaXRoVGltZW91dChwcm9taXNlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgY29uc29sZS5kaXIoYFJQIC0gRmFpbGVkIHRvIGZpbmlzaCBzdGVwIGl0ZW06ICR7ZX1gKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBhc3luYyBvbkxvZyh7IHN1aXRlSWQsIGNhc2VJZCwgc3RlcElkLCBsZXZlbCwgbXNnLCB0aW1lLCBzcmMgfSkge1xyXG4gICAgICAgIGlmICghdGhpcy5yZXBvcnRMb2dzKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gT3h5Z2VuIG1pZ2h0IHN0YXJ0IGdlbmVyYXRpbmcgbG9ncyBiZWZvcmUgb25SdW5uZXJTdGFydCBldmVudCwgaWdub3JlIHRoZW1cclxuICAgICAgICBpZiAoIXRoaXMudGVtcExhdW5jaElkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgcnBQYXJlbnRJZCA9IHN0ZXBJZCA/XHJcbiAgICAgICAgICAgIHRoaXMuY2JTdGVwVG9ScElkSGFzaFtzdGVwSWRdXHJcbiAgICAgICAgICAgIDogY2FzZUlkID8gdGhpcy5jYkNhc2VUb1JwSWRIYXNoW2Nhc2VJZF1cclxuICAgICAgICAgICAgOiBzdWl0ZUlkID8gdGhpcy5jYlN1aXRlVG9ScElkSGFzaFtzdWl0ZUlkXVxyXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcclxuICAgICAgICBjb25zdCBycExldmVsID0gdGhpcy5fZ2V0UnBMZXZlbChsZXZlbCk7XHJcbiAgICAgICAgY29uc3QgbG9nUmVxID0ge1xyXG4gICAgICAgICAgICBtZXNzYWdlOiBtc2csXHJcbiAgICAgICAgICAgIGxldmVsOiBycExldmVsLFxyXG4gICAgICAgICAgICB0aW1lOiB0aW1lLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgY29uc3QgeyBwcm9taXNlIH0gPSB0aGlzLnJwQ2xpZW50LnNlbmRMb2cocnBQYXJlbnRJZCB8fCB0aGlzLnRlbXBMYXVuY2hJZCwgbG9nUmVxKTtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByb21pc2VXaXRoVGltZW91dChwcm9taXNlKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgY29uc29sZS5kaXIoYFJQIC0gRmFpbGVkIHRvIGNyZWF0ZSBsb2cgaXRlbTogJHtlfWApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIF9nZXRScExldmVsKG94TGV2ZWwpIHtcclxuICAgICAgICBpZiAob3hMZXZlbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gb3hMZXZlbC50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gJ2luZm8nO1xyXG4gICAgfVxyXG4gICAgLypfZ2V0UnBBcmdzKGNiQXJncykge1xyXG4gICAgICAgIGlmICghY2JBcmdzIHx8ICFjYkFyZ3MubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IHJwQXJncyA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGk9MDsgaSA8IGNiQXJncy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBjb25zdCBhcmcgPSBjYkFyZ3NbaV07XHJcbiAgICAgICAgICAgIGxldCBhcmdTdHIgPSB0eXBlb2YgYXJnID09PSAnc3RyaW5nJyB8fCBhcmcgaW5zdGFuY2VvZiBTdHJpbmcgPyBhcmcgOiBKU09OLnN0cmluZ2lmeShhcmcpO1xyXG4gICAgICAgICAgICBycEFyZ3MucHVzaCh7XHJcbiAgICAgICAgICAgICAgICBrZXk6IGBhcmcke2l9YCxcclxuICAgICAgICAgICAgICAgIHZhbHVlOiBhcmdTdHJcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBycEFyZ3M7XHJcbiAgICB9Ki9cclxuICAgIF9nZXRTdGVwTmFtZShzdGVwKSB7XHJcbiAgICAgICAgbGV0IG5hbWU7XHJcblxyXG4gICAgICAgIGlmIChzdGVwLm5hbWUgPT09ICd0cmFuc2FjdGlvbicgJiYgc3RlcC5hcmdzLmxlbmd0aCA+IDApIHsgIC8vIEZJWE1FOiBzdGVwcyBuZWVkIHRvIGJlIG5lc3RlZCB1bmRlciB0cmFuc2FjdGlvbnNcclxuICAgICAgICAgICAgbmFtZSA9IHN0ZXAuYXJnc1swXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAoc3RlcC5zaWduYXR1cmUpIHtcclxuICAgICAgICAgICAgbmFtZSA9IHN0ZXAuc2lnbmF0dXJlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChzdGVwLm1vZHVsZSkgeyAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGSVhNRTogaXMgdGhpcyBldmVyIHJlYWNoZWQ/IFwic3RlcC5zaWduYXR1cmVcIiBzZWVtcyB0byBhbHdheXMgZXhpc3RcclxuICAgICAgICAgICAgbmFtZSA9IGAke3N0ZXAubW9kdWxlfS4ke3N0ZXAubmFtZX1gO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgbmFtZSA9IHN0ZXAubmFtZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIG1heGltdW0gYWxsb3dlZCBuYW1lIGxlbmd0aCBpbiBSUCBpcyAxMDI0IGJ5dGVzXHJcbiAgICAgICAgLy8gd2UgdHJ1bmNhdGUgaXQgZXZlbiBsb3dlciBzbyBpdCB3aWxsIGRpc3BsYXkgbmljZWx5XHJcbiAgICAgICAgaWYgKG5hbWUubGVuZ3RoID4gTUFYX05BTUVfTEVOR1RIKSB7XHJcbiAgICAgICAgICAgIG5hbWUgPSBuYW1lLnN1YnN0cmluZygwLCBNQVhfTkFNRV9MRU5HVEgtMykgKyAnLi4uJztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG5hbWU7XHJcbiAgICB9XHJcbiAgICBwcm9taXNlV2l0aFRpbWVvdXQocHJvbWlzZSwgdGltZW91dCA9IDEwICogMTAwMCkge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIGlmICghcHJvbWlzZSB8fCAhcHJvbWlzZS50aGVuKSB7XHJcbiAgICAgICAgICAgICAgICByZWplY3QoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBwcm9taXNlLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcclxuICAgICAgICAgICAgc2V0VGltZW91dChyZWplY3QsIHRpbWVvdXQpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG4iXX0=