@dynatrace/rum-javascript-sdk 1.331.18 → 1.333.2

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.
@@ -1,4 +1,5 @@
1
1
  import { expect, test as base } from "@playwright/test";
2
+ import { DEFAULT_IGNORED_EVENTS, DEFAULT_IGNORED_FIELDS, DEFAULT_REMOVED_FIELDS, filterIgnoredEvents, processEventProperties, readSnapshot, sortEventsByCharacteristics, writeSnapshot } from "./snapshot.js";
2
3
  import { fetchRumJavaScript } from "./install.js";
3
4
  import { uncompress } from "snappyjs";
4
5
  const DEFAULT_TIMEOUT = 5_000;
@@ -22,12 +23,31 @@ export const test = base.extend({
22
23
  const cache = new Map();
23
24
  await use(cache);
24
25
  }, { scope: "worker", auto: true, box: true }],
25
- dynatraceTesting: async ({ page, dynatraceConfig, rumJavaScriptCache }, use) => {
26
+ dynatraceTesting: async ({ page, dynatraceConfig, rumJavaScriptCache }, use, testInfo) => {
26
27
  validateDynatraceConfig(dynatraceConfig);
27
- // Check if page has already navigated and warn about fixture ordering
28
- const currentUrl = page.url();
29
- if (currentUrl !== "about:blank") {
30
- console.warn(`[Dynatrace Testing] Warning: Page has already navigated to "${currentUrl}".
28
+ warnIfPageAlreadyNavigated(page);
29
+ const { ignoreWarnings = [], dumpEventsOnFail = false } = dynatraceConfig;
30
+ const context = {
31
+ events: [],
32
+ beacons: [],
33
+ warnings: [],
34
+ dumpEventsOnFail
35
+ };
36
+ setupConsoleWarningListener(page, ignoreWarnings, context);
37
+ await setupRumJavaScriptAndListeners(page, dynatraceConfig, rumJavaScriptCache, context);
38
+ await use(createDynatraceTestingApi(context, testInfo));
39
+ }
40
+ });
41
+ /**
42
+ * Warns if the page has already navigated away from about:blank.
43
+ * This indicates the fixture may not inject RUM JavaScript correctly.
44
+ *
45
+ * @param page The Playwright page instance
46
+ */
47
+ function warnIfPageAlreadyNavigated(page) {
48
+ const currentUrl = page.url();
49
+ if (currentUrl !== "about:blank") {
50
+ console.warn(`[Dynatrace Testing] Warning: Page has already navigated to "${currentUrl}".
31
51
  The RUM JavaScript may not be injected. Ensure dynatraceTesting is destructured
32
52
  before any fixtures that navigate the page.
33
53
 
@@ -35,178 +55,235 @@ Example of correct fixture order:
35
55
  test("my test", async ({ dynatraceTesting, myCustomFixture, page }) => { ... });
36
56
 
37
57
  See testing.md for more information.`);
58
+ }
59
+ }
60
+ /**
61
+ * Sets up a console listener to capture Dynatrace-related warnings.
62
+ *
63
+ * @param page The Playwright page instance
64
+ * @param ignoreWarnings Array of regex patterns for warnings to ignore
65
+ * @param context The testing context to store warnings
66
+ */
67
+ function setupConsoleWarningListener(page, ignoreWarnings, context) {
68
+ const ignoreRegexes = ignoreWarnings.map(x => new RegExp(x, "i"));
69
+ page.on("console", (msg) => {
70
+ if (msg.text().includes("ynatrace") && !ignoreRegexes.some(regex => regex.test(msg.text()))) {
71
+ context.warnings.push(msg.text());
72
+ }
73
+ });
74
+ }
75
+ /**
76
+ * Sets up RUM JavaScript injection and beacon request listeners.
77
+ *
78
+ * @param page The Playwright page instance
79
+ * @param config The Dynatrace configuration
80
+ * @param cache The worker-scoped cache for RUM JavaScript
81
+ * @param context The testing context to store beacons and events
82
+ */
83
+ async function setupRumJavaScriptAndListeners(page, config, cache, context) {
84
+ const { endpointUrl, appId, token } = config;
85
+ const cacheKey = `${endpointUrl}:${appId}`;
86
+ let rum = cache.get(cacheKey);
87
+ if (!rum) {
88
+ rum = await fetchRumJavaScriptContent(endpointUrl, appId, token);
89
+ const beaconUri = extractBeaconUri(rum);
90
+ cache.set(cacheKey, rum);
91
+ cache.set(`${cacheKey}:beaconUri`, beaconUri);
92
+ }
93
+ else {
94
+ const beaconUri = cache.get(`${cacheKey}:beaconUri`);
95
+ if (!beaconUri) {
96
+ throw new Error("Failed to retrieve beaconUri from cache.");
38
97
  }
39
- const { endpointUrl, appId, token, ignoreWarnings = [], dumpEventsOnFail = false } = dynatraceConfig;
40
- const beacons = [];
41
- const events = [];
42
- const warnings = [];
43
- const ignoreRegexes = ignoreWarnings.map(x => new RegExp(x, "i"));
44
- page.on("console", (msg) => {
45
- if (msg.text().includes("ynatrace") && !ignoreRegexes.some(regex => regex.test(msg.text()))) {
46
- warnings.push(msg.text());
98
+ }
99
+ page.on("request", (request) => {
100
+ const url = request.url();
101
+ // Gen 3 beacons should always have ty=js
102
+ if (!url.includes("ty=js")) {
103
+ return;
104
+ }
105
+ const beaconBodyString = extractBeaconBody(request, url);
106
+ if (!beaconBodyString) {
107
+ return;
108
+ }
109
+ try {
110
+ const beaconBody = JSON.parse(beaconBodyString);
111
+ context.beacons.push({
112
+ url: url,
113
+ body: beaconBody
114
+ });
115
+ context.events.push(...beaconBody.data.events);
116
+ }
117
+ catch (error) {
118
+ console.error("[Dynatrace Testing] Failed to parse beacon body:", error);
119
+ }
120
+ });
121
+ await page.addInitScript(rum);
122
+ }
123
+ /**
124
+ * Creates the DynatraceTesting API object with all testing methods.
125
+ *
126
+ * @param context The testing context containing events, beacons, and warnings
127
+ * @param testInfo The Playwright test info for snapshot paths
128
+ * @returns The DynatraceTesting API object
129
+ */
130
+ function createDynatraceTestingApi(context, testInfo) {
131
+ const { events, beacons, warnings } = context;
132
+ return {
133
+ async waitForBeacons(options = {}) {
134
+ const { minCount = 0, timeout = DEFAULT_TIMEOUT } = options;
135
+ const start = Date.now();
136
+ while (beacons.length < minCount && (Date.now() - start) <= timeout) {
137
+ if (warnings.length > 0) {
138
+ throwWithEventDump(context, "Unexpected Dynatrace API warnings: " + warnings.join("\n"), "waitForBeacons - unexpected warnings");
139
+ }
140
+ await wait(100);
47
141
  }
48
- });
49
- await setupRumJavaScript();
50
- await use({
51
- async waitForBeacons(options = {}) {
52
- const { minCount = 0, timeout = DEFAULT_TIMEOUT } = options;
53
- const start = Date.now();
54
- while (beacons.length < minCount && (Date.now() - start) <= timeout) {
55
- if (warnings.length > 0) {
56
- throwWithEventDump("Unexpected Dynatrace API warnings: " + warnings.join("\n"), "waitForBeacons - unexpected warnings");
142
+ if (beacons.length < minCount) {
143
+ throwWithEventDump(context, `Found only ${beacons.length} Dynatrace beacons after timeout of ${timeout}ms, but expected at least ${minCount}.`, "waitForBeacons - timeout");
144
+ }
145
+ return beacons;
146
+ },
147
+ async expectToHaveSentEvent(expectedEvent, options = {}) {
148
+ const { timeout = DEFAULT_TIMEOUT } = options;
149
+ const start = Date.now();
150
+ let lastNonMatch = void 0;
151
+ let nextCheckIndex = 0;
152
+ while ((Date.now() - start) <= timeout) {
153
+ for (let i = nextCheckIndex; i < events.length; i++) {
154
+ const beaconEvent = events[i];
155
+ try {
156
+ expect(beaconEvent).toMatchObject(expectedEvent);
157
+ return;
57
158
  }
58
- await wait(100);
59
- }
60
- if (beacons.length < minCount) {
61
- throwWithEventDump(`Found only ${beacons.length} Dynatrace beacons after timeout of ${timeout}ms, but expected at least ${minCount}.`, "waitForBeacons - timeout");
62
- }
63
- return beacons;
64
- },
65
- async expectToHaveSentEvent(expectedEvent, options = {}) {
66
- const { timeout = DEFAULT_TIMEOUT } = options;
67
- const start = Date.now();
68
- let lastNonMatch = void 0;
69
- let nextCheckIndex = 0;
70
- while ((Date.now() - start) <= timeout) {
71
- for (let i = nextCheckIndex; i < events.length; i++) {
72
- const beaconEvent = events[i];
73
- try {
74
- expect(beaconEvent).toMatchObject(expectedEvent);
75
- return;
76
- }
77
- catch {
78
- lastNonMatch = beaconEvent;
79
- }
80
- nextCheckIndex = i + 1;
159
+ catch {
160
+ lastNonMatch = beaconEvent;
81
161
  }
82
- await wait(100);
162
+ nextCheckIndex = i + 1;
83
163
  }
84
- if (!lastNonMatch) {
85
- throwWithEventDump("Dynatrace didn't send any events.", "expectToHaveSentEvent - no events");
86
- }
87
- dumpEventsIfEnabled("expectToHaveSentEvent - no match");
88
- expect(lastNonMatch).toMatchObject(expectedEvent);
89
- },
90
- async expectToHaveSentEventTimes(expectedEvent, times, options = {}) {
91
- const { timeout = DEFAULT_TIMEOUT } = options;
92
- const start = Date.now();
93
- let lastNonMatch = void 0;
94
- let nextCheckIndex = 0;
95
- let foundTimes = 0;
96
- while ((Date.now() - start) <= timeout) {
97
- for (let i = nextCheckIndex; i < events.length; i++) {
98
- const beaconEvent = events[i];
99
- try {
100
- expect(beaconEvent).toMatchObject(expectedEvent);
101
- foundTimes++;
102
- }
103
- catch {
104
- lastNonMatch = beaconEvent;
105
- }
106
- nextCheckIndex = i + 1;
107
- }
108
- if (foundTimes === times) {
109
- return;
164
+ await wait(100);
165
+ }
166
+ if (!lastNonMatch) {
167
+ throwWithEventDump(context, "Dynatrace didn't send any events.", "expectToHaveSentEvent - no events");
168
+ }
169
+ dumpEventsIfEnabled(context, "expectToHaveSentEvent - no match");
170
+ expect(lastNonMatch).toMatchObject(expectedEvent);
171
+ },
172
+ async expectToHaveSentEventTimes(expectedEvent, times, options = {}) {
173
+ const { timeout = DEFAULT_TIMEOUT } = options;
174
+ const start = Date.now();
175
+ let lastNonMatch = void 0;
176
+ let nextCheckIndex = 0;
177
+ let foundTimes = 0;
178
+ while ((Date.now() - start) <= timeout) {
179
+ for (let i = nextCheckIndex; i < events.length; i++) {
180
+ const beaconEvent = events[i];
181
+ try {
182
+ expect(beaconEvent).toMatchObject(expectedEvent);
183
+ foundTimes++;
110
184
  }
111
- if (foundTimes > times) {
112
- throwWithEventDump(`Expected ${times} event occurrences, found ${foundTimes}.`, "expectToHaveSentEventTimes - too many matches");
185
+ catch {
186
+ lastNonMatch = beaconEvent;
113
187
  }
114
- await wait(100);
188
+ nextCheckIndex = i + 1;
115
189
  }
116
- if (!lastNonMatch) {
117
- throwWithEventDump("Dynatrace didn't send any events", "expectToHaveSentEventTimes - no events");
190
+ if (foundTimes === times) {
191
+ return;
118
192
  }
119
- if (foundTimes < times) {
120
- throwWithEventDump(`Didn't find the expected amount of ${times} matching events, found ${foundTimes}.`, "expectToHaveSentEventTimes - count mismatch");
193
+ if (foundTimes > times) {
194
+ throwWithEventDump(context, `Expected ${times} event occurrences, found ${foundTimes}.`, "expectToHaveSentEventTimes - too many matches");
121
195
  }
122
- dumpEventsIfEnabled("expectToHaveSentEventTimes - no match");
123
- expect(lastNonMatch).toMatchObject(expectedEvent);
124
- },
125
- clearEvents() {
126
- events.length = 0;
127
- beacons.length = 0;
196
+ await wait(100);
128
197
  }
129
- });
130
- /**
131
- * Dumps received events to console if dumpEventsOnFail is enabled.
132
- * Formats events for readability.
133
- *
134
- * @param context Additional context about why events are being dumped
135
- */
136
- function dumpEventsIfEnabled(context) {
137
- if (!dumpEventsOnFail) {
138
- return;
198
+ if (!lastNonMatch) {
199
+ throwWithEventDump(context, "Dynatrace didn't send any events", "expectToHaveSentEventTimes - no events");
139
200
  }
140
- console.log(`\n[Dynatrace Testing] Event Dump (${context})`);
141
- console.log(`Total events received: ${events.length}`);
142
- console.log(`Total beacons received: ${beacons.length}`);
143
- if (events.length === 0) {
144
- console.log("No events were received.");
201
+ if (foundTimes < times) {
202
+ throwWithEventDump(context, `Didn't find the expected amount of ${times} matching events, found ${foundTimes}.`, "expectToHaveSentEventTimes - count mismatch");
145
203
  }
146
- else {
147
- console.log("\nReceived events:");
148
- events.forEach((event, index) => {
149
- console.log(`\nEvent ${index + 1}:`, JSON.stringify(event, null, 2));
150
- });
204
+ dumpEventsIfEnabled(context, "expectToHaveSentEventTimes - no match");
205
+ expect(lastNonMatch).toMatchObject(expectedEvent);
206
+ },
207
+ clearEvents() {
208
+ events.length = 0;
209
+ beacons.length = 0;
210
+ },
211
+ toMatchEventSnapshot(options = {}) {
212
+ const { ignoreEvents = [...DEFAULT_IGNORED_EVENTS], ignoredFields = [...DEFAULT_IGNORED_FIELDS], removedFields = [...DEFAULT_REMOVED_FIELDS], name } = options;
213
+ const snapshotName = name ?? "events";
214
+ const snapshotPath = testInfo.snapshotPath(`${snapshotName}.events.snap`);
215
+ const updateSnapshots = testInfo.config.updateSnapshots === "all";
216
+ const filteredEvents = filterIgnoredEvents(events, ignoreEvents);
217
+ const processedEvents = processEventProperties(filteredEvents, ignoredFields, removedFields);
218
+ const snapshotResult = readSnapshot(snapshotPath);
219
+ if (!snapshotResult.exists || updateSnapshots) {
220
+ writeSnapshot(snapshotPath, processedEvents);
221
+ if (!snapshotResult.exists) {
222
+ console.log(`[Dynatrace Testing] Created new snapshot: ${snapshotPath}`);
223
+ }
224
+ else {
225
+ console.log(`[Dynatrace Testing] Updated snapshot: ${snapshotPath}`);
226
+ }
227
+ return Promise.resolve();
151
228
  }
152
- }
153
- /**
154
- * Throws an error with a custom message. If event dumping is enabled, logs the received Dynatrace events before
155
- * throwing the error.
156
- *
157
- * @param message The error message to be thrown
158
- * @param context Context about the failure for event dumping
159
- */
160
- function throwWithEventDump(message, context) {
161
- dumpEventsIfEnabled(context ?? "assertion failure");
162
- throw new Error(message);
163
- }
164
- async function setupRumJavaScript() {
165
- // Fetch RUM JavaScript once and cache it
166
- const cacheKey = `${endpointUrl}:${appId}`;
167
- let rum = rumJavaScriptCache.get(cacheKey);
168
- let beaconUri;
169
- if (!rum) {
170
- rum = await fetchRumJavaScriptContent(endpointUrl, appId, token);
171
- beaconUri = extractBeaconUri(rum);
172
- rumJavaScriptCache.set(cacheKey, rum);
173
- rumJavaScriptCache.set(`${cacheKey}:beaconUri`, beaconUri);
229
+ const snapshotData = snapshotResult.data;
230
+ if (!snapshotData) {
231
+ return Promise.reject(new Error("[Dynatrace Testing] Snapshot file is empty"));
174
232
  }
175
- else {
176
- beaconUri = rumJavaScriptCache.get(`${cacheKey}:beaconUri`);
177
- if (!beaconUri) {
178
- throw new Error("Failed to retrieve beaconUri from cache.");
179
- }
233
+ // Sort both arrays by characteristics for order-independent comparison
234
+ const sortedActual = sortEventsByCharacteristics(processedEvents);
235
+ const sortedExpected = sortEventsByCharacteristics(snapshotData);
236
+ try {
237
+ // Use Playwright's expect for comparison - provides excellent diff output
238
+ expect(sortedActual).toStrictEqual(sortedExpected);
239
+ return Promise.resolve();
240
+ }
241
+ catch (error) {
242
+ dumpEventsIfEnabled(context, "toMatchEventSnapshot - mismatch");
243
+ const errorMessage = `[Dynatrace Testing] Snapshot mismatch for "${snapshotName}".\n\n`
244
+ + `Snapshot path: ${snapshotPath}\n\n`
245
+ + `${error instanceof Error ? error.message : String(error)}\n\n`
246
+ + `To update the snapshot, run with --update-snapshots flag.`;
247
+ return Promise.reject(new Error(errorMessage));
180
248
  }
181
- // Listen to network requests to capture beacon data
182
- // This approach doesn't interfere with user-defined routes
183
- page.on("request", (request) => {
184
- const url = request.url();
185
- // Gen 3 beacons should always have ty=js
186
- if (!url.includes("ty=js")) {
187
- return;
188
- }
189
- const beaconBodyString = extractBeaconBody(request, url);
190
- if (!beaconBodyString) {
191
- return;
192
- }
193
- try {
194
- const beaconBody = JSON.parse(beaconBodyString);
195
- beacons.push({
196
- url: url,
197
- body: beaconBody
198
- });
199
- events.push(...beaconBody.data.events);
200
- }
201
- catch (error) {
202
- console.error("[Dynatrace Testing] Failed to parse beacon body:", error);
203
- }
204
- });
205
- // Use addInitScript to inject RUM script tag before any page scripts execute
206
- await page.addInitScript(rum);
207
249
  }
250
+ };
251
+ }
252
+ /**
253
+ * Dumps received events to console if dumpEventsOnFail is enabled.
254
+ *
255
+ * @param context The testing context containing events and beacons
256
+ * @param description Additional context about why events are being dumped
257
+ */
258
+ function dumpEventsIfEnabled(context, description) {
259
+ if (!context.dumpEventsOnFail) {
260
+ return;
208
261
  }
209
- });
262
+ console.log(`\n[Dynatrace Testing] Event Dump (${description})`);
263
+ console.log(`Total events received: ${context.events.length}`);
264
+ console.log(`Total beacons received: ${context.beacons.length}`);
265
+ if (context.events.length === 0) {
266
+ console.log("No events were received.");
267
+ }
268
+ else {
269
+ console.log("\nReceived events:");
270
+ context.events.forEach((event, index) => {
271
+ console.log(`\nEvent ${index + 1}:`, JSON.stringify(event, null, 2));
272
+ });
273
+ }
274
+ }
275
+ /**
276
+ * Throws an error with a custom message. If event dumping is enabled, logs the received Dynatrace events before
277
+ * throwing the error.
278
+ *
279
+ * @param context The testing context for event dumping
280
+ * @param message The error message to be thrown
281
+ * @param description Context about the failure for event dumping
282
+ */
283
+ function throwWithEventDump(context, message, description) {
284
+ dumpEventsIfEnabled(context, description ?? "assertion failure");
285
+ throw new Error(message);
286
+ }
210
287
  /**
211
288
  * Creates a helpful error for missing configuration fields.
212
289
  *
@@ -316,4 +393,4 @@ function extractBeaconBody(request, url) {
316
393
  }
317
394
  return request.postData();
318
395
  }
319
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS90ZXN0aW5nL3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUNILE1BQU0sRUFDTixJQUFJLElBQUksSUFBSSxFQUNmLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2xELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFrRXRDLE1BQU0sZUFBZSxHQUFHLEtBQUssQ0FBQztBQUU5QixNQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBK0RsQzs7R0FFRztBQUNILE1BQU0sa0JBQWtCLEdBQTJCO0lBQy9DLFdBQVcsRUFBRSwrRUFBK0U7SUFDNUYsS0FBSyxFQUFFLGlFQUFpRTtJQUN4RSxLQUFLLEVBQUUsa0VBQWtFO0NBQzVFLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBeUQ7SUFDcEYsZUFBZSxFQUFFLENBQUM7WUFDZCxLQUFLLEVBQUUsRUFBRTtZQUNULFdBQVcsRUFBRSxFQUFFO1lBQ2YsS0FBSyxFQUFFLEVBQUU7U0FDWixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDO0lBRXBCLDZIQUE2SDtJQUM3SCxrQkFBa0IsRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDcEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7WUFDeEMsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckIsQ0FBQyxFQUFFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUU5QyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsZUFB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QU8sT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQzlCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFJlcXVlc3QgfSBmcm9tIFwiQHBsYXl3cmlnaHQvdGVzdFwiO1xuaW1wb3J0IHtcbiAgICBleHBlY3QsXG4gICAgdGVzdCBhcyBiYXNlXG59IGZyb20gXCJAcGxheXdyaWdodC90ZXN0XCI7XG5pbXBvcnQgeyBmZXRjaFJ1bUphdmFTY3JpcHQgfSBmcm9tIFwiLi9pbnN0YWxsLmpzXCI7XG5pbXBvcnQgeyB1bmNvbXByZXNzIH0gZnJvbSBcInNuYXBweWpzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2FpdEZvckJlYWNvbnNPcHRpb25zIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbWluaW11bSBudW1iZXIgb2YgYmVhY29uIHJlcXVlc3RzIHRvIHdhaXQgZm9yXG4gICAgICovXG4gICAgbWluQ291bnQ/OiBudW1iZXI7XG4gICAgLyoqXG4gICAgICogVGhlIG1heGltdW0gdGltZSB0byB3YWl0IGZvciBiZWFjb24gcmVxdWVzdHMsIGluIG1pbGxpc2Vjb25kcyAtIERlZmF1bHQ6IDVfMDAwXG4gICAgICovXG4gICAgdGltZW91dD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHBlY3RPcHRpb25zIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSB0aW1lIHRvIHdhaXQgZm9yIHRoZSBldmVudCB0byBiZSBzZW50LCBpbiBtaWxsaXNlY29uZHMgLSBEZWZhdWx0OiA1XzAwMFxuICAgICAqL1xuICAgIHRpbWVvdXQ/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHluYXRyYWNlVGVzdGluZyB7XG4gICAgLyoqXG4gICAgICogV2FpdHMgZm9yIGEgc3BlY2lmaWVkIG51bWJlciBvZiBiZWFjb24gcmVxdWVzdHMgb3IgdW50aWwgYSB0aW1lb3V0IG9jY3Vycy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvcHRpb25zIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3Igd2FpdGluZyBmb3IgYmVhY29uc1xuICAgICAqIEByZXR1cm5zICAgICAgIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gYXJyYXkgb2YgYmVhY29uIHJlcXVlc3RzXG4gICAgICovXG4gICAgd2FpdEZvckJlYWNvbnMob3B0aW9ucz86IFdhaXRGb3JCZWFjb25zT3B0aW9ucyk6IFByb21pc2U8QmVhY29uUmVxdWVzdFtdPjtcblxuICAgIC8qKlxuICAgICAqIFZlcmlmaWVzIHRoYXQgYSBzcGVjaWZpYyBldmVudCBoYXMgYmVlbiBzZW50LCBvcHRpb25hbGx5IHdpdGhpbiBhIHRpbWVvdXQgcGVyaW9kLlxuICAgICAqXG4gICAgICogQHBhcmFtIGV2ZW50ICAgVGhlIGV2ZW50IHRvIGNoZWNrLCByZXByZXNlbnRlZCBhcyBhIGtleS12YWx1ZSBwYWlyIG9iamVjdC4gVGhpcyB1c2VzIFBsYXl3cmlnaHRzIGV4cGVjdChldmVudCkudG9NYXRjaE9iamVjdC5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoZSB2ZXJpZmljYXRpb25cbiAgICAgKiBAcmV0dXJucyAgICAgICBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBldmVudCBpcyBjb25maXJtZWQgdG8gaGF2ZSBiZWVuIHNlbnRcbiAgICAgKi9cbiAgICBleHBlY3RUb0hhdmVTZW50RXZlbnQoZXZlbnQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBvcHRpb25zPzogRXhwZWN0T3B0aW9ucyk6IFByb21pc2U8dm9pZD47XG5cbiAgICAvKipcbiAgICAgKiBWZXJpZmllcyB0aGF0IGEgc3BlY2lmaWMgZXZlbnQgaGFzIGJlZW4gc2VudCBhIHNwZWNpZmllZCBudW1iZXIgb2YgdGltZXMsIG9wdGlvbmFsbHkgd2l0aGluIGEgdGltZW91dCBwZXJpb2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnQgICBUaGUgZXZlbnQgdG8gY2hlY2ssIHJlcHJlc2VudGVkIGFzIGEga2V5LXZhbHVlIHBhaXIgb2JqZWN0LiBUaGlzIHVzZXMgUGxheXdyaWdodHMgZXhwZWN0KGV2ZW50KS50b01hdGNoT2JqZWN0LlxuICAgICAqIEBwYXJhbSB0aW1lcyAgIFRoZSBleGFjdCBudW1iZXIgb2YgdGltZXMgdGhlIGV2ZW50IGlzIGV4cGVjdGVkIHRvIGhhdmUgYmVlbiBzZW50XG4gICAgICogQHBhcmFtIG9wdGlvbnMgQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgdmVyaWZpY2F0aW9uXG4gICAgICogQHJldHVybnMgICAgICAgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZXZlbnQgaXMgY29uZmlybWVkIHRvIGhhdmUgYmVlbiBzZW50IHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIHRpbWVzXG4gICAgICovXG4gICAgZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMoZXZlbnQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCB0aW1lczogbnVtYmVyLCBvcHRpb25zPzogRXhwZWN0T3B0aW9ucyk6IFByb21pc2U8dm9pZD47XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgYWxsIGV2ZW50cyBhbmQgYmVhY29ucywgYWxsb3dpbmcgZm9yIHN1YnNlcXVlbnQgZXhwZWN0YXRpb25zIHRvIGlnbm9yZSBldmVudHMgdGhhdCBoYXZlIGJlZW4gc2VudFxuICAgICAqIGluIHRoZSBwYXN0LiBFeGFtcGxlOlxuICAgICAqIGBgYFxuICAgICAqIHNlbmRGb29FdmVudCgpO1xuICAgICAqIGF3YWl0IGR5bmF0cmFjZVRlc3RpbmcuZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMoeyBmb286IFwiYmFyXCIgfSwgMSk7XG4gICAgICogZHluYXRyYWNlVGVzdGluZy5jbGVhckV2ZW50cygpO1xuICAgICAqIGF3YWl0IGR5bmF0cmFjZVRlc3RpbmcuZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMoeyBmb286IFwiYmFyXCIgfSwgMSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgY2xlYXJFdmVudHMoKTogdm9pZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCZWFjb25SZXF1ZXN0IHtcbiAgICB1cmw6IHN0cmluZztcbiAgICBib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuY29uc3QgREVGQVVMVF9USU1FT1VUID0gNV8wMDA7XG5cbmNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcblxuZXhwb3J0IGludGVyZmFjZSBEeW5hdHJhY2VUZXN0aW5nRml4dHVyZSB7XG4gICAgLyoqXG4gICAgICogVGhlIHRlc3RpbmcgQVBJIHByb3ZpZGluZyBleHBlY3QgbWV0aG9kcy5cbiAgICAgKi9cbiAgICBkeW5hdHJhY2VUZXN0aW5nOiBEeW5hdHJhY2VUZXN0aW5nO1xuXG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiB0byBlbmFibGUgRHluYXRyYWNlIHRlc3Rpbmcgd2l0aCBhIGdpdmVuIGVudmlyb25tZW50LlxuICAgICAqL1xuICAgIGR5bmF0cmFjZUNvbmZpZzogRHluYXRyYWNlQ29uZmlnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER5bmF0cmFjZUNvbmZpZyB7XG4gICAgLyoqXG4gICAgICogVGhlIFVSTCBvZiB0aGUgRHluYXRyYWNlIEFQSSBlbmRwb2ludCB0byBjb25uZWN0IHRvLCBzZWVcbiAgICAgKiBbUlVNIG1hbnVhbCBpbnNlcnRpb24gdGFncyBBUEldKGh0dHBzOi8vZG9jcy5keW5hdHJhY2UuY29tL2RvY3MvZGlzY292ZXItZHluYXRyYWNlL3JlZmVyZW5jZXMvZHluYXRyYWNlLWFwaS9lbnZpcm9ubWVudC1hcGkvcnVtL3J1bS1tYW51YWwtaW5zZXJ0aW9uLXRhZ3MpXG4gICAgICogZm9yIGRldGFpbHMuIEV4YW1wbGU6IGh0dHBzOi8ve3lvdXItZW52aXJvbm1lbnQtaWR9LmxpdmUuZHluYXRyYWNlLmNvbSBvclxuICAgICAqIGh0dHBzOi8ve3lvdXItYWN0aXZlZ2F0ZS1kb21haW59L2Uve3lvdXItZW52aXJvbm1lbnQtaWR9XG4gICAgICovXG4gICAgZW5kcG9pbnRVcmw6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBhcHBsaWNhdGlvbiBJRCB0byBpZGVudGlmeSB0aGUgY29ycmVjdCBSVU0gSmF2YVNjcmlwdCB0byBmZXRjaC4gWW91IGNhbiBmaW5kXG4gICAgICogdGhpcyBpbiB0aGUgVVJMIGlmIHlvdSBvcGVuIHRoZSBFeHBlcmllbmNlIFZpdGFscyBhcHAgYW5kIHNlbGVjdCB0aGUgZnJvbnRlbmQgeW91XG4gICAgICogd2FudCB0byB0ZXN0LiBFeGFtcGxlOiBBUFBMSUNBVElPTi1BQkNERUYwMTIzNDU2Nzg5XG4gICAgICovXG4gICAgYXBwSWQ6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIFRoZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmb3IgdGhlIGluc3RhbGxhdGlvbi4gU2VlXG4gICAgICogW1Rva2VucyBhbmQgYXV0aGVudGljYXRpb25dKGh0dHBzOi8vZG9jcy5keW5hdHJhY2UuY29tL2RvY3MvZGlzY292ZXItZHluYXRyYWNlL3JlZmVyZW5jZXMvZHluYXRyYWNlLWFwaS9iYXNpY3MvZHluYXRyYWNlLWFwaS1hdXRoZW50aWNhdGlvbikuXG4gICAgICovXG4gICAgdG9rZW46IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEFjY2VwdHMgYW4gYXJyYXkgb2YgcmVndWxhciBleHByZXNzaW9ucyB0byBtYXRjaCBhZ2FpbnN0IER5bmF0cmFjZS1yZWxhdGVkIHdhcm5pbmdzLiBCeSBkZWZhdWx0LCB0aGVzZSB3YXJuaW5nc1xuICAgICAqIHRyaWdnZXIgdGVzdCBmYWlscy4gSWYgeW91IGFudGljaXBhdGUgd2FybmluZ3MgYW5kIGRvbid0IHdhbnQgeW91ciB0ZXN0cyB0byBmYWlsLCB1c2UgdGhpcyBzZXR0aW5nIHRvIGlnbm9yZSB0aGVtXG4gICAgICogYnkgbWVzc2FnZS4gRXhhbXBsZTpcbiAgICAgKiBbXCJpbnZhbGlkIHByb3BlcnR5IG15X2FwcF9kYXRhXFwuXFxcXHcrWzAtOV9dKlwiXVxuICAgICAqL1xuICAgIGlnbm9yZVdhcm5pbmdzPzogc3RyaW5nW107XG5cbiAgICAvKipcbiAgICAgKiBEdW1wIHRoZSBhcnJheSBvZiBEeW5hdHJhY2UgZXZlbnRzIGludG8gdGhlIGNvbnNvbGUgaW4gY2FzZSBhbiBhc3NlcnRpb24gZmFpbHMuXG4gICAgICovXG4gICAgZHVtcEV2ZW50c09uRmFpbD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogV29ya2VyLXNjb3BlZCBmaXh0dXJlcyBmb3IgY2FjaGluZyBSVU0gSmF2YVNjcmlwdCBhY3Jvc3MgdGVzdHMgaW4gdGhlIHNhbWUgd29ya2VyLlxuICogVGhpcyBpbXByb3ZlcyBwZXJmb3JtYW5jZSBieSBhdm9pZGluZyByZWR1bmRhbnQgbmV0d29yayByZXF1ZXN0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEeW5hdHJhY2VUZXN0aW5nV29ya2VyRml4dHVyZSB7XG4gICAgLyoqXG4gICAgICogQ2FjaGUgZm9yIFJVTSBKYXZhU2NyaXB0IHNuaXBwZXRzLCBzY29wZWQgdG8gdGhlIHdvcmtlci5cbiAgICAgKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHJ1bUphdmFTY3JpcHRDYWNoZTogTWFwPHN0cmluZywgc3RyaW5nPjtcbn1cblxuLyoqXG4gKiBGaWVsZCBkZXNjcmlwdGlvbnMgZm9yIGNvbmZpZ3VyYXRpb24gZXJyb3IgbWVzc2FnZXMuXG4gKi9cbmNvbnN0IEZJRUxEX0RFU0NSSVBUSU9OUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICBlbmRwb2ludFVybDogXCJUaGUgRHluYXRyYWNlIGVudmlyb25tZW50IFVSTCAoZS5nLiwgXFxcImh0dHBzOi8vYWJjMTIzNDUubGl2ZS5keW5hdHJhY2UuY29tXFxcIilcIixcbiAgICBhcHBJZDogXCJUaGUgUlVNIGFwcGxpY2F0aW9uIElEIChlLmcuLCBcXFwiQVBQTElDQVRJT04tQUJDREVGMDEyMzQ1Njc4OVxcXCIpXCIsXG4gICAgdG9rZW46IFwiVGhlIEFQSSB0b2tlbiB3aXRoIFxcXCJSZWFkIFJVTSBtYW51YWwgaW5zZXJ0aW9uIHRhZ3NcXFwiIHBlcm1pc3Npb25cIlxufTtcblxuZXhwb3J0IGNvbnN0IHRlc3QgPSBiYXNlLmV4dGVuZDxEeW5hdHJhY2VUZXN0aW5nRml4dHVyZSwgRHluYXRyYWNlVGVzdGluZ1dvcmtlckZpeHR1cmU+KHtcbiAgICBkeW5hdHJhY2VDb25maWc6IFt7XG4gICAgICAgIGFwcElkOiBcIlwiLFxuICAgICAgICBlbmRwb2ludFVybDogXCJcIixcbiAgICAgICAgdG9rZW46IFwiXCJcbiAgICB9LCB7IG9wdGlvbjogdHJ1ZSB9XSxcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1lbXB0eS1wYXR0ZXJuIC0tIFBsYXl3cmlnaHQgcmVxdWlyZXMgb2JqZWN0IGRlc3RydWN0dXJpbmcgZXZlbiB3aGVuIG5vIGRlcGVuZGVuY2llcyBhcmUgbmVlZGVkXG4gICAgcnVtSmF2YVNjcmlwdENhY2hlOiBbYXN5bmMgKHsgfSwgdXNlKSA9PiB7IC8vIE5PU09OQVJcbiAgICAgICAgY29uc3QgY2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgICAgICBhd2FpdCB1c2UoY2FjaGUpO1xuICAgIH0sIHsgc2NvcGU6IFwid29ya2VyXCIsIGF1dG86IHRydWUsIGJveDogdHJ1ZSB9XSxcblxuICAgIGR5bmF0cmFjZVRlc3Rpbmc6IGFzeW5jICh7IHBhZ2UsIGR5bmF0cmFjZUNvbmZpZywgcnVtSmF2YVNjcmlwdENhY2hlIH0sIHVzZSkgPT4ge1xuICAgICAgICB2YWxpZGF0ZUR5bmF0cmFjZUNvbmZpZyhkeW5hdHJhY2VDb25maWcpO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIHBhZ2UgaGFzIGFscmVhZHkgbmF2aWdhdGVkIGFuZCB3YXJuIGFib3V0IGZpeHR1cmUgb3JkZXJpbmdcbiAgICAgICAgY29uc3QgY3VycmVudFVybCA9IHBhZ2UudXJsKCk7XG4gICAgICAgIGlmIChjdXJyZW50VXJsICE9PSBcImFib3V0OmJsYW5rXCIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICBgW0R5bmF0cmFjZSBUZXN0aW5nXSBXYXJuaW5nOiBQYWdlIGhhcyBhbHJlYWR5IG5hdmlnYXRlZCB0byBcIiR7Y3VycmVudFVybH1cIi5cblRoZSBSVU0gSmF2YVNjcmlwdCBtYXkgbm90IGJlIGluamVjdGVkLiBFbnN1cmUgZHluYXRyYWNlVGVzdGluZyBpcyBkZXN0cnVjdHVyZWRcbmJlZm9yZSBhbnkgZml4dHVyZXMgdGhhdCBuYXZpZ2F0ZSB0aGUgcGFnZS5cblxuRXhhbXBsZSBvZiBjb3JyZWN0IGZpeHR1cmUgb3JkZXI6XG4gICAgdGVzdChcIm15IHRlc3RcIiwgYXN5bmMgKHsgZHluYXRyYWNlVGVzdGluZywgbXlDdXN0b21GaXh0dXJlLCBwYWdlIH0pID0+IHsgLi4uIH0pO1xuXG5TZWUgdGVzdGluZy5tZCBmb3IgbW9yZSBpbmZvcm1hdGlvbi5gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBlbmRwb2ludFVybCwgYXBwSWQsIHRva2VuLCBpZ25vcmVXYXJuaW5ncyA9IFtdLCBkdW1wRXZlbnRzT25GYWlsID0gZmFsc2UgfSA9IGR5bmF0cmFjZUNvbmZpZztcbiAgICAgICAgY29uc3QgYmVhY29uczogeyB1cmw6IHN0cmluZywgYm9keTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfVtdID0gW107XG4gICAgICAgIGNvbnN0IGV2ZW50czogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXSA9IFtdO1xuICAgICAgICBjb25zdCB3YXJuaW5nczogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgY29uc3QgaWdub3JlUmVnZXhlcyA9IGlnbm9yZVdhcm5pbmdzLm1hcCh4ID0+IG5ldyBSZWdFeHAoeCwgXCJpXCIpKTtcblxuICAgICAgICBwYWdlLm9uKFwiY29uc29sZVwiLCAobXNnKSA9PiB7XG4gICAgICAgICAgICBpZiAobXNnLnRleHQoKS5pbmNsdWRlcyhcInluYXRyYWNlXCIpICYmICFpZ25vcmVSZWdleGVzLnNvbWUocmVnZXggPT4gcmVnZXgudGVzdChtc2cudGV4dCgpKSkpIHtcbiAgICAgICAgICAgICAgICB3YXJuaW5ncy5wdXNoKG1zZy50ZXh0KCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCBzZXR1cFJ1bUphdmFTY3JpcHQoKTtcblxuICAgICAgICBhd2FpdCB1c2Uoe1xuICAgICAgICAgICAgYXN5bmMgd2FpdEZvckJlYWNvbnMob3B0aW9uczogV2FpdEZvckJlYWNvbnNPcHRpb25zID0ge30pOiBQcm9taXNlPEJlYWNvblJlcXVlc3RbXT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgbWluQ291bnQgPSAwLCB0aW1lb3V0ID0gREVGQVVMVF9USU1FT1VUIH0gPSBvcHRpb25zO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChiZWFjb25zLmxlbmd0aCA8IG1pbkNvdW50ICYmIChEYXRlLm5vdygpIC0gc3RhcnQpIDw9IHRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlVuZXhwZWN0ZWQgRHluYXRyYWNlIEFQSSB3YXJuaW5nczogXCIgKyB3YXJuaW5ncy5qb2luKFwiXFxuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwid2FpdEZvckJlYWNvbnMgLSB1bmV4cGVjdGVkIHdhcm5pbmdzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChiZWFjb25zLmxlbmd0aCA8IG1pbkNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgICAgIGBGb3VuZCBvbmx5ICR7YmVhY29ucy5sZW5ndGh9IER5bmF0cmFjZSBiZWFjb25zIGFmdGVyIHRpbWVvdXQgb2YgJHt0aW1lb3V0fW1zLCBidXQgZXhwZWN0ZWQgYXQgbGVhc3QgJHttaW5Db3VudH0uYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIFwid2FpdEZvckJlYWNvbnMgLSB0aW1lb3V0XCJcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYmVhY29ucztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGFzeW5jIGV4cGVjdFRvSGF2ZVNlbnRFdmVudChcbiAgICAgICAgICAgICAgICBleHBlY3RlZEV2ZW50OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgICAgICAgICBvcHRpb25zOiBFeHBlY3RPcHRpb25zID0ge31cbiAgICAgICAgICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVCB9ID0gb3B0aW9ucztcbiAgICAgICAgICAgICAgICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3ROb25NYXRjaDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQgPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgbGV0IG5leHRDaGVja0luZGV4ID0gMDtcblxuICAgICAgICAgICAgICAgIHdoaWxlICgoRGF0ZS5ub3coKSAtIHN0YXJ0KSA8PSB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBuZXh0Q2hlY2tJbmRleDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVhY29uRXZlbnQgPSBldmVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChiZWFjb25FdmVudCkudG9NYXRjaE9iamVjdChleHBlY3RlZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0Tm9uTWF0Y2ggPSBiZWFjb25FdmVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDaGVja0luZGV4ID0gaSArIDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghbGFzdE5vbk1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRHluYXRyYWNlIGRpZG4ndCBzZW5kIGFueSBldmVudHMuXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcImV4cGVjdFRvSGF2ZVNlbnRFdmVudCAtIG5vIGV2ZW50c1wiXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZHVtcEV2ZW50c0lmRW5hYmxlZChcImV4cGVjdFRvSGF2ZVNlbnRFdmVudCAtIG5vIG1hdGNoXCIpO1xuICAgICAgICAgICAgICAgIGV4cGVjdChsYXN0Tm9uTWF0Y2gpLnRvTWF0Y2hPYmplY3QoZXhwZWN0ZWRFdmVudCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBhc3luYyBleHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyhcbiAgICAgICAgICAgICAgICBleHBlY3RlZEV2ZW50OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgICAgICAgICB0aW1lczogbnVtYmVyLFxuICAgICAgICAgICAgICAgIG9wdGlvbnM6IEV4cGVjdE9wdGlvbnMgPSB7fVxuICAgICAgICAgICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyB0aW1lb3V0ID0gREVGQVVMVF9USU1FT1VUIH0gPSBvcHRpb25zO1xuICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdE5vbk1hdGNoOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZCA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICBsZXQgbmV4dENoZWNrSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGxldCBmb3VuZFRpbWVzID0gMDtcblxuICAgICAgICAgICAgICAgIHdoaWxlICgoRGF0ZS5ub3coKSAtIHN0YXJ0KSA8PSB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBuZXh0Q2hlY2tJbmRleDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVhY29uRXZlbnQgPSBldmVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdChiZWFjb25FdmVudCkudG9NYXRjaE9iamVjdChleHBlY3RlZEV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZFRpbWVzKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0Tm9uTWF0Y2ggPSBiZWFjb25FdmVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRDaGVja0luZGV4ID0gaSArIDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvdW5kVGltZXMgPT09IHRpbWVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvdW5kVGltZXMgPiB0aW1lcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dXaXRoRXZlbnREdW1wKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBFeHBlY3RlZCAke3RpbWVzfSBldmVudCBvY2N1cnJlbmNlcywgZm91bmQgJHtmb3VuZFRpbWVzfS5gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMgLSB0b28gbWFueSBtYXRjaGVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghbGFzdE5vbk1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRHluYXRyYWNlIGRpZG4ndCBzZW5kIGFueSBldmVudHNcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMgLSBubyBldmVudHNcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChmb3VuZFRpbWVzIDwgdGltZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3dXaXRoRXZlbnREdW1wKFxuICAgICAgICAgICAgICAgICAgICAgICAgYERpZG4ndCBmaW5kIHRoZSBleHBlY3RlZCBhbW91bnQgb2YgJHt0aW1lc30gbWF0Y2hpbmcgZXZlbnRzLCBmb3VuZCAke2ZvdW5kVGltZXN9LmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBcImV4cGVjdFRvSGF2ZVNlbnRFdmVudFRpbWVzIC0gY291bnQgbWlzbWF0Y2hcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGR1bXBFdmVudHNJZkVuYWJsZWQoXCJleHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyAtIG5vIG1hdGNoXCIpO1xuICAgICAgICAgICAgICAgIGV4cGVjdChsYXN0Tm9uTWF0Y2gpLnRvTWF0Y2hPYmplY3QoZXhwZWN0ZWRFdmVudCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjbGVhckV2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgICAgICAgICBldmVudHMubGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICBiZWFjb25zLmxlbmd0aCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEdW1wcyByZWNlaXZlZCBldmVudHMgdG8gY29uc29sZSBpZiBkdW1wRXZlbnRzT25GYWlsIGlzIGVuYWJsZWQuXG4gICAgICAgICAqIEZvcm1hdHMgZXZlbnRzIGZvciByZWFkYWJpbGl0eS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGNvbnRleHQgQWRkaXRpb25hbCBjb250ZXh0IGFib3V0IHdoeSBldmVudHMgYXJlIGJlaW5nIGR1bXBlZFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gZHVtcEV2ZW50c0lmRW5hYmxlZChjb250ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgICAgIGlmICghZHVtcEV2ZW50c09uRmFpbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc29sZS5sb2coYFxcbltEeW5hdHJhY2UgVGVzdGluZ10gRXZlbnQgRHVtcCAoJHtjb250ZXh0fSlgKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBUb3RhbCBldmVudHMgcmVjZWl2ZWQ6ICR7ZXZlbnRzLmxlbmd0aH1gKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBUb3RhbCBiZWFjb25zIHJlY2VpdmVkOiAke2JlYWNvbnMubGVuZ3RofWApO1xuXG4gICAgICAgICAgICBpZiAoZXZlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTm8gZXZlbnRzIHdlcmUgcmVjZWl2ZWQuXCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlxcblJlY2VpdmVkIGV2ZW50czpcIik7XG4gICAgICAgICAgICAgICAgZXZlbnRzLmZvckVhY2goKGV2ZW50LCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgXFxuRXZlbnQgJHtpbmRleCArIDF9OmAsIEpTT04uc3RyaW5naWZ5KGV2ZW50LCBudWxsLCAyKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogVGhyb3dzIGFuIGVycm9yIHdpdGggYSBjdXN0b20gbWVzc2FnZS4gSWYgZXZlbnQgZHVtcGluZyBpcyBlbmFibGVkLCBsb2dzIHRoZSByZWNlaXZlZCBEeW5hdHJhY2UgZXZlbnRzIGJlZm9yZVxuICAgICAgICAgKiB0aHJvd2luZyB0aGUgZXJyb3IuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBlcnJvciBtZXNzYWdlIHRvIGJlIHRocm93blxuICAgICAgICAgKiBAcGFyYW0gY29udGV4dCBDb250ZXh0IGFib3V0IHRoZSBmYWlsdXJlIGZvciBldmVudCBkdW1waW5nXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiB0aHJvd1dpdGhFdmVudER1bXAobWVzc2FnZTogc3RyaW5nLCBjb250ZXh0Pzogc3RyaW5nKTogbmV2ZXIge1xuICAgICAgICAgICAgZHVtcEV2ZW50c0lmRW5hYmxlZChjb250ZXh0ID8/IFwiYXNzZXJ0aW9uIGZhaWx1cmVcIik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICBhc3luYyBmdW5jdGlvbiBzZXR1cFJ1bUphdmFTY3JpcHQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgICAgICAvLyBGZXRjaCBSVU0gSmF2YVNjcmlwdCBvbmNlIGFuZCBjYWNoZSBpdFxuICAgICAgICAgICAgY29uc3QgY2FjaGVLZXkgPSBgJHtlbmRwb2ludFVybH06JHthcHBJZH1gO1xuICAgICAgICAgICAgbGV0IHJ1bSA9IHJ1bUphdmFTY3JpcHRDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgICAgICAgICAgbGV0IGJlYWNvblVyaTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKCFydW0pIHtcbiAgICAgICAgICAgICAgICBydW0gPSBhd2FpdCBmZXRjaFJ1bUphdmFTY3JpcHRDb250ZW50KGVuZHBvaW50VXJsLCBhcHBJZCwgdG9rZW4pO1xuICAgICAgICAgICAgICAgIGJlYWNvblVyaSA9IGV4dHJhY3RCZWFjb25VcmkocnVtKTtcblxuICAgICAgICAgICAgICAgIHJ1bUphdmFTY3JpcHRDYWNoZS5zZXQoY2FjaGVLZXksIHJ1bSk7XG4gICAgICAgICAgICAgICAgcnVtSmF2YVNjcmlwdENhY2hlLnNldChgJHtjYWNoZUtleX06YmVhY29uVXJpYCwgYmVhY29uVXJpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYmVhY29uVXJpID0gcnVtSmF2YVNjcmlwdENhY2hlLmdldChgJHtjYWNoZUtleX06YmVhY29uVXJpYCk7XG4gICAgICAgICAgICAgICAgaWYgKCFiZWFjb25VcmkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHJldHJpZXZlIGJlYWNvblVyaSBmcm9tIGNhY2hlLlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3RlbiB0byBuZXR3b3JrIHJlcXVlc3RzIHRvIGNhcHR1cmUgYmVhY29uIGRhdGFcbiAgICAgICAgICAgIC8vIFRoaXMgYXBwcm9hY2ggZG9lc24ndCBpbnRlcmZlcmUgd2l0aCB1c2VyLWRlZmluZWQgcm91dGVzXG4gICAgICAgICAgICBwYWdlLm9uKFwicmVxdWVzdFwiLCAocmVxdWVzdCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IHJlcXVlc3QudXJsKCk7XG4gICAgICAgICAgICAgICAgLy8gR2VuIDMgYmVhY29ucyBzaG91bGQgYWx3YXlzIGhhdmUgdHk9anNcbiAgICAgICAgICAgICAgICBpZiAoIXVybC5pbmNsdWRlcyhcInR5PWpzXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYmVhY29uQm9keVN0cmluZyA9IGV4dHJhY3RCZWFjb25Cb2R5KHJlcXVlc3QsIHVybCk7XG4gICAgICAgICAgICAgICAgaWYgKCFiZWFjb25Cb2R5U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVhY29uQm9keToge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50czogUmVjb3JkPHN0cmluZywgdW5rbm93bj5bXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0gPSBKU09OLnBhcnNlKGJlYWNvbkJvZHlTdHJpbmcpO1xuICAgICAgICAgICAgICAgICAgICBiZWFjb25zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICAgICAgICAgICBib2R5OiBiZWFjb25Cb2R5XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBldmVudHMucHVzaCguLi5iZWFjb25Cb2R5LmRhdGEuZXZlbnRzKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiW0R5bmF0cmFjZSBUZXN0aW5nXSBGYWlsZWQgdG8gcGFyc2UgYmVhY29uIGJvZHk6XCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gVXNlIGFkZEluaXRTY3JpcHQgdG8gaW5qZWN0IFJVTSBzY3JpcHQgdGFnIGJlZm9yZSBhbnkgcGFnZSBzY3JpcHRzIGV4ZWN1dGVcbiAgICAgICAgICAgIGF3YWl0IHBhZ2UuYWRkSW5pdFNjcmlwdChydW0pO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGhlbHBmdWwgZXJyb3IgZm9yIG1pc3NpbmcgY29uZmlndXJhdGlvbiBmaWVsZHMuXG4gKlxuICogQHBhcmFtIG1pc3NpbmdGaWVsZHMgQXJyYXkgb2YgZmllbGQgbmFtZXMgdGhhdCBhcmUgbWlzc2luZyBvciBlbXB0eVxuICogQHJldHVybnMgICAgICAgICAgICAgRXJyb3Igd2l0aCBkZXRhaWxlZCBzZXR1cCBpbnN0cnVjdGlvbnNcbiAqL1xuZnVuY3Rpb24gY3JlYXRlTWlzc2luZ0NvbmZpZ0Vycm9yKG1pc3NpbmdGaWVsZHM6IHN0cmluZ1tdKTogRXJyb3Ige1xuICAgIGNvbnN0IG1pc3NpbmdEZXRhaWxzID0gbWlzc2luZ0ZpZWxkc1xuICAgICAgICAubWFwKGZpZWxkID0+IGAgICAgLSAke2ZpZWxkfTogJHtGSUVMRF9ERVNDUklQVElPTlNbZmllbGRdfWApXG4gICAgICAgIC5qb2luKFwiXFxuXCIpO1xuXG4gICAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICAgICAgYFtEeW5hdHJhY2UgVGVzdGluZ10gTWlzc2luZyByZXF1aXJlZCBjb25maWd1cmF0aW9uIGZpZWxkJHttaXNzaW5nRmllbGRzLmxlbmd0aCA+IDEgPyBcInNcIiA6IFwiXCJ9OiAke21pc3NpbmdGaWVsZHMuam9pbihcIiwgXCIpfVxuXG4ke21pc3NpbmdEZXRhaWxzfVxuXG5Db25maWd1cmUgdmlhIHRlc3QudXNlKCk6XG4gICAgdGVzdC51c2Uoe1xuICAgICAgICBkeW5hdHJhY2VDb25maWc6IHtcbiAgICAgICAgICAgIGVuZHBvaW50VXJsOiBwcm9jZXNzLmVudi5EVF9FTkRQT0lOVF9VUkwhLFxuICAgICAgICAgICAgYXBwSWQ6IHByb2Nlc3MuZW52LkRUX0FQUF9JRCEsXG4gICAgICAgICAgICB0b2tlbjogcHJvY2Vzcy5lbnYuRFRfVE9LRU4hXG4gICAgICAgIH1cbiAgICB9KTtcblxuU2VlIHRlc3RpbmcubWQgZm9yIGRldGFpbGVkIHNldHVwIGluc3RydWN0aW9ucy5gXG4gICAgKTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdGhlIER5bmF0cmFjZSBjb25maWd1cmF0aW9uIGFuZCB0aHJvd3MgYSBoZWxwZnVsIGVycm9yIGlmIGludmFsaWQuXG4gKlxuICogQHBhcmFtIGNvbmZpZyBUaGUgY29uZmlndXJhdGlvbiB0byB2YWxpZGF0ZVxuICogQHRocm93cyBFcnJvciB3aXRoIGRldGFpbGVkIHNldHVwIGluc3RydWN0aW9ucyBpZiBjb25maWd1cmF0aW9uIGlzIGludmFsaWRcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVEeW5hdHJhY2VDb25maWcoY29uZmlnOiBEeW5hdHJhY2VDb25maWcpOiB2b2lkIHtcbiAgICBjb25zdCBtaXNzaW5nRmllbGRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKCFjb25maWcuZW5kcG9pbnRVcmwgfHwgY29uZmlnLmVuZHBvaW50VXJsLnRyaW0oKSA9PT0gXCJcIikge1xuICAgICAgICBtaXNzaW5nRmllbGRzLnB1c2goXCJlbmRwb2ludFVybFwiKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5hcHBJZCB8fCBjb25maWcuYXBwSWQudHJpbSgpID09PSBcIlwiKSB7XG4gICAgICAgIG1pc3NpbmdGaWVsZHMucHVzaChcImFwcElkXCIpO1xuICAgIH1cblxuICAgIGlmICghY29uZmlnLnRva2VuIHx8IGNvbmZpZy50b2tlbi50cmltKCkgPT09IFwiXCIpIHtcbiAgICAgICAgbWlzc2luZ0ZpZWxkcy5wdXNoKFwidG9rZW5cIik7XG4gICAgfVxuXG4gICAgaWYgKG1pc3NpbmdGaWVsZHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBjcmVhdGVNaXNzaW5nQ29uZmlnRXJyb3IobWlzc2luZ0ZpZWxkcyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIFJVTSBKYXZhU2NyaXB0IGNvbnRlbnQgZnJvbSB0aGUgRHluYXRyYWNlIEFQSSBlbmRwb2ludC5cbiAqXG4gKiBAcGFyYW0gZW5kcG9pbnRVcmwgVGhlIFVSTCBvZiB0aGUgRHluYXRyYWNlIEFQSSBlbmRwb2ludFxuICogQHBhcmFtIGFwcElkICAgICAgIFRoZSBhcHBsaWNhdGlvbiBJRCB0byBpZGVudGlmeSB0aGUgY29ycmVjdCBSVU0gSmF2YVNjcmlwdFxuICogQHBhcmFtIHRva2VuICAgICAgIFRoZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmb3IgdGhlIGluc3RhbGxhdGlvblxuICogQHJldHVybnMgICAgICAgICAgIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBSVU0gSmF2YVNjcmlwdCBjb250ZW50XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZldGNoUnVtSmF2YVNjcmlwdENvbnRlbnQoZW5kcG9pbnRVcmw6IHN0cmluZywgYXBwSWQ6IHN0cmluZywgdG9rZW46IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcnVtQXBpUmVzdWx0ID0gYXdhaXQgZmV0Y2hSdW1KYXZhU2NyaXB0KGVuZHBvaW50VXJsLCBhcHBJZCwgdG9rZW4pO1xuICAgIGlmICghcnVtQXBpUmVzdWx0LmluY2x1ZGVzKFwiX2NvbXBsZXRlLmpzXCIpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRHluYXRyYWNlIHJlY2VpdmVkIHVuZXhwZWN0ZWQgUlVNIEphdmFTY3JpcHQgd2hlbiByZXF1ZXN0aW5nIHRoZSBKYXZhU2NyaXB0IFRhZyB2aWEgQVBJOiAke3J1bUFwaVJlc3VsdH1gKTtcbiAgICB9XG5cbiAgICAvLyBFeHRyYWN0IHRoZSBzcmMgVVJMIGZyb20gdGhlIHNjcmlwdCB0YWdcbiAgICBjb25zdCBzcmNNYXRjaCA9IHJ1bUFwaVJlc3VsdC5tYXRjaCgvc3JjPVwiKFteXCJdKylcIi8pO1xuICAgIGlmICghc3JjTWF0Y2gpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGV4dHJhY3Qgc3JjIFVSTCBmcm9tIFJVTSBKYXZhU2NyaXB0IHRhZy5cIik7XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdFVybCA9IHNyY01hdGNoWzFdO1xuXG4gICAgLy8gRmV0Y2ggdGhlIGFjdHVhbCBKYXZhU2NyaXB0IGNvbnRlbnRcbiAgICBjb25zdCBzY3JpcHRSZXNwb25zZSA9IGF3YWl0IGZldGNoKHNjcmlwdFVybCk7XG4gICAgcmV0dXJuIHNjcmlwdFJlc3BvbnNlLnRleHQoKTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyB0aGUgYmVhY29uIFVSSSBmcm9tIHRoZSBSVU0gSmF2YVNjcmlwdCBjb250ZW50LlxuICpcbiAqIEBwYXJhbSBydW0gVGhlIFJVTSBKYXZhU2NyaXB0IGNvbnRlbnQgdG8gZXh0cmFjdCB0aGUgYmVhY29uIFVSSSBmcm9tXG4gKiBAcmV0dXJucyAgIFRoZSBleHRyYWN0ZWQgYmVhY29uIFVSSVxuICovXG5mdW5jdGlvbiBleHRyYWN0QmVhY29uVXJpKHJ1bTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBFeHRyYWN0IHRoZSBiZWFjb25VcmkgZnJvbSB0aGUgSmF2YVNjcmlwdCBjb250ZW50XG4gICAgY29uc3QgYmVhY29uVXJpTWF0Y2ggPSBydW0ubWF0Y2goL1wiYmVhY29uVXJpXCI6XCIoW15cIl0rKVwiLyk7XG4gICAgaWYgKCFiZWFjb25VcmlNYXRjaCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gZXh0cmFjdCBiZWFjb25VcmkgZnJvbSBSVU0gSmF2YVNjcmlwdCBjb250ZW50LlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGJlYWNvblVyaU1hdGNoWzFdO1xufVxuXG4vKipcbiAqIFdhaXRzIGZvciBhIGdpdmVuIHRpbWUgYW5kIHJlc29sdmVzIHVwb24gdGltZW91dC5cbiAqXG4gKiBAcGFyYW0gdGltZSBUaGUgdGltZSB0byB3YWl0IGluIG1pbGxpc2Vjb25kc1xuICogQHJldHVybnMgICAgQSByZXNvbHZlZCBwcm9taXNlIHdoZW4gdGhlIHRpbWUgcmFuIG91dFxuICovXG5mdW5jdGlvbiB3YWl0KHRpbWU6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIHRpbWUpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHRoZSBib2R5IG9mIGEgYmVhY29uIHJlcXVlc3QsIG9wdGlvbmFsbHkgZGVjb21wcmVzc2luZyBpdCBpZiB0aGUgVVJMIGluZGljYXRlcyBjb21wcmVzc2VkIGRhdGEuXG4gKlxuICogQHBhcmFtIHJlcXVlc3QgVGhlIHJlcXVlc3Qgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGJlYWNvbiBkYXRhXG4gKiBAcGFyYW0gdXJsICAgICBUaGUgVVJMIG9mIHRoZSByZXF1ZXN0IHRvIGNoZWNrIGZvciBzcGVjaWZpYyBjb21wcmVzc2lvbiBpbmRpY2F0b3JzXG4gKiBAcmV0dXJucyAgICAgICBUaGUgZXh0cmFjdGVkIGJvZHkgb2YgdGhlIGJlYWNvbiByZXF1ZXN0LCBvciBudWxsIGlmIG5vIHJlcXVlc3QgYm9keSBpcyBwcmVzZW50XG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RCZWFjb25Cb2R5KHJlcXVlc3Q6IFJlcXVlc3QsIHVybDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgYnVmZmVyID0gcmVxdWVzdC5wb3N0RGF0YUJ1ZmZlcigpO1xuICAgIGlmICh1cmwuaW5jbHVkZXMoXCJjbz1zbmFwcHlcIikgJiYgYnVmZmVyKSB7XG4gICAgICAgIGNvbnN0IHVpbnQ4RGF0YSA9IHVuY29tcHJlc3MoYnVmZmVyKTtcbiAgICAgICAgcmV0dXJuIGRlY29kZXIuZGVjb2RlKHVpbnQ4RGF0YSk7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0LnBvc3REYXRhKCk7XG59XG4iXX0=
396
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NvdXJjZS90ZXN0aW5nL3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsT0FBTyxFQUNILE1BQU0sRUFDTixJQUFJLElBQUksSUFBSSxFQUNmLE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNILHNCQUFzQixFQUN0QixzQkFBc0IsRUFDdEIsc0JBQXNCLEVBQ3RCLG1CQUFtQixFQUNuQixzQkFBc0IsRUFDdEIsWUFBWSxFQUNaLDJCQUEyQixFQUMzQixhQUFhLEVBQ2hCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBMkV0QyxNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUM7QUFFOUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztBQXlFbEM7O0dBRUc7QUFDSCxNQUFNLGtCQUFrQixHQUEyQjtJQUMvQyxXQUFXLEVBQUUsK0VBQStFO0lBQzVGLEtBQUssRUFBRSxpRUFBaUU7SUFDeEUsS0FBSyxFQUFFLGtFQUFrRTtDQUM1RSxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQXlEO0lBQ3BGLGVBQWUsRUFBRSxDQUFDO1lBQ2QsS0FBSyxFQUFFLEVBQUU7WUFDVCxXQUFXLEVBQUUsRUFBRTtZQUNmLEtBQUssRUFBRSxFQUFFO1NBQ1osRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUVwQiw2SEFBNkg7SUFDN0gsa0JBQWtCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRyxFQUFFLEdBQUcsRUFBRSxFQUFFO1lBQ3BDLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1lBQ3hDLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FB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RCxDQUFDLENBQUM7SUFDaEYsQ0FBQztJQUNELE9BQU8sY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzdCLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsSUFBSSxDQUFDLElBQVk7SUFDdEIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1FBQzNCLFVBQVUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDOUIsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxPQUFnQixFQUFFLEdBQVc7SUFDcEQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3hDLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckMsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUge1xuICAgIFBhZ2UsXG4gICAgUmVxdWVzdCxcbiAgICBUZXN0SW5mb1xufSBmcm9tIFwiQHBsYXl3cmlnaHQvdGVzdFwiO1xuaW1wb3J0IHR5cGUgeyBTbmFwc2hvdE9wdGlvbnMgfSBmcm9tIFwiLi9zbmFwc2hvdC5qc1wiO1xuaW1wb3J0IHtcbiAgICBleHBlY3QsXG4gICAgdGVzdCBhcyBiYXNlXG59IGZyb20gXCJAcGxheXdyaWdodC90ZXN0XCI7XG5pbXBvcnQge1xuICAgIERFRkFVTFRfSUdOT1JFRF9FVkVOVFMsXG4gICAgREVGQVVMVF9JR05PUkVEX0ZJRUxEUyxcbiAgICBERUZBVUxUX1JFTU9WRURfRklFTERTLFxuICAgIGZpbHRlcklnbm9yZWRFdmVudHMsXG4gICAgcHJvY2Vzc0V2ZW50UHJvcGVydGllcyxcbiAgICByZWFkU25hcHNob3QsXG4gICAgc29ydEV2ZW50c0J5Q2hhcmFjdGVyaXN0aWNzLFxuICAgIHdyaXRlU25hcHNob3Rcbn0gZnJvbSBcIi4vc25hcHNob3QuanNcIjtcbmltcG9ydCB7IGZldGNoUnVtSmF2YVNjcmlwdCB9IGZyb20gXCIuL2luc3RhbGwuanNcIjtcbmltcG9ydCB7IHVuY29tcHJlc3MgfSBmcm9tIFwic25hcHB5anNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBXYWl0Rm9yQmVhY29uc09wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIFRoZSBtaW5pbXVtIG51bWJlciBvZiBiZWFjb24gcmVxdWVzdHMgdG8gd2FpdCBmb3JcbiAgICAgKi9cbiAgICBtaW5Db3VudD86IG51bWJlcjtcbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSB0aW1lIHRvIHdhaXQgZm9yIGJlYWNvbiByZXF1ZXN0cywgaW4gbWlsbGlzZWNvbmRzIC0gRGVmYXVsdDogNV8wMDBcbiAgICAgKi9cbiAgICB0aW1lb3V0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4cGVjdE9wdGlvbnMge1xuICAgIC8qKlxuICAgICAqIFRoZSBtYXhpbXVtIHRpbWUgdG8gd2FpdCBmb3IgdGhlIGV2ZW50IHRvIGJlIHNlbnQsIGluIG1pbGxpc2Vjb25kcyAtIERlZmF1bHQ6IDVfMDAwXG4gICAgICovXG4gICAgdGltZW91dD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBEeW5hdHJhY2VUZXN0aW5nIHtcbiAgICAvKipcbiAgICAgKiBXYWl0cyBmb3IgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGJlYWNvbiByZXF1ZXN0cyBvciB1bnRpbCBhIHRpbWVvdXQgb2NjdXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB3YWl0aW5nIGZvciBiZWFjb25zXG4gICAgICogQHJldHVybnMgICAgICAgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiBiZWFjb24gcmVxdWVzdHNcbiAgICAgKi9cbiAgICB3YWl0Rm9yQmVhY29ucyhvcHRpb25zPzogV2FpdEZvckJlYWNvbnNPcHRpb25zKTogUHJvbWlzZTxCZWFjb25SZXF1ZXN0W10+O1xuXG4gICAgLyoqXG4gICAgICogVmVyaWZpZXMgdGhhdCBhIHNwZWNpZmljIGV2ZW50IGhhcyBiZWVuIHNlbnQsIG9wdGlvbmFsbHkgd2l0aGluIGEgdGltZW91dCBwZXJpb2QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZXZlbnQgICBUaGUgZXZlbnQgdG8gY2hlY2ssIHJlcHJlc2VudGVkIGFzIGEga2V5LXZhbHVlIHBhaXIgb2JqZWN0LiBUaGlzIHVzZXMgUGxheXdyaWdodHMgZXhwZWN0KGV2ZW50KS50b01hdGNoT2JqZWN0LlxuICAgICAqIEBwYXJhbSBvcHRpb25zIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIHZlcmlmaWNhdGlvblxuICAgICAqIEByZXR1cm5zICAgICAgIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGV2ZW50IGlzIGNvbmZpcm1lZCB0byBoYXZlIGJlZW4gc2VudFxuICAgICAqL1xuICAgIGV4cGVjdFRvSGF2ZVNlbnRFdmVudChldmVudDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIG9wdGlvbnM/OiBFeHBlY3RPcHRpb25zKTogUHJvbWlzZTx2b2lkPjtcblxuICAgIC8qKlxuICAgICAqIFZlcmlmaWVzIHRoYXQgYSBzcGVjaWZpYyBldmVudCBoYXMgYmVlbiBzZW50IGEgc3BlY2lmaWVkIG51bWJlciBvZiB0aW1lcywgb3B0aW9uYWxseSB3aXRoaW4gYSB0aW1lb3V0IHBlcmlvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBldmVudCAgIFRoZSBldmVudCB0byBjaGVjaywgcmVwcmVzZW50ZWQgYXMgYSBrZXktdmFsdWUgcGFpciBvYmplY3QuIFRoaXMgdXNlcyBQbGF5d3JpZ2h0cyBleHBlY3QoZXZlbnQpLnRvTWF0Y2hPYmplY3QuXG4gICAgICogQHBhcmFtIHRpbWVzICAgVGhlIGV4YWN0IG51bWJlciBvZiB0aW1lcyB0aGUgZXZlbnQgaXMgZXhwZWN0ZWQgdG8gaGF2ZSBiZWVuIHNlbnRcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoZSB2ZXJpZmljYXRpb25cbiAgICAgKiBAcmV0dXJucyAgICAgICBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBldmVudCBpcyBjb25maXJtZWQgdG8gaGF2ZSBiZWVuIHNlbnQgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgdGltZXNcbiAgICAgKi9cbiAgICBleHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyhldmVudDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIHRpbWVzOiBudW1iZXIsIG9wdGlvbnM/OiBFeHBlY3RPcHRpb25zKTogUHJvbWlzZTx2b2lkPjtcblxuICAgIC8qKlxuICAgICAqIENsZWFycyBhbGwgZXZlbnRzIGFuZCBiZWFjb25zLCBhbGxvd2luZyBmb3Igc3Vic2VxdWVudCBleHBlY3RhdGlvbnMgdG8gaWdub3JlIGV2ZW50cyB0aGF0IGhhdmUgYmVlbiBzZW50XG4gICAgICogaW4gdGhlIHBhc3QuIEV4YW1wbGU6XG4gICAgICogYGBgXG4gICAgICogc2VuZEZvb0V2ZW50KCk7XG4gICAgICogYXdhaXQgZHluYXRyYWNlVGVzdGluZy5leHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyh7IGZvbzogXCJiYXJcIiB9LCAxKTtcbiAgICAgKiBkeW5hdHJhY2VUZXN0aW5nLmNsZWFyRXZlbnRzKCk7XG4gICAgICogYXdhaXQgZHluYXRyYWNlVGVzdGluZy5leHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyh7IGZvbzogXCJiYXJcIiB9LCAxKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBjbGVhckV2ZW50cygpOiB2b2lkO1xuXG4gICAgLyoqXG4gICAgICogQ29tcGFyZXMgY2FwdHVyZWQgZXZlbnRzIGFnYWluc3QgYSBzdG9yZWQgc25hcHNob3QgZmlsZS5cbiAgICAgKiBPbiBmaXJzdCBydW4sIGNyZWF0ZXMgdGhlIHNuYXBzaG90LiBPbiBzdWJzZXF1ZW50IHJ1bnMsIGNvbXBhcmVzIGFuZCBmYWlscyBpZiBkaWZmZXJlbnQuXG4gICAgICogVm9sYXRpbGUgZmllbGRzICh0aW1lc3RhbXBzLCBJRHMsIGV0Yy4pIGFyZSBtYXNrZWQgYnkgZGVmYXVsdCB0byBwcmV2ZW50IGZsYWt5IHRlc3RzLlxuICAgICAqXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQ29uZmlndXJhdGlvbiBmb3Igc25hcHNob3QgY29tcGFyaXNvblxuICAgICAqL1xuICAgIHRvTWF0Y2hFdmVudFNuYXBzaG90KG9wdGlvbnM/OiBTbmFwc2hvdE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJlYWNvblJlcXVlc3Qge1xuICAgIHVybDogc3RyaW5nO1xuICAgIGJvZHk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG5jb25zdCBERUZBVUxUX1RJTUVPVVQgPSA1XzAwMDtcblxuY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuXG4vKipcbiAqIEludGVybmFsIGNvbnRleHQgc2hhcmVkIGJldHdlZW4gdGVzdGluZyBBUEkgbWV0aG9kcy5cbiAqL1xuaW50ZXJmYWNlIFRlc3RpbmdDb250ZXh0IHtcbiAgICBldmVudHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gICAgYmVhY29uczogQmVhY29uUmVxdWVzdFtdO1xuICAgIHdhcm5pbmdzOiBzdHJpbmdbXTtcbiAgICBkdW1wRXZlbnRzT25GYWlsOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER5bmF0cmFjZVRlc3RpbmdGaXh0dXJlIHtcbiAgICAvKipcbiAgICAgKiBUaGUgdGVzdGluZyBBUEkgcHJvdmlkaW5nIGV4cGVjdCBtZXRob2RzLlxuICAgICAqL1xuICAgIGR5bmF0cmFjZVRlc3Rpbmc6IER5bmF0cmFjZVRlc3Rpbmc7XG5cbiAgICAvKipcbiAgICAgKiBDb25maWd1cmF0aW9uIHRvIGVuYWJsZSBEeW5hdHJhY2UgdGVzdGluZyB3aXRoIGEgZ2l2ZW4gZW52aXJvbm1lbnQuXG4gICAgICovXG4gICAgZHluYXRyYWNlQ29uZmlnOiBEeW5hdHJhY2VDb25maWc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHluYXRyYWNlQ29uZmlnIHtcbiAgICAvKipcbiAgICAgKiBUaGUgVVJMIG9mIHRoZSBEeW5hdHJhY2UgQVBJIGVuZHBvaW50IHRvIGNvbm5lY3QgdG8sIHNlZVxuICAgICAqIFtSVU0gbWFudWFsIGluc2VydGlvbiB0YWdzIEFQSV0oaHR0cHM6Ly9kb2NzLmR5bmF0cmFjZS5jb20vZG9jcy9kaXNjb3Zlci1keW5hdHJhY2UvcmVmZXJlbmNlcy9keW5hdHJhY2UtYXBpL2Vudmlyb25tZW50LWFwaS9ydW0vcnVtLW1hbnVhbC1pbnNlcnRpb24tdGFncylcbiAgICAgKiBmb3IgZGV0YWlscy4gRXhhbXBsZTogaHR0cHM6Ly97eW91ci1lbnZpcm9ubWVudC1pZH0ubGl2ZS5keW5hdHJhY2UuY29tIG9yXG4gICAgICogaHR0cHM6Ly97eW91ci1hY3RpdmVnYXRlLWRvbWFpbn0vZS97eW91ci1lbnZpcm9ubWVudC1pZH1cbiAgICAgKi9cbiAgICBlbmRwb2ludFVybDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGFwcGxpY2F0aW9uIElEIHRvIGlkZW50aWZ5IHRoZSBjb3JyZWN0IFJVTSBKYXZhU2NyaXB0IHRvIGZldGNoLiBZb3UgY2FuIGZpbmRcbiAgICAgKiB0aGlzIGluIHRoZSBVUkwgaWYgeW91IG9wZW4gdGhlIEV4cGVyaWVuY2UgVml0YWxzIGFwcCBhbmQgc2VsZWN0IHRoZSBmcm9udGVuZCB5b3VcbiAgICAgKiB3YW50IHRvIHRlc3QuIEV4YW1wbGU6IEFQUExJQ0FUSU9OLUFCQ0RFRjAxMjM0NTY3ODlcbiAgICAgKi9cbiAgICBhcHBJZDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuIGZvciB0aGUgaW5zdGFsbGF0aW9uLiBTZWVcbiAgICAgKiBbVG9rZW5zIGFuZCBhdXRoZW50aWNhdGlvbl0oaHR0cHM6Ly9kb2NzLmR5bmF0cmFjZS5jb20vZG9jcy9kaXNjb3Zlci1keW5hdHJhY2UvcmVmZXJlbmNlcy9keW5hdHJhY2UtYXBpL2Jhc2ljcy9keW5hdHJhY2UtYXBpLWF1dGhlbnRpY2F0aW9uKS5cbiAgICAgKi9cbiAgICB0b2tlbjogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQWNjZXB0cyBhbiBhcnJheSBvZiByZWd1bGFyIGV4cHJlc3Npb25zIHRvIG1hdGNoIGFnYWluc3QgRHluYXRyYWNlLXJlbGF0ZWQgd2FybmluZ3MuIEJ5IGRlZmF1bHQsIHRoZXNlIHdhcm5pbmdzXG4gICAgICogdHJpZ2dlciB0ZXN0IGZhaWxzLiBJZiB5b3UgYW50aWNpcGF0ZSB3YXJuaW5ncyBhbmQgZG9uJ3Qgd2FudCB5b3VyIHRlc3RzIHRvIGZhaWwsIHVzZSB0aGlzIHNldHRpbmcgdG8gaWdub3JlIHRoZW1cbiAgICAgKiBieSBtZXNzYWdlLiBFeGFtcGxlOlxuICAgICAqIFtcImludmFsaWQgcHJvcGVydHkgbXlfYXBwX2RhdGFcXC5cXFxcdytbMC05X10qXCJdXG4gICAgICovXG4gICAgaWdub3JlV2FybmluZ3M/OiBzdHJpbmdbXTtcblxuICAgIC8qKlxuICAgICAqIER1bXAgdGhlIGFycmF5IG9mIER5bmF0cmFjZSBldmVudHMgaW50byB0aGUgY29uc29sZSBpbiBjYXNlIGFuIGFzc2VydGlvbiBmYWlscy5cbiAgICAgKi9cbiAgICBkdW1wRXZlbnRzT25GYWlsPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBXb3JrZXItc2NvcGVkIGZpeHR1cmVzIGZvciBjYWNoaW5nIFJVTSBKYXZhU2NyaXB0IGFjcm9zcyB0ZXN0cyBpbiB0aGUgc2FtZSB3b3JrZXIuXG4gKiBUaGlzIGltcHJvdmVzIHBlcmZvcm1hbmNlIGJ5IGF2b2lkaW5nIHJlZHVuZGFudCBuZXR3b3JrIHJlcXVlc3RzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIER5bmF0cmFjZVRlc3RpbmdXb3JrZXJGaXh0dXJlIHtcbiAgICAvKipcbiAgICAgKiBDYWNoZSBmb3IgUlVNIEphdmFTY3JpcHQgc25pcHBldHMsIHNjb3BlZCB0byB0aGUgd29ya2VyLlxuICAgICAqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgcnVtSmF2YVNjcmlwdENhY2hlOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xufVxuXG4vKipcbiAqIEZpZWxkIGRlc2NyaXB0aW9ucyBmb3IgY29uZmlndXJhdGlvbiBlcnJvciBtZXNzYWdlcy5cbiAqL1xuY29uc3QgRklFTERfREVTQ1JJUFRJT05TOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIGVuZHBvaW50VXJsOiBcIlRoZSBEeW5hdHJhY2UgZW52aXJvbm1lbnQgVVJMIChlLmcuLCBcXFwiaHR0cHM6Ly9hYmMxMjM0NS5saXZlLmR5bmF0cmFjZS5jb21cXFwiKVwiLFxuICAgIGFwcElkOiBcIlRoZSBSVU0gYXBwbGljYXRpb24gSUQgKGUuZy4sIFxcXCJBUFBMSUNBVElPTi1BQkNERUYwMTIzNDU2Nzg5XFxcIilcIixcbiAgICB0b2tlbjogXCJUaGUgQVBJIHRva2VuIHdpdGggXFxcIlJlYWQgUlVNIG1hbnVhbCBpbnNlcnRpb24gdGFnc1xcXCIgcGVybWlzc2lvblwiXG59O1xuXG5leHBvcnQgY29uc3QgdGVzdCA9IGJhc2UuZXh0ZW5kPER5bmF0cmFjZVRlc3RpbmdGaXh0dXJlLCBEeW5hdHJhY2VUZXN0aW5nV29ya2VyRml4dHVyZT4oe1xuICAgIGR5bmF0cmFjZUNvbmZpZzogW3tcbiAgICAgICAgYXBwSWQ6IFwiXCIsXG4gICAgICAgIGVuZHBvaW50VXJsOiBcIlwiLFxuICAgICAgICB0b2tlbjogXCJcIlxuICAgIH0sIHsgb3B0aW9uOiB0cnVlIH1dLFxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVtcHR5LXBhdHRlcm4gLS0gUGxheXdyaWdodCByZXF1aXJlcyBvYmplY3QgZGVzdHJ1Y3R1cmluZyBldmVuIHdoZW4gbm8gZGVwZW5kZW5jaWVzIGFyZSBuZWVkZWRcbiAgICBydW1KYXZhU2NyaXB0Q2FjaGU6IFthc3luYyAoeyB9LCB1c2UpID0+IHsgLy8gTk9TT05BUlxuICAgICAgICBjb25zdCBjYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgICAgIGF3YWl0IHVzZShjYWNoZSk7XG4gICAgfSwgeyBzY29wZTogXCJ3b3JrZXJcIiwgYXV0bzogdHJ1ZSwgYm94OiB0cnVlIH1dLFxuXG4gICAgZHluYXRyYWNlVGVzdGluZzogYXN5bmMgKFxuICAgICAgICB7IHBhZ2UsIGR5bmF0cmFjZUNvbmZpZywgcnVtSmF2YVNjcmlwdENhY2hlIH0sXG4gICAgICAgIHVzZSxcbiAgICAgICAgdGVzdEluZm86IFRlc3RJbmZvXG4gICAgKSA9PiB7XG4gICAgICAgIHZhbGlkYXRlRHluYXRyYWNlQ29uZmlnKGR5bmF0cmFjZUNvbmZpZyk7XG4gICAgICAgIHdhcm5JZlBhZ2VBbHJlYWR5TmF2aWdhdGVkKHBhZ2UpO1xuXG4gICAgICAgIGNvbnN0IHsgaWdub3JlV2FybmluZ3MgPSBbXSwgZHVtcEV2ZW50c09uRmFpbCA9IGZhbHNlIH0gPSBkeW5hdHJhY2VDb25maWc7XG4gICAgICAgIGNvbnN0IGNvbnRleHQ6IFRlc3RpbmdDb250ZXh0ID0ge1xuICAgICAgICAgICAgZXZlbnRzOiBbXSxcbiAgICAgICAgICAgIGJlYWNvbnM6IFtdLFxuICAgICAgICAgICAgd2FybmluZ3M6IFtdLFxuICAgICAgICAgICAgZHVtcEV2ZW50c09uRmFpbFxuICAgICAgICB9O1xuXG4gICAgICAgIHNldHVwQ29uc29sZVdhcm5pbmdMaXN0ZW5lcihwYWdlLCBpZ25vcmVXYXJuaW5ncywgY29udGV4dCk7XG4gICAgICAgIGF3YWl0IHNldHVwUnVtSmF2YVNjcmlwdEFuZExpc3RlbmVycyhwYWdlLCBkeW5hdHJhY2VDb25maWcsIHJ1bUphdmFTY3JpcHRDYWNoZSwgY29udGV4dCk7XG4gICAgICAgIGF3YWl0IHVzZShjcmVhdGVEeW5hdHJhY2VUZXN0aW5nQXBpKGNvbnRleHQsIHRlc3RJbmZvKSk7XG4gICAgfVxufSk7XG5cbi8qKlxuICogV2FybnMgaWYgdGhlIHBhZ2UgaGFzIGFscmVhZHkgbmF2aWdhdGVkIGF3YXkgZnJvbSBhYm91dDpibGFuay5cbiAqIFRoaXMgaW5kaWNhdGVzIHRoZSBmaXh0dXJlIG1heSBub3QgaW5qZWN0IFJVTSBKYXZhU2NyaXB0IGNvcnJlY3RseS5cbiAqXG4gKiBAcGFyYW0gcGFnZSBUaGUgUGxheXdyaWdodCBwYWdlIGluc3RhbmNlXG4gKi9cbmZ1bmN0aW9uIHdhcm5JZlBhZ2VBbHJlYWR5TmF2aWdhdGVkKHBhZ2U6IFBhZ2UpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50VXJsID0gcGFnZS51cmwoKTtcbiAgICBpZiAoY3VycmVudFVybCAhPT0gXCJhYm91dDpibGFua1wiKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgIGBbRHluYXRyYWNlIFRlc3RpbmddIFdhcm5pbmc6IFBhZ2UgaGFzIGFscmVhZHkgbmF2aWdhdGVkIHRvIFwiJHtjdXJyZW50VXJsfVwiLlxuVGhlIFJVTSBKYXZhU2NyaXB0IG1heSBub3QgYmUgaW5qZWN0ZWQuIEVuc3VyZSBkeW5hdHJhY2VUZXN0aW5nIGlzIGRlc3RydWN0dXJlZFxuYmVmb3JlIGFueSBmaXh0dXJlcyB0aGF0IG5hdmlnYXRlIHRoZSBwYWdlLlxuXG5FeGFtcGxlIG9mIGNvcnJlY3QgZml4dHVyZSBvcmRlcjpcbiAgICB0ZXN0KFwibXkgdGVzdFwiLCBhc3luYyAoeyBkeW5hdHJhY2VUZXN0aW5nLCBteUN1c3RvbUZpeHR1cmUsIHBhZ2UgfSkgPT4geyAuLi4gfSk7XG5cblNlZSB0ZXN0aW5nLm1kIGZvciBtb3JlIGluZm9ybWF0aW9uLmBcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbi8qKlxuICogU2V0cyB1cCBhIGNvbnNvbGUgbGlzdGVuZXIgdG8gY2FwdHVyZSBEeW5hdHJhY2UtcmVsYXRlZCB3YXJuaW5ncy5cbiAqXG4gKiBAcGFyYW0gcGFnZSAgICAgICAgICAgVGhlIFBsYXl3cmlnaHQgcGFnZSBpbnN0YW5jZVxuICogQHBhcmFtIGlnbm9yZVdhcm5pbmdzIEFycmF5IG9mIHJlZ2V4IHBhdHRlcm5zIGZvciB3YXJuaW5ncyB0byBpZ25vcmVcbiAqIEBwYXJhbSBjb250ZXh0ICAgICAgICBUaGUgdGVzdGluZyBjb250ZXh0IHRvIHN0b3JlIHdhcm5pbmdzXG4gKi9cbmZ1bmN0aW9uIHNldHVwQ29uc29sZVdhcm5pbmdMaXN0ZW5lcihcbiAgICBwYWdlOiBQYWdlLFxuICAgIGlnbm9yZVdhcm5pbmdzOiBzdHJpbmdbXSxcbiAgICBjb250ZXh0OiBUZXN0aW5nQ29udGV4dFxuKTogdm9pZCB7XG4gICAgY29uc3QgaWdub3JlUmVnZXhlcyA9IGlnbm9yZVdhcm5pbmdzLm1hcCh4ID0+IG5ldyBSZWdFeHAoeCwgXCJpXCIpKTtcbiAgICBwYWdlLm9uKFwiY29uc29sZVwiLCAobXNnKSA9PiB7XG4gICAgICAgIGlmIChtc2cudGV4dCgpLmluY2x1ZGVzKFwieW5hdHJhY2VcIikgJiYgIWlnbm9yZVJlZ2V4ZXMuc29tZShyZWdleCA9PiByZWdleC50ZXN0KG1zZy50ZXh0KCkpKSkge1xuICAgICAgICAgICAgY29udGV4dC53YXJuaW5ncy5wdXNoKG1zZy50ZXh0KCkpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogU2V0cyB1cCBSVU0gSmF2YVNjcmlwdCBpbmplY3Rpb24gYW5kIGJlYWNvbiByZXF1ZXN0IGxpc3RlbmVycy5cbiAqXG4gKiBAcGFyYW0gcGFnZSAgICBUaGUgUGxheXdyaWdodCBwYWdlIGluc3RhbmNlXG4gKiBAcGFyYW0gY29uZmlnICBUaGUgRHluYXRyYWNlIGNvbmZpZ3VyYXRpb25cbiAqIEBwYXJhbSBjYWNoZSAgIFRoZSB3b3JrZXItc2NvcGVkIGNhY2hlIGZvciBSVU0gSmF2YVNjcmlwdFxuICogQHBhcmFtIGNvbnRleHQgVGhlIHRlc3RpbmcgY29udGV4dCB0byBzdG9yZSBiZWFjb25zIGFuZCBldmVudHNcbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0dXBSdW1KYXZhU2NyaXB0QW5kTGlzdGVuZXJzKFxuICAgIHBhZ2U6IFBhZ2UsXG4gICAgY29uZmlnOiBEeW5hdHJhY2VDb25maWcsXG4gICAgY2FjaGU6IE1hcDxzdHJpbmcsIHN0cmluZz4sXG4gICAgY29udGV4dDogVGVzdGluZ0NvbnRleHRcbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgZW5kcG9pbnRVcmwsIGFwcElkLCB0b2tlbiB9ID0gY29uZmlnO1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gYCR7ZW5kcG9pbnRVcmx9OiR7YXBwSWR9YDtcbiAgICBsZXQgcnVtID0gY2FjaGUuZ2V0KGNhY2hlS2V5KTtcblxuICAgIGlmICghcnVtKSB7XG4gICAgICAgIHJ1bSA9IGF3YWl0IGZldGNoUnVtSmF2YVNjcmlwdENvbnRlbnQoZW5kcG9pbnRVcmwsIGFwcElkLCB0b2tlbik7XG4gICAgICAgIGNvbnN0IGJlYWNvblVyaSA9IGV4dHJhY3RCZWFjb25VcmkocnVtKTtcbiAgICAgICAgY2FjaGUuc2V0KGNhY2hlS2V5LCBydW0pO1xuICAgICAgICBjYWNoZS5zZXQoYCR7Y2FjaGVLZXl9OmJlYWNvblVyaWAsIGJlYWNvblVyaSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgYmVhY29uVXJpID0gY2FjaGUuZ2V0KGAke2NhY2hlS2V5fTpiZWFjb25VcmlgKTtcbiAgICAgICAgaWYgKCFiZWFjb25VcmkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byByZXRyaWV2ZSBiZWFjb25VcmkgZnJvbSBjYWNoZS5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwYWdlLm9uKFwicmVxdWVzdFwiLCAocmVxdWVzdCkgPT4ge1xuICAgICAgICBjb25zdCB1cmwgPSByZXF1ZXN0LnVybCgpO1xuICAgICAgICAvLyBHZW4gMyBiZWFjb25zIHNob3VsZCBhbHdheXMgaGF2ZSB0eT1qc1xuICAgICAgICBpZiAoIXVybC5pbmNsdWRlcyhcInR5PWpzXCIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYmVhY29uQm9keVN0cmluZyA9IGV4dHJhY3RCZWFjb25Cb2R5KHJlcXVlc3QsIHVybCk7XG4gICAgICAgIGlmICghYmVhY29uQm9keVN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBiZWFjb25Cb2R5OiB7XG4gICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICBldmVudHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gPSBKU09OLnBhcnNlKGJlYWNvbkJvZHlTdHJpbmcpO1xuICAgICAgICAgICAgY29udGV4dC5iZWFjb25zLnB1c2goe1xuICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgIGJvZHk6IGJlYWNvbkJvZHlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29udGV4dC5ldmVudHMucHVzaCguLi5iZWFjb25Cb2R5LmRhdGEuZXZlbnRzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJbRHluYXRyYWNlIFRlc3RpbmddIEZhaWxlZCB0byBwYXJzZSBiZWFjb24gYm9keTpcIiwgZXJyb3IpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBhd2FpdCBwYWdlLmFkZEluaXRTY3JpcHQocnVtKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBEeW5hdHJhY2VUZXN0aW5nIEFQSSBvYmplY3Qgd2l0aCBhbGwgdGVzdGluZyBtZXRob2RzLlxuICpcbiAqIEBwYXJhbSBjb250ZXh0ICBUaGUgdGVzdGluZyBjb250ZXh0IGNvbnRhaW5pbmcgZXZlbnRzLCBiZWFjb25zLCBhbmQgd2FybmluZ3NcbiAqIEBwYXJhbSB0ZXN0SW5mbyBUaGUgUGxheXdyaWdodCB0ZXN0IGluZm8gZm9yIHNuYXBzaG90IHBhdGhzXG4gKiBAcmV0dXJucyAgICAgICAgVGhlIER5bmF0cmFjZVRlc3RpbmcgQVBJIG9iamVjdFxuICovXG5mdW5jdGlvbiBjcmVhdGVEeW5hdHJhY2VUZXN0aW5nQXBpKGNvbnRleHQ6IFRlc3RpbmdDb250ZXh0LCB0ZXN0SW5mbzogVGVzdEluZm8pOiBEeW5hdHJhY2VUZXN0aW5nIHtcbiAgICBjb25zdCB7IGV2ZW50cywgYmVhY29ucywgd2FybmluZ3MgfSA9IGNvbnRleHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBhc3luYyB3YWl0Rm9yQmVhY29ucyhvcHRpb25zOiBXYWl0Rm9yQmVhY29uc09wdGlvbnMgPSB7fSk6IFByb21pc2U8QmVhY29uUmVxdWVzdFtdPiB7XG4gICAgICAgICAgICBjb25zdCB7IG1pbkNvdW50ID0gMCwgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVCB9ID0gb3B0aW9ucztcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcblxuICAgICAgICAgICAgd2hpbGUgKGJlYWNvbnMubGVuZ3RoIDwgbWluQ291bnQgJiYgKERhdGUubm93KCkgLSBzdGFydCkgPD0gdGltZW91dCkge1xuICAgICAgICAgICAgICAgIGlmICh3YXJuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICBcIlVuZXhwZWN0ZWQgRHluYXRyYWNlIEFQSSB3YXJuaW5nczogXCIgKyB3YXJuaW5ncy5qb2luKFwiXFxuXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJ3YWl0Rm9yQmVhY29ucyAtIHVuZXhwZWN0ZWQgd2FybmluZ3NcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhd2FpdCB3YWl0KDEwMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWFjb25zLmxlbmd0aCA8IG1pbkNvdW50KSB7XG4gICAgICAgICAgICAgICAgdGhyb3dXaXRoRXZlbnREdW1wKFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBgRm91bmQgb25seSAke2JlYWNvbnMubGVuZ3RofSBEeW5hdHJhY2UgYmVhY29ucyBhZnRlciB0aW1lb3V0IG9mICR7dGltZW91dH1tcywgYnV0IGV4cGVjdGVkIGF0IGxlYXN0ICR7bWluQ291bnR9LmAsXG4gICAgICAgICAgICAgICAgICAgIFwid2FpdEZvckJlYWNvbnMgLSB0aW1lb3V0XCJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gYmVhY29ucztcbiAgICAgICAgfSxcblxuICAgICAgICBhc3luYyBleHBlY3RUb0hhdmVTZW50RXZlbnQoXG4gICAgICAgICAgICBleHBlY3RlZEV2ZW50OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgICAgIG9wdGlvbnM6IEV4cGVjdE9wdGlvbnMgPSB7fVxuICAgICAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVCB9ID0gb3B0aW9ucztcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGxldCBsYXN0Tm9uTWF0Y2g6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkID0gdm9pZCAwO1xuICAgICAgICAgICAgbGV0IG5leHRDaGVja0luZGV4ID0gMDtcblxuICAgICAgICAgICAgd2hpbGUgKChEYXRlLm5vdygpIC0gc3RhcnQpIDw9IHRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gbmV4dENoZWNrSW5kZXg7IGkgPCBldmVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVhY29uRXZlbnQgPSBldmVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3QoYmVhY29uRXZlbnQpLnRvTWF0Y2hPYmplY3QoZXhwZWN0ZWRFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE5vbk1hdGNoID0gYmVhY29uRXZlbnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbmV4dENoZWNrSW5kZXggPSBpICsgMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWxhc3ROb25NYXRjaCkge1xuICAgICAgICAgICAgICAgIHRocm93V2l0aEV2ZW50RHVtcChcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgXCJEeW5hdHJhY2UgZGlkbid0IHNlbmQgYW55IGV2ZW50cy5cIixcbiAgICAgICAgICAgICAgICAgICAgXCJleHBlY3RUb0hhdmVTZW50RXZlbnQgLSBubyBldmVudHNcIlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGR1bXBFdmVudHNJZkVuYWJsZWQoY29udGV4dCwgXCJleHBlY3RUb0hhdmVTZW50RXZlbnQgLSBubyBtYXRjaFwiKTtcbiAgICAgICAgICAgIGV4cGVjdChsYXN0Tm9uTWF0Y2gpLnRvTWF0Y2hPYmplY3QoZXhwZWN0ZWRFdmVudCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgYXN5bmMgZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMoXG4gICAgICAgICAgICBleHBlY3RlZEV2ZW50OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICAgICAgICAgIHRpbWVzOiBudW1iZXIsXG4gICAgICAgICAgICBvcHRpb25zOiBFeHBlY3RPcHRpb25zID0ge31cbiAgICAgICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgICAgICBjb25zdCB7IHRpbWVvdXQgPSBERUZBVUxUX1RJTUVPVVQgfSA9IG9wdGlvbnM7XG4gICAgICAgICAgICBjb25zdCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBsZXQgbGFzdE5vbk1hdGNoOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZCA9IHZvaWQgMDtcbiAgICAgICAgICAgIGxldCBuZXh0Q2hlY2tJbmRleCA9IDA7XG4gICAgICAgICAgICBsZXQgZm91bmRUaW1lcyA9IDA7XG5cbiAgICAgICAgICAgIHdoaWxlICgoRGF0ZS5ub3coKSAtIHN0YXJ0KSA8PSB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IG5leHRDaGVja0luZGV4OyBpIDwgZXZlbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGJlYWNvbkV2ZW50ID0gZXZlbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0KGJlYWNvbkV2ZW50KS50b01hdGNoT2JqZWN0KGV4cGVjdGVkRXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm91bmRUaW1lcysrO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3ROb25NYXRjaCA9IGJlYWNvbkV2ZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG5leHRDaGVja0luZGV4ID0gaSArIDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmb3VuZFRpbWVzID09PSB0aW1lcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChmb3VuZFRpbWVzID4gdGltZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3dXaXRoRXZlbnREdW1wKFxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGBFeHBlY3RlZCAke3RpbWVzfSBldmVudCBvY2N1cnJlbmNlcywgZm91bmQgJHtmb3VuZFRpbWVzfS5gLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJleHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyAtIHRvbyBtYW55IG1hdGNoZXNcIlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhd2FpdCB3YWl0KDEwMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbGFzdE5vbk1hdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3dXaXRoRXZlbnREdW1wKFxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBcIkR5bmF0cmFjZSBkaWRuJ3Qgc2VuZCBhbnkgZXZlbnRzXCIsXG4gICAgICAgICAgICAgICAgICAgIFwiZXhwZWN0VG9IYXZlU2VudEV2ZW50VGltZXMgLSBubyBldmVudHNcIlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmb3VuZFRpbWVzIDwgdGltZXMpIHtcbiAgICAgICAgICAgICAgICB0aHJvd1dpdGhFdmVudER1bXAoXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgIGBEaWRuJ3QgZmluZCB0aGUgZXhwZWN0ZWQgYW1vdW50IG9mICR7dGltZXN9IG1hdGNoaW5nIGV2ZW50cywgZm91bmQgJHtmb3VuZFRpbWVzfS5gLFxuICAgICAgICAgICAgICAgICAgICBcImV4cGVjdFRvSGF2ZVNlbnRFdmVudFRpbWVzIC0gY291bnQgbWlzbWF0Y2hcIlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGR1bXBFdmVudHNJZkVuYWJsZWQoY29udGV4dCwgXCJleHBlY3RUb0hhdmVTZW50RXZlbnRUaW1lcyAtIG5vIG1hdGNoXCIpO1xuICAgICAgICAgICAgZXhwZWN0KGxhc3ROb25NYXRjaCkudG9NYXRjaE9iamVjdChleHBlY3RlZEV2ZW50KTtcbiAgICAgICAgfSxcblxuICAgICAgICBjbGVhckV2ZW50cygpOiB2b2lkIHtcbiAgICAgICAgICAgIGV2ZW50cy5sZW5ndGggPSAwO1xuICAgICAgICAgICAgYmVhY29ucy5sZW5ndGggPSAwO1xuICAgICAgICB9LFxuXG4gICAgICAgIHRvTWF0Y2hFdmVudFNuYXBzaG90KG9wdGlvbnM6IFNuYXBzaG90T3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICAgICAgaWdub3JlRXZlbnRzID0gWy4uLkRFRkFVTFRfSUdOT1JFRF9FVkVOVFNdLFxuICAgICAgICAgICAgICAgIGlnbm9yZWRGaWVsZHMgPSBbLi4uREVGQVVMVF9JR05PUkVEX0ZJRUxEU10sXG4gICAgICAgICAgICAgICAgcmVtb3ZlZEZpZWxkcyA9IFsuLi5ERUZBVUxUX1JFTU9WRURfRklFTERTXSxcbiAgICAgICAgICAgICAgICBuYW1lXG4gICAgICAgICAgICB9ID0gb3B0aW9ucztcblxuICAgICAgICAgICAgY29uc3Qgc25hcHNob3ROYW1lID0gbmFtZSA/PyBcImV2ZW50c1wiO1xuICAgICAgICAgICAgY29uc3Qgc25hcHNob3RQYXRoID0gdGVzdEluZm8uc25hcHNob3RQYXRoKGAke3NuYXBzaG90TmFtZX0uZXZlbnRzLnNuYXBgKTtcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZVNuYXBzaG90cyA9IHRlc3RJbmZvLmNvbmZpZy51cGRhdGVTbmFwc2hvdHMgPT09IFwiYWxsXCI7XG5cbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcmVkRXZlbnRzID0gZmlsdGVySWdub3JlZEV2ZW50cyhldmVudHMsIGlnbm9yZUV2ZW50cyk7XG4gICAgICAgICAgICBjb25zdCBwcm9jZXNzZWRFdmVudHMgPSBwcm9jZXNzRXZlbnRQcm9wZXJ0aWVzKGZpbHRlcmVkRXZlbnRzLCBpZ25vcmVkRmllbGRzLCByZW1vdmVkRmllbGRzKTtcbiAgICAgICAgICAgIGNvbnN0IHNuYXBzaG90UmVzdWx0ID0gcmVhZFNuYXBzaG90KHNuYXBzaG90UGF0aCk7XG5cbiAgICAgICAgICAgIGlmICghc25hcHNob3RSZXN1bHQuZXhpc3RzIHx8IHVwZGF0ZVNuYXBzaG90cykge1xuICAgICAgICAgICAgICAgIHdyaXRlU25hcHNob3Qoc25hcHNob3RQYXRoLCBwcm9jZXNzZWRFdmVudHMpO1xuICAgICAgICAgICAgICAgIGlmICghc25hcHNob3RSZXN1bHQuZXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbRHluYXRyYWNlIFRlc3RpbmddIENyZWF0ZWQgbmV3IHNuYXBzaG90OiAke3NuYXBzaG90UGF0aH1gKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgW0R5bmF0cmFjZSBUZXN0aW5nXSBVcGRhdGVkIHNuYXBzaG90OiAke3NuYXBzaG90UGF0aH1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBzbmFwc2hvdERhdGEgPSBzbmFwc2hvdFJlc3VsdC5kYXRhO1xuICAgICAgICAgICAgaWYgKCFzbmFwc2hvdERhdGEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKFwiW0R5bmF0cmFjZSBUZXN0aW5nXSBTbmFwc2hvdCBmaWxlIGlzIGVtcHR5XCIpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU29ydCBib3RoIGFycmF5cyBieSBjaGFyYWN0ZXJpc3RpY3MgZm9yIG9yZGVyLWluZGVwZW5kZW50IGNvbXBhcmlzb25cbiAgICAgICAgICAgIGNvbnN0IHNvcnRlZEFjdHVhbCA9IHNvcnRFdmVudHNCeUNoYXJhY3RlcmlzdGljcyhwcm9jZXNzZWRFdmVudHMpO1xuICAgICAgICAgICAgY29uc3Qgc29ydGVkRXhwZWN0ZWQgPSBzb3J0RXZlbnRzQnlDaGFyYWN0ZXJpc3RpY3Moc25hcHNob3REYXRhKTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyBVc2UgUGxheXdyaWdodCdzIGV4cGVjdCBmb3IgY29tcGFyaXNvbiAtIHByb3ZpZGVzIGV4Y2VsbGVudCBkaWZmIG91dHB1dFxuICAgICAgICAgICAgICAgIGV4cGVjdChzb3J0ZWRBY3R1YWwpLnRvU3RyaWN0RXF1YWwoc29ydGVkRXhwZWN0ZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgZHVtcEV2ZW50c0lmRW5hYmxlZChjb250ZXh0LCBcInRvTWF0Y2hFdmVudFNuYXBzaG90IC0gbWlzbWF0Y2hcIik7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYFtEeW5hdHJhY2UgVGVzdGluZ10gU25hcHNob3QgbWlzbWF0Y2ggZm9yIFwiJHtzbmFwc2hvdE5hbWV9XCIuXFxuXFxuYFxuICAgICAgICAgICAgICAgICAgICArIGBTbmFwc2hvdCBwYXRoOiAke3NuYXBzaG90UGF0aH1cXG5cXG5gXG4gICAgICAgICAgICAgICAgICAgICsgYCR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfVxcblxcbmBcbiAgICAgICAgICAgICAgICAgICAgKyBgVG8gdXBkYXRlIHRoZSBzbmFwc2hvdCwgcnVuIHdpdGggLS11cGRhdGUtc25hcHNob3RzIGZsYWcuYDtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGVycm9yTWVzc2FnZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbn1cblxuLyoqXG4gKiBEdW1wcyByZWNlaXZlZCBldmVudHMgdG8gY29uc29sZSBpZiBkdW1wRXZlbnRzT25GYWlsIGlzIGVuYWJsZWQuXG4gKlxuICogQHBhcmFtIGNvbnRleHQgICAgIFRoZSB0ZXN0aW5nIGNvbnRleHQgY29udGFpbmluZyBldmVudHMgYW5kIGJlYWNvbnNcbiAqIEBwYXJhbSBkZXNjcmlwdGlvbiBBZGRpdGlvbmFsIGNvbnRleHQgYWJvdXQgd2h5IGV2ZW50cyBhcmUgYmVpbmcgZHVtcGVkXG4gKi9cbmZ1bmN0aW9uIGR1bXBFdmVudHNJZkVuYWJsZWQoY29udGV4dDogVGVzdGluZ0NvbnRleHQsIGRlc2NyaXB0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIWNvbnRleHQuZHVtcEV2ZW50c09uRmFpbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coYFxcbltEeW5hdHJhY2UgVGVzdGluZ10gRXZlbnQgRHVtcCAoJHtkZXNjcmlwdGlvbn0pYCk7XG4gICAgY29uc29sZS5sb2coYFRvdGFsIGV2ZW50cyByZWNlaXZlZDogJHtjb250ZXh0LmV2ZW50cy5sZW5ndGh9YCk7XG4gICAgY29uc29sZS5sb2coYFRvdGFsIGJlYWNvbnMgcmVjZWl2ZWQ6ICR7Y29udGV4dC5iZWFjb25zLmxlbmd0aH1gKTtcblxuICAgIGlmIChjb250ZXh0LmV2ZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJObyBldmVudHMgd2VyZSByZWNlaXZlZC5cIik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJcXG5SZWNlaXZlZCBldmVudHM6XCIpO1xuICAgICAgICBjb250ZXh0LmV2ZW50cy5mb3JFYWNoKChldmVudCwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBcXG5FdmVudCAke2luZGV4ICsgMX06YCwgSlNPTi5zdHJpbmdpZnkoZXZlbnQsIG51bGwsIDIpKTtcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFRocm93cyBhbiBlcnJvciB3aXRoIGEgY3VzdG9tIG1lc3NhZ2UuIElmIGV2ZW50IGR1bXBpbmcgaXMgZW5hYmxlZCwgbG9ncyB0aGUgcmVjZWl2ZWQgRHluYXRyYWNlIGV2ZW50cyBiZWZvcmVcbiAqIHRocm93aW5nIHRoZSBlcnJvci5cbiAqXG4gKiBAcGFyYW0gY29udGV4dCAgICAgVGhlIHRlc3RpbmcgY29udGV4dCBmb3IgZXZlbnQgZHVtcGluZ1xuICogQHBhcmFtIG1lc3NhZ2UgICAgIFRoZSBlcnJvciBtZXNzYWdlIHRvIGJlIHRocm93blxuICogQHBhcmFtIGRlc2NyaXB0aW9uIENvbnRleHQgYWJvdXQgdGhlIGZhaWx1cmUgZm9yIGV2ZW50IGR1bXBpbmdcbiAqL1xuZnVuY3Rpb24gdGhyb3dXaXRoRXZlbnREdW1wKGNvbnRleHQ6IFRlc3RpbmdDb250ZXh0LCBtZXNzYWdlOiBzdHJpbmcsIGRlc2NyaXB0aW9uPzogc3RyaW5nKTogbmV2ZXIge1xuICAgIGR1bXBFdmVudHNJZkVuYWJsZWQoY29udGV4dCwgZGVzY3JpcHRpb24gPz8gXCJhc3NlcnRpb24gZmFpbHVyZVwiKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGhlbHBmdWwgZXJyb3IgZm9yIG1pc3NpbmcgY29uZmlndXJhdGlvbiBmaWVsZHMuXG4gKlxuICogQHBhcmFtIG1pc3NpbmdGaWVsZHMgQXJyYXkgb2YgZmllbGQgbmFtZXMgdGhhdCBhcmUgbWlzc2luZyBvciBlbXB0eVxuICogQHJldHVybnMgICAgICAgICAgICAgRXJyb3Igd2l0aCBkZXRhaWxlZCBzZXR1cCBpbnN0cnVjdGlvbnNcbiAqL1xuZnVuY3Rpb24gY3JlYXRlTWlzc2luZ0NvbmZpZ0Vycm9yKG1pc3NpbmdGaWVsZHM6IHN0cmluZ1tdKTogRXJyb3Ige1xuICAgIGNvbnN0IG1pc3NpbmdEZXRhaWxzID0gbWlzc2luZ0ZpZWxkc1xuICAgICAgICAubWFwKGZpZWxkID0+IGAgICAgLSAke2ZpZWxkfTogJHtGSUVMRF9ERVNDUklQVElPTlNbZmllbGRdfWApXG4gICAgICAgIC5qb2luKFwiXFxuXCIpO1xuXG4gICAgcmV0dXJuIG5ldyBFcnJvcihcbiAgICAgICAgYFtEeW5hdHJhY2UgVGVzdGluZ10gTWlzc2luZyByZXF1aXJlZCBjb25maWd1cmF0aW9uIGZpZWxkJHttaXNzaW5nRmllbGRzLmxlbmd0aCA+IDEgPyBcInNcIiA6IFwiXCJ9OiAke21pc3NpbmdGaWVsZHMuam9pbihcIiwgXCIpfVxuXG4ke21pc3NpbmdEZXRhaWxzfVxuXG5Db25maWd1cmUgdmlhIHRlc3QudXNlKCk6XG4gICAgdGVzdC51c2Uoe1xuICAgICAgICBkeW5hdHJhY2VDb25maWc6IHtcbiAgICAgICAgICAgIGVuZHBvaW50VXJsOiBwcm9jZXNzLmVudi5EVF9FTkRQT0lOVF9VUkwhLFxuICAgICAgICAgICAgYXBwSWQ6IHByb2Nlc3MuZW52LkRUX0FQUF9JRCEsXG4gICAgICAgICAgICB0b2tlbjogcHJvY2Vzcy5lbnYuRFRfVE9LRU4hXG4gICAgICAgIH1cbiAgICB9KTtcblxuU2VlIHRlc3RpbmcubWQgZm9yIGRldGFpbGVkIHNldHVwIGluc3RydWN0aW9ucy5gXG4gICAgKTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdGhlIER5bmF0cmFjZSBjb25maWd1cmF0aW9uIGFuZCB0aHJvd3MgYSBoZWxwZnVsIGVycm9yIGlmIGludmFsaWQuXG4gKlxuICogQHBhcmFtIGNvbmZpZyBUaGUgY29uZmlndXJhdGlvbiB0byB2YWxpZGF0ZVxuICogQHRocm93cyBFcnJvciB3aXRoIGRldGFpbGVkIHNldHVwIGluc3RydWN0aW9ucyBpZiBjb25maWd1cmF0aW9uIGlzIGludmFsaWRcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVEeW5hdHJhY2VDb25maWcoY29uZmlnOiBEeW5hdHJhY2VDb25maWcpOiB2b2lkIHtcbiAgICBjb25zdCBtaXNzaW5nRmllbGRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKCFjb25maWcuZW5kcG9pbnRVcmwgfHwgY29uZmlnLmVuZHBvaW50VXJsLnRyaW0oKSA9PT0gXCJcIikge1xuICAgICAgICBtaXNzaW5nRmllbGRzLnB1c2goXCJlbmRwb2ludFVybFwiKTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbmZpZy5hcHBJZCB8fCBjb25maWcuYXBwSWQudHJpbSgpID09PSBcIlwiKSB7XG4gICAgICAgIG1pc3NpbmdGaWVsZHMucHVzaChcImFwcElkXCIpO1xuICAgIH1cblxuICAgIGlmICghY29uZmlnLnRva2VuIHx8IGNvbmZpZy50b2tlbi50cmltKCkgPT09IFwiXCIpIHtcbiAgICAgICAgbWlzc2luZ0ZpZWxkcy5wdXNoKFwidG9rZW5cIik7XG4gICAgfVxuXG4gICAgaWYgKG1pc3NpbmdGaWVsZHMubGVuZ3RoID4gMCkge1xuICAgICAgICB0aHJvdyBjcmVhdGVNaXNzaW5nQ29uZmlnRXJyb3IobWlzc2luZ0ZpZWxkcyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIFJVTSBKYXZhU2NyaXB0IGNvbnRlbnQgZnJvbSB0aGUgRHluYXRyYWNlIEFQSSBlbmRwb2ludC5cbiAqXG4gKiBAcGFyYW0gZW5kcG9pbnRVcmwgVGhlIFVSTCBvZiB0aGUgRHluYXRyYWNlIEFQSSBlbmRwb2ludFxuICogQHBhcmFtIGFwcElkICAgICAgIFRoZSBhcHBsaWNhdGlvbiBJRCB0byBpZGVudGlmeSB0aGUgY29ycmVjdCBSVU0gSmF2YVNjcmlwdFxuICogQHBhcmFtIHRva2VuICAgICAgIFRoZSBhdXRoZW50aWNhdGlvbiB0b2tlbiBmb3IgdGhlIGluc3RhbGxhdGlvblxuICogQHJldHVybnMgICAgICAgICAgIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBSVU0gSmF2YVNjcmlwdCBjb250ZW50XG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZldGNoUnVtSmF2YVNjcmlwdENvbnRlbnQoZW5kcG9pbnRVcmw6IHN0cmluZywgYXBwSWQ6IHN0cmluZywgdG9rZW46IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgcnVtQXBpUmVzdWx0ID0gYXdhaXQgZmV0Y2hSdW1KYXZhU2NyaXB0KGVuZHBvaW50VXJsLCBhcHBJZCwgdG9rZW4pO1xuICAgIGlmICghcnVtQXBpUmVzdWx0LmluY2x1ZGVzKFwiX2NvbXBsZXRlLmpzXCIpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRHluYXRyYWNlIHJlY2VpdmVkIHVuZXhwZWN0ZWQgUlVNIEphdmFTY3JpcHQgd2hlbiByZXF1ZXN0aW5nIHRoZSBKYXZhU2NyaXB0IFRhZyB2aWEgQVBJOiAke3J1bUFwaVJlc3VsdH1gKTtcbiAgICB9XG5cbiAgICAvLyBFeHRyYWN0IHRoZSBzcmMgVVJMIGZyb20gdGhlIHNjcmlwdCB0YWdcbiAgICBjb25zdCBzcmNNYXRjaCA9IHJ1bUFwaVJlc3VsdC5tYXRjaCgvc3JjPVwiKFteXCJdKylcIi8pO1xuICAgIGlmICghc3JjTWF0Y2gpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGV4dHJhY3Qgc3JjIFVSTCBmcm9tIFJVTSBKYXZhU2NyaXB0IHRhZy5cIik7XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdFVybCA9IHNyY01hdGNoWzFdO1xuXG4gICAgLy8gRmV0Y2ggdGhlIGFjdHVhbCBKYXZhU2NyaXB0IGNvbnRlbnRcbiAgICBjb25zdCBzY3JpcHRSZXNwb25zZSA9IGF3YWl0IGZldGNoKHNjcmlwdFVybCk7XG4gICAgcmV0dXJuIHNjcmlwdFJlc3BvbnNlLnRleHQoKTtcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyB0aGUgYmVhY29uIFVSSSBmcm9tIHRoZSBSVU0gSmF2YVNjcmlwdCBjb250ZW50LlxuICpcbiAqIEBwYXJhbSBydW0gVGhlIFJVTSBKYXZhU2NyaXB0IGNvbnRlbnQgdG8gZXh0cmFjdCB0aGUgYmVhY29uIFVSSSBmcm9tXG4gKiBAcmV0dXJucyAgIFRoZSBleHRyYWN0ZWQgYmVhY29uIFVSSVxuICovXG5mdW5jdGlvbiBleHRyYWN0QmVhY29uVXJpKHJ1bTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBFeHRyYWN0IHRoZSBiZWFjb25VcmkgZnJvbSB0aGUgSmF2YVNjcmlwdCBjb250ZW50XG4gICAgY29uc3QgYmVhY29uVXJpTWF0Y2ggPSBydW0ubWF0Y2goL1wiYmVhY29uVXJpXCI6XCIoW15cIl0rKVwiLyk7XG4gICAgaWYgKCFiZWFjb25VcmlNYXRjaCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gZXh0cmFjdCBiZWFjb25VcmkgZnJvbSBSVU0gSmF2YVNjcmlwdCBjb250ZW50LlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIGJlYWNvblVyaU1hdGNoWzFdO1xufVxuXG4vKipcbiAqIFdhaXRzIGZvciBhIGdpdmVuIHRpbWUgYW5kIHJlc29sdmVzIHVwb24gdGltZW91dC5cbiAqXG4gKiBAcGFyYW0gdGltZSBUaGUgdGltZSB0byB3YWl0IGluIG1pbGxpc2Vjb25kc1xuICogQHJldHVybnMgICAgQSByZXNvbHZlZCBwcm9taXNlIHdoZW4gdGhlIHRpbWUgcmFuIG91dFxuICovXG5mdW5jdGlvbiB3YWl0KHRpbWU6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIHRpbWUpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHRoZSBib2R5IG9mIGEgYmVhY29uIHJlcXVlc3QsIG9wdGlvbmFsbHkgZGVjb21wcmVzc2luZyBpdCBpZiB0aGUgVVJMIGluZGljYXRlcyBjb21wcmVzc2VkIGRhdGEuXG4gKlxuICogQHBhcmFtIHJlcXVlc3QgVGhlIHJlcXVlc3Qgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGJlYWNvbiBkYXRhXG4gKiBAcGFyYW0gdXJsICAgICBUaGUgVVJMIG9mIHRoZSByZXF1ZXN0IHRvIGNoZWNrIGZvciBzcGVjaWZpYyBjb21wcmVzc2lvbiBpbmRpY2F0b3JzXG4gKiBAcmV0dXJucyAgICAgICBUaGUgZXh0cmFjdGVkIGJvZHkgb2YgdGhlIGJlYWNvbiByZXF1ZXN0LCBvciBudWxsIGlmIG5vIHJlcXVlc3QgYm9keSBpcyBwcmVzZW50XG4gKi9cbmZ1bmN0aW9uIGV4dHJhY3RCZWFjb25Cb2R5KHJlcXVlc3Q6IFJlcXVlc3QsIHVybDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgYnVmZmVyID0gcmVxdWVzdC5wb3N0RGF0YUJ1ZmZlcigpO1xuICAgIGlmICh1cmwuaW5jbHVkZXMoXCJjbz1zbmFwcHlcIikgJiYgYnVmZmVyKSB7XG4gICAgICAgIGNvbnN0IHVpbnQ4RGF0YSA9IHVuY29tcHJlc3MoYnVmZmVyKTtcbiAgICAgICAgcmV0dXJuIGRlY29kZXIuZGVjb2RlKHVpbnQ4RGF0YSk7XG4gICAgfVxuICAgIHJldHVybiByZXF1ZXN0LnBvc3REYXRhKCk7XG59XG4iXX0=