@smoothdeploy/playwright-core 1.57.1 → 1.58.1-beta-1770452953000

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.

Potentially problematic release.


This version of @smoothdeploy/playwright-core might be problematic. Click here for more details.

Files changed (155) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +35 -0
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/channelOwner.js +4 -3
  9. package/lib/client/clientInstrumentation.js +10 -0
  10. package/lib/client/connection.js +4 -0
  11. package/lib/client/elementHandle.js +3 -0
  12. package/lib/client/events.js +3 -0
  13. package/lib/client/fetch.js +3 -4
  14. package/lib/client/frame.js +1 -0
  15. package/lib/client/page.js +28 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/generated/injectedScriptSource.js +1 -1
  19. package/lib/generated/pollingRecorderSource.js +1 -1
  20. package/lib/mcpBundle.js +84 -0
  21. package/lib/mcpBundleImpl/index.js +147 -0
  22. package/lib/protocol/serializers.js +5 -0
  23. package/lib/protocol/validator.js +92 -3
  24. package/lib/remote/playwrightServer.js +1 -2
  25. package/lib/server/agent/actionRunner.js +335 -0
  26. package/lib/server/agent/actions.js +128 -0
  27. package/lib/server/agent/codegen.js +111 -0
  28. package/lib/server/agent/context.js +150 -0
  29. package/lib/server/agent/expectTools.js +156 -0
  30. package/lib/server/agent/pageAgent.js +204 -0
  31. package/lib/server/agent/performTools.js +262 -0
  32. package/lib/server/agent/tool.js +109 -0
  33. package/lib/server/artifact.js +1 -1
  34. package/lib/server/bidi/bidiBrowser.js +56 -12
  35. package/lib/server/bidi/bidiChromium.js +6 -11
  36. package/lib/server/bidi/bidiConnection.js +1 -0
  37. package/lib/server/bidi/bidiDeserializer.js +116 -0
  38. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  39. package/lib/server/bidi/bidiFirefox.js +6 -8
  40. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  41. package/lib/server/bidi/bidiPage.js +39 -28
  42. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  43. package/lib/server/browserContext.js +32 -25
  44. package/lib/server/browserType.js +12 -4
  45. package/lib/server/chromium/chromium.js +14 -21
  46. package/lib/server/chromium/chromiumSwitches.js +2 -2
  47. package/lib/server/chromium/crBrowser.js +22 -12
  48. package/lib/server/chromium/crConnection.js +0 -5
  49. package/lib/server/chromium/crDevTools.js +0 -2
  50. package/lib/server/chromium/crNetworkManager.js +43 -2
  51. package/lib/server/chromium/crPage.js +19 -87
  52. package/lib/server/codegen/javascript.js +6 -29
  53. package/lib/server/deviceDescriptorsSource.json +56 -56
  54. package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
  55. package/lib/server/dispatchers/dispatcher.js +6 -13
  56. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  57. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  58. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  59. package/lib/server/dom.js +12 -3
  60. package/lib/server/electron/electron.js +5 -2
  61. package/lib/server/firefox/ffBrowser.js +10 -20
  62. package/lib/server/firefox/ffConnection.js +0 -5
  63. package/lib/server/firefox/ffNetworkManager.js +2 -2
  64. package/lib/server/firefox/ffPage.js +15 -18
  65. package/lib/server/firefox/firefox.js +6 -8
  66. package/lib/server/frameSelectors.js +9 -3
  67. package/lib/server/frames.js +49 -33
  68. package/lib/server/instrumentation.js +3 -0
  69. package/lib/server/network.js +50 -12
  70. package/lib/server/page.js +33 -89
  71. package/lib/server/progress.js +26 -6
  72. package/lib/server/recorder/recorderApp.js +79 -100
  73. package/lib/server/recorder.js +55 -0
  74. package/lib/server/registry/browserFetcher.js +6 -4
  75. package/lib/server/registry/index.js +172 -149
  76. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  77. package/lib/server/screencast.js +190 -0
  78. package/lib/server/screenshotCompositor.js +153 -0
  79. package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
  80. package/lib/server/trace/recorder/tracing.js +21 -21
  81. package/lib/server/trace/viewer/traceParser.js +72 -0
  82. package/lib/server/trace/viewer/traceViewer.js +17 -13
  83. package/lib/server/utils/expectUtils.js +87 -2
  84. package/lib/server/utils/httpServer.js +4 -19
  85. package/lib/server/utils/network.js +37 -28
  86. package/lib/server/utils/nodePlatform.js +6 -0
  87. package/lib/server/videoRecorder.js +124 -0
  88. package/lib/server/webkit/webkit.js +4 -6
  89. package/lib/server/webkit/wkBrowser.js +2 -6
  90. package/lib/server/webkit/wkConnection.js +1 -6
  91. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  92. package/lib/server/webkit/wkPage.js +75 -46
  93. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  94. package/lib/utils/isomorphic/lruCache.js +51 -0
  95. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  96. package/lib/utils/isomorphic/stringUtils.js +49 -0
  97. package/lib/utils/isomorphic/trace/entries.js +16 -0
  98. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  99. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  100. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  101. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  102. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  103. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  104. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  105. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  106. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  107. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  108. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  109. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  110. package/lib/utils/isomorphic/yaml.js +84 -0
  111. package/lib/utils.js +2 -0
  112. package/lib/utilsBundle.js +2 -5
  113. package/lib/utilsBundleImpl/index.js +165 -165
  114. package/lib/vite/htmlReport/index.html +21 -21
  115. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  116. package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
  117. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  118. package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
  119. package/lib/vite/recorder/index.html +2 -2
  120. package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
  121. package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
  122. package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
  123. package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
  124. package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
  125. package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
  126. package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
  128. package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
  129. package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
  130. package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
  131. package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
  132. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
  133. package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
  134. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  135. package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
  136. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  137. package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
  138. package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
  139. package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
  140. package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
  141. package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
  142. package/lib/vite/traceViewer/index.html +4 -4
  143. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  144. package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
  145. package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
  146. package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
  147. package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
  148. package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
  149. package/lib/vite/traceViewer/uiMode.html +3 -3
  150. package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
  151. package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
  152. package/package.json +3 -1
  153. package/types/protocol.d.ts +738 -159
  154. package/types/types.d.ts +25 -38
  155. package/lib/vite/recorder/assets/index-DJqDAOZp.js +0 -193
@@ -0,0 +1,1829 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./assets/xtermModule-DDw6eROI.js","./xtermModule.BKlWQB97.css"])))=>i.map(i=>d[i]);
2
+ import { u as useMeasure, r as reactExports, f as currentTheme, _ as __vitePreload, g as addThemeListener, h as removeThemeListener, j as jsxRuntimeExports, R as React, E as Expandable, s as settings, i as clsx, k as TreeView, t as testStatusIcon, m as msToString, l as Toolbar, n as ToolbarButton, M as MultiTraceModel, b as Workbench, o as useSetting, T as TestServerConnection, W as WebSocketTestServerTransport, S as SplitView, p as SettingsView, a as DefaultSettingsView, d as applyTheme, e as clientExports } from "./assets/defaultSettingsView-D4fm31R-.js";
3
+ var define_process_env_default = {};
4
+ class TeleReporterReceiver {
5
+ constructor(reporter, options = {}) {
6
+ this.isListing = false;
7
+ this._tests = /* @__PURE__ */ new Map();
8
+ this._rootSuite = new TeleSuite("", "root");
9
+ this._options = options;
10
+ this._reporter = reporter;
11
+ }
12
+ reset() {
13
+ this._rootSuite._entries = [];
14
+ this._tests.clear();
15
+ }
16
+ dispatch(message) {
17
+ const { method, params } = message;
18
+ if (method === "onConfigure") {
19
+ this._onConfigure(params.config);
20
+ return;
21
+ }
22
+ if (method === "onProject") {
23
+ this._onProject(params.project);
24
+ return;
25
+ }
26
+ if (method === "onBegin") {
27
+ this._onBegin();
28
+ return;
29
+ }
30
+ if (method === "onTestBegin") {
31
+ this._onTestBegin(params.testId, params.result);
32
+ return;
33
+ }
34
+ if (method === "onTestEnd") {
35
+ this._onTestEnd(params.test, params.result);
36
+ return;
37
+ }
38
+ if (method === "onStepBegin") {
39
+ this._onStepBegin(params.testId, params.resultId, params.step);
40
+ return;
41
+ }
42
+ if (method === "onAttach") {
43
+ this._onAttach(params.testId, params.resultId, params.attachments);
44
+ return;
45
+ }
46
+ if (method === "onStepEnd") {
47
+ this._onStepEnd(params.testId, params.resultId, params.step);
48
+ return;
49
+ }
50
+ if (method === "onError") {
51
+ this._onError(params.error);
52
+ return;
53
+ }
54
+ if (method === "onStdIO") {
55
+ this._onStdIO(params.type, params.testId, params.resultId, params.data, params.isBase64);
56
+ return;
57
+ }
58
+ if (method === "onEnd")
59
+ return this._onEnd(params.result);
60
+ if (method === "onExit")
61
+ return this._onExit();
62
+ }
63
+ _onConfigure(config) {
64
+ var _a, _b;
65
+ this._rootDir = config.rootDir;
66
+ this._config = this._parseConfig(config);
67
+ (_b = (_a = this._reporter).onConfigure) == null ? void 0 : _b.call(_a, this._config);
68
+ }
69
+ _onProject(project) {
70
+ let projectSuite = this._options.mergeProjects ? this._rootSuite.suites.find((suite) => suite.project().name === project.name) : void 0;
71
+ if (!projectSuite) {
72
+ projectSuite = new TeleSuite(project.name, "project");
73
+ this._rootSuite._addSuite(projectSuite);
74
+ }
75
+ projectSuite._project = this._parseProject(project);
76
+ for (const suite of project.suites)
77
+ this._mergeSuiteInto(suite, projectSuite);
78
+ }
79
+ _onBegin() {
80
+ var _a, _b;
81
+ (_b = (_a = this._reporter).onBegin) == null ? void 0 : _b.call(_a, this._rootSuite);
82
+ }
83
+ _onTestBegin(testId, payload) {
84
+ var _a, _b;
85
+ const test = this._tests.get(testId);
86
+ if (this._options.clearPreviousResultsWhenTestBegins)
87
+ test.results = [];
88
+ const testResult = test._createTestResult(payload.id);
89
+ testResult.retry = payload.retry;
90
+ testResult.workerIndex = payload.workerIndex;
91
+ testResult.parallelIndex = payload.parallelIndex;
92
+ testResult.setStartTimeNumber(payload.startTime);
93
+ (_b = (_a = this._reporter).onTestBegin) == null ? void 0 : _b.call(_a, test, testResult);
94
+ }
95
+ _onTestEnd(testEndPayload, payload) {
96
+ var _a, _b, _c;
97
+ const test = this._tests.get(testEndPayload.testId);
98
+ test.timeout = testEndPayload.timeout;
99
+ test.expectedStatus = testEndPayload.expectedStatus;
100
+ const result = test.results.find((r) => r._id === payload.id);
101
+ result.duration = payload.duration;
102
+ result.status = payload.status;
103
+ result.errors = payload.errors;
104
+ result.error = (_a = result.errors) == null ? void 0 : _a[0];
105
+ if (!!payload.attachments)
106
+ result.attachments = this._parseAttachments(payload.attachments);
107
+ if (payload.annotations) {
108
+ this._absoluteAnnotationLocationsInplace(payload.annotations);
109
+ result.annotations = payload.annotations;
110
+ test.annotations = payload.annotations;
111
+ }
112
+ (_c = (_b = this._reporter).onTestEnd) == null ? void 0 : _c.call(_b, test, result);
113
+ result._stepMap = /* @__PURE__ */ new Map();
114
+ }
115
+ _onStepBegin(testId, resultId, payload) {
116
+ var _a, _b;
117
+ const test = this._tests.get(testId);
118
+ const result = test.results.find((r) => r._id === resultId);
119
+ const parentStep = payload.parentStepId ? result._stepMap.get(payload.parentStepId) : void 0;
120
+ const location = this._absoluteLocation(payload.location);
121
+ const step = new TeleTestStep(payload, parentStep, location, result);
122
+ if (parentStep)
123
+ parentStep.steps.push(step);
124
+ else
125
+ result.steps.push(step);
126
+ result._stepMap.set(payload.id, step);
127
+ (_b = (_a = this._reporter).onStepBegin) == null ? void 0 : _b.call(_a, test, result, step);
128
+ }
129
+ _onStepEnd(testId, resultId, payload) {
130
+ var _a, _b;
131
+ const test = this._tests.get(testId);
132
+ const result = test.results.find((r) => r._id === resultId);
133
+ const step = result._stepMap.get(payload.id);
134
+ step._endPayload = payload;
135
+ step.duration = payload.duration;
136
+ step.error = payload.error;
137
+ (_b = (_a = this._reporter).onStepEnd) == null ? void 0 : _b.call(_a, test, result, step);
138
+ }
139
+ _onAttach(testId, resultId, attachments) {
140
+ const test = this._tests.get(testId);
141
+ const result = test.results.find((r) => r._id === resultId);
142
+ result.attachments.push(...attachments.map((a) => ({
143
+ name: a.name,
144
+ contentType: a.contentType,
145
+ path: a.path,
146
+ body: a.base64 && globalThis.Buffer ? Buffer.from(a.base64, "base64") : void 0
147
+ })));
148
+ }
149
+ _onError(error) {
150
+ var _a, _b;
151
+ (_b = (_a = this._reporter).onError) == null ? void 0 : _b.call(_a, error);
152
+ }
153
+ _onStdIO(type, testId, resultId, data, isBase64) {
154
+ var _a, _b, _c, _d;
155
+ const chunk = isBase64 ? globalThis.Buffer ? Buffer.from(data, "base64") : atob(data) : data;
156
+ const test = testId ? this._tests.get(testId) : void 0;
157
+ const result = test && resultId ? test.results.find((r) => r._id === resultId) : void 0;
158
+ if (type === "stdout") {
159
+ result == null ? void 0 : result.stdout.push(chunk);
160
+ (_b = (_a = this._reporter).onStdOut) == null ? void 0 : _b.call(_a, chunk, test, result);
161
+ } else {
162
+ result == null ? void 0 : result.stderr.push(chunk);
163
+ (_d = (_c = this._reporter).onStdErr) == null ? void 0 : _d.call(_c, chunk, test, result);
164
+ }
165
+ }
166
+ async _onEnd(result) {
167
+ var _a, _b;
168
+ await ((_b = (_a = this._reporter).onEnd) == null ? void 0 : _b.call(_a, {
169
+ status: result.status,
170
+ startTime: new Date(result.startTime),
171
+ duration: result.duration
172
+ }));
173
+ }
174
+ _onExit() {
175
+ var _a, _b;
176
+ return (_b = (_a = this._reporter).onExit) == null ? void 0 : _b.call(_a);
177
+ }
178
+ _parseConfig(config) {
179
+ const result = { ...baseFullConfig, ...config };
180
+ if (this._options.configOverrides) {
181
+ result.configFile = this._options.configOverrides.configFile;
182
+ result.reportSlowTests = this._options.configOverrides.reportSlowTests;
183
+ result.quiet = this._options.configOverrides.quiet;
184
+ result.reporter = [...this._options.configOverrides.reporter];
185
+ }
186
+ return result;
187
+ }
188
+ _parseProject(project) {
189
+ return {
190
+ metadata: project.metadata,
191
+ name: project.name,
192
+ outputDir: this._absolutePath(project.outputDir),
193
+ repeatEach: project.repeatEach,
194
+ retries: project.retries,
195
+ testDir: this._absolutePath(project.testDir),
196
+ testIgnore: parseRegexPatterns(project.testIgnore),
197
+ testMatch: parseRegexPatterns(project.testMatch),
198
+ timeout: project.timeout,
199
+ grep: parseRegexPatterns(project.grep),
200
+ grepInvert: parseRegexPatterns(project.grepInvert),
201
+ dependencies: project.dependencies,
202
+ teardown: project.teardown,
203
+ snapshotDir: this._absolutePath(project.snapshotDir),
204
+ use: project.use
205
+ };
206
+ }
207
+ _parseAttachments(attachments) {
208
+ return attachments.map((a) => {
209
+ return {
210
+ ...a,
211
+ body: a.base64 && globalThis.Buffer ? Buffer.from(a.base64, "base64") : void 0
212
+ };
213
+ });
214
+ }
215
+ _mergeSuiteInto(jsonSuite, parent) {
216
+ let targetSuite = parent.suites.find((s) => s.title === jsonSuite.title);
217
+ if (!targetSuite) {
218
+ targetSuite = new TeleSuite(jsonSuite.title, parent.type === "project" ? "file" : "describe");
219
+ parent._addSuite(targetSuite);
220
+ }
221
+ targetSuite.location = this._absoluteLocation(jsonSuite.location);
222
+ jsonSuite.entries.forEach((e) => {
223
+ if ("testId" in e)
224
+ this._mergeTestInto(e, targetSuite);
225
+ else
226
+ this._mergeSuiteInto(e, targetSuite);
227
+ });
228
+ }
229
+ _mergeTestInto(jsonTest, parent) {
230
+ let targetTest = this._options.mergeTestCases ? parent.tests.find((s) => s.title === jsonTest.title && s.repeatEachIndex === jsonTest.repeatEachIndex) : void 0;
231
+ if (!targetTest) {
232
+ targetTest = new TeleTestCase(jsonTest.testId, jsonTest.title, this._absoluteLocation(jsonTest.location), jsonTest.repeatEachIndex);
233
+ parent._addTest(targetTest);
234
+ this._tests.set(targetTest.id, targetTest);
235
+ }
236
+ this._updateTest(jsonTest, targetTest);
237
+ }
238
+ _updateTest(payload, test) {
239
+ test.id = payload.testId;
240
+ test.location = this._absoluteLocation(payload.location);
241
+ test.retries = payload.retries;
242
+ test.tags = payload.tags ?? [];
243
+ test.annotations = payload.annotations ?? [];
244
+ this._absoluteAnnotationLocationsInplace(test.annotations);
245
+ return test;
246
+ }
247
+ _absoluteAnnotationLocationsInplace(annotations) {
248
+ for (const annotation of annotations) {
249
+ if (annotation.location)
250
+ annotation.location = this._absoluteLocation(annotation.location);
251
+ }
252
+ }
253
+ _absoluteLocation(location) {
254
+ if (!location)
255
+ return location;
256
+ return {
257
+ ...location,
258
+ file: this._absolutePath(location.file)
259
+ };
260
+ }
261
+ _absolutePath(relativePath) {
262
+ if (relativePath === void 0)
263
+ return;
264
+ return this._options.resolvePath ? this._options.resolvePath(this._rootDir, relativePath) : this._rootDir + "/" + relativePath;
265
+ }
266
+ }
267
+ class TeleSuite {
268
+ constructor(title, type) {
269
+ this._entries = [];
270
+ this._requireFile = "";
271
+ this._parallelMode = "none";
272
+ this.title = title;
273
+ this._type = type;
274
+ }
275
+ get type() {
276
+ return this._type;
277
+ }
278
+ get suites() {
279
+ return this._entries.filter((e) => e.type !== "test");
280
+ }
281
+ get tests() {
282
+ return this._entries.filter((e) => e.type === "test");
283
+ }
284
+ entries() {
285
+ return this._entries;
286
+ }
287
+ allTests() {
288
+ const result = [];
289
+ const visit = (suite) => {
290
+ for (const entry of suite.entries()) {
291
+ if (entry.type === "test")
292
+ result.push(entry);
293
+ else
294
+ visit(entry);
295
+ }
296
+ };
297
+ visit(this);
298
+ return result;
299
+ }
300
+ titlePath() {
301
+ const titlePath = this.parent ? this.parent.titlePath() : [];
302
+ if (this.title || this._type !== "describe")
303
+ titlePath.push(this.title);
304
+ return titlePath;
305
+ }
306
+ project() {
307
+ var _a;
308
+ return this._project ?? ((_a = this.parent) == null ? void 0 : _a.project());
309
+ }
310
+ _addTest(test) {
311
+ test.parent = this;
312
+ this._entries.push(test);
313
+ }
314
+ _addSuite(suite) {
315
+ suite.parent = this;
316
+ this._entries.push(suite);
317
+ }
318
+ }
319
+ class TeleTestCase {
320
+ constructor(id, title, location, repeatEachIndex) {
321
+ this.fn = () => {
322
+ };
323
+ this.results = [];
324
+ this.type = "test";
325
+ this.expectedStatus = "passed";
326
+ this.timeout = 0;
327
+ this.annotations = [];
328
+ this.retries = 0;
329
+ this.tags = [];
330
+ this.repeatEachIndex = 0;
331
+ this.id = id;
332
+ this.title = title;
333
+ this.location = location;
334
+ this.repeatEachIndex = repeatEachIndex;
335
+ }
336
+ titlePath() {
337
+ const titlePath = this.parent ? this.parent.titlePath() : [];
338
+ titlePath.push(this.title);
339
+ return titlePath;
340
+ }
341
+ outcome() {
342
+ return computeTestCaseOutcome(this);
343
+ }
344
+ ok() {
345
+ const status = this.outcome();
346
+ return status === "expected" || status === "flaky" || status === "skipped";
347
+ }
348
+ _createTestResult(id) {
349
+ const result = new TeleTestResult(this.results.length, id);
350
+ this.results.push(result);
351
+ return result;
352
+ }
353
+ }
354
+ class TeleTestStep {
355
+ constructor(payload, parentStep, location, result) {
356
+ this.duration = -1;
357
+ this.steps = [];
358
+ this._startTime = 0;
359
+ this.title = payload.title;
360
+ this.category = payload.category;
361
+ this.location = location;
362
+ this.parent = parentStep;
363
+ this._startTime = payload.startTime;
364
+ this._result = result;
365
+ }
366
+ titlePath() {
367
+ var _a;
368
+ const parentPath = ((_a = this.parent) == null ? void 0 : _a.titlePath()) || [];
369
+ return [...parentPath, this.title];
370
+ }
371
+ get startTime() {
372
+ return new Date(this._startTime);
373
+ }
374
+ set startTime(value) {
375
+ this._startTime = +value;
376
+ }
377
+ get attachments() {
378
+ var _a, _b;
379
+ return ((_b = (_a = this._endPayload) == null ? void 0 : _a.attachments) == null ? void 0 : _b.map((index) => this._result.attachments[index])) ?? [];
380
+ }
381
+ get annotations() {
382
+ var _a;
383
+ return ((_a = this._endPayload) == null ? void 0 : _a.annotations) ?? [];
384
+ }
385
+ }
386
+ class TeleTestResult {
387
+ constructor(retry, id) {
388
+ this.parallelIndex = -1;
389
+ this.workerIndex = -1;
390
+ this.duration = -1;
391
+ this.stdout = [];
392
+ this.stderr = [];
393
+ this.attachments = [];
394
+ this.annotations = [];
395
+ this.status = "skipped";
396
+ this.steps = [];
397
+ this.errors = [];
398
+ this._stepMap = /* @__PURE__ */ new Map();
399
+ this._startTime = 0;
400
+ this.retry = retry;
401
+ this._id = id;
402
+ }
403
+ setStartTimeNumber(startTime) {
404
+ this._startTime = startTime;
405
+ }
406
+ get startTime() {
407
+ return new Date(this._startTime);
408
+ }
409
+ set startTime(value) {
410
+ this._startTime = +value;
411
+ }
412
+ }
413
+ const baseFullConfig = {
414
+ forbidOnly: false,
415
+ fullyParallel: false,
416
+ globalSetup: null,
417
+ globalTeardown: null,
418
+ globalTimeout: 0,
419
+ grep: /.*/,
420
+ grepInvert: null,
421
+ maxFailures: 0,
422
+ metadata: {},
423
+ preserveOutput: "always",
424
+ projects: [],
425
+ reporter: [[define_process_env_default.CI ? "dot" : "list"]],
426
+ reportSlowTests: {
427
+ max: 5,
428
+ threshold: 3e5
429
+ /* 5 minutes */
430
+ },
431
+ configFile: "",
432
+ rootDir: "",
433
+ quiet: false,
434
+ shard: null,
435
+ tags: [],
436
+ updateSnapshots: "missing",
437
+ updateSourceMethod: "patch",
438
+ version: "",
439
+ workers: 0,
440
+ webServer: null
441
+ };
442
+ function parseRegexPatterns(patterns) {
443
+ return patterns.map((p) => {
444
+ if (p.s !== void 0)
445
+ return p.s;
446
+ return new RegExp(p.r.source, p.r.flags);
447
+ });
448
+ }
449
+ function computeTestCaseOutcome(test) {
450
+ let skipped = 0;
451
+ let expected = 0;
452
+ let unexpected = 0;
453
+ for (const result of test.results) {
454
+ if (result.status === "interrupted") ;
455
+ else if (result.status === "skipped" && test.expectedStatus === "skipped") {
456
+ ++skipped;
457
+ } else if (result.status === "skipped") ;
458
+ else if (result.status === test.expectedStatus) {
459
+ ++expected;
460
+ } else {
461
+ ++unexpected;
462
+ }
463
+ }
464
+ if (expected === 0 && unexpected === 0)
465
+ return "skipped";
466
+ if (unexpected === 0)
467
+ return "expected";
468
+ if (expected === 0 && skipped === 0)
469
+ return "unexpected";
470
+ return "flaky";
471
+ }
472
+ class TestTree {
473
+ constructor(rootFolder, rootSuite, loadErrors, projectFilters, pathSeparator, hideFiles) {
474
+ this._treeItemById = /* @__PURE__ */ new Map();
475
+ this._treeItemByTestId = /* @__PURE__ */ new Map();
476
+ const filterProjects = projectFilters && [...projectFilters.values()].some(Boolean);
477
+ this.pathSeparator = pathSeparator;
478
+ this.rootItem = {
479
+ kind: "group",
480
+ subKind: "folder",
481
+ id: rootFolder,
482
+ title: "",
483
+ location: { file: "", line: 0, column: 0 },
484
+ duration: 0,
485
+ parent: void 0,
486
+ children: [],
487
+ status: "none",
488
+ hasLoadErrors: false
489
+ };
490
+ this._treeItemById.set(rootFolder, this.rootItem);
491
+ const visitSuite = (project, parentSuite, parentGroup, mode) => {
492
+ for (const suite of mode === "tests" ? [] : parentSuite.suites) {
493
+ if (!suite.title) {
494
+ visitSuite(project, suite, parentGroup, "all");
495
+ continue;
496
+ }
497
+ let group = parentGroup.children.find((item) => item.kind === "group" && item.title === suite.title);
498
+ if (!group) {
499
+ group = {
500
+ kind: "group",
501
+ subKind: "describe",
502
+ id: "suite:" + parentSuite.titlePath().join("") + "" + suite.title,
503
+ // account for anonymous suites
504
+ title: suite.title,
505
+ location: suite.location,
506
+ duration: 0,
507
+ parent: parentGroup,
508
+ children: [],
509
+ status: "none",
510
+ hasLoadErrors: false
511
+ };
512
+ this._addChild(parentGroup, group);
513
+ }
514
+ visitSuite(project, suite, group, "all");
515
+ }
516
+ for (const test of mode === "suites" ? [] : parentSuite.tests) {
517
+ const title = test.title;
518
+ let testCaseItem = parentGroup.children.find((t) => t.kind !== "group" && t.title === title);
519
+ if (!testCaseItem) {
520
+ testCaseItem = {
521
+ kind: "case",
522
+ id: "test:" + test.titlePath().join(""),
523
+ title,
524
+ parent: parentGroup,
525
+ children: [],
526
+ tests: [],
527
+ location: test.location,
528
+ duration: 0,
529
+ status: "none",
530
+ project: void 0,
531
+ test: void 0,
532
+ tags: test.tags
533
+ };
534
+ this._addChild(parentGroup, testCaseItem);
535
+ }
536
+ const result = test.results[0];
537
+ let status = "none";
538
+ if ((result == null ? void 0 : result[statusEx]) === "scheduled")
539
+ status = "scheduled";
540
+ else if ((result == null ? void 0 : result[statusEx]) === "running")
541
+ status = "running";
542
+ else if ((result == null ? void 0 : result.status) === "skipped")
543
+ status = "skipped";
544
+ else if ((result == null ? void 0 : result.status) === "interrupted")
545
+ status = "none";
546
+ else if (result && test.outcome() !== "expected")
547
+ status = "failed";
548
+ else if (result && test.outcome() === "expected")
549
+ status = "passed";
550
+ testCaseItem.tests.push(test);
551
+ const testItem = {
552
+ kind: "test",
553
+ id: test.id,
554
+ title: project.name,
555
+ location: test.location,
556
+ test,
557
+ parent: testCaseItem,
558
+ children: [],
559
+ status,
560
+ duration: test.results.length ? Math.max(0, test.results[0].duration) : 0,
561
+ project
562
+ };
563
+ this._addChild(testCaseItem, testItem);
564
+ this._treeItemByTestId.set(test.id, testItem);
565
+ testCaseItem.duration = testCaseItem.children.reduce((a, b) => a + b.duration, 0);
566
+ }
567
+ };
568
+ for (const projectSuite of (rootSuite == null ? void 0 : rootSuite.suites) || []) {
569
+ if (filterProjects && !projectFilters.get(projectSuite.title))
570
+ continue;
571
+ for (const fileSuite of projectSuite.suites) {
572
+ if (hideFiles) {
573
+ visitSuite(projectSuite.project(), fileSuite, this.rootItem, "suites");
574
+ if (fileSuite.tests.length) {
575
+ const defaultDescribeItem = this._defaultDescribeItem();
576
+ visitSuite(projectSuite.project(), fileSuite, defaultDescribeItem, "tests");
577
+ }
578
+ } else {
579
+ const fileItem = this._fileItem(fileSuite.location.file.split(pathSeparator), true);
580
+ visitSuite(projectSuite.project(), fileSuite, fileItem, "all");
581
+ }
582
+ }
583
+ }
584
+ for (const loadError of loadErrors) {
585
+ if (!loadError.location)
586
+ continue;
587
+ const fileItem = this._fileItem(loadError.location.file.split(pathSeparator), true);
588
+ fileItem.hasLoadErrors = true;
589
+ }
590
+ }
591
+ _addChild(parent, child) {
592
+ parent.children.push(child);
593
+ child.parent = parent;
594
+ this._treeItemById.set(child.id, child);
595
+ }
596
+ filterTree(filterText, statusFilters, runningTestIds) {
597
+ const tokens = filterText.trim().toLowerCase().split(" ");
598
+ const filtersStatuses = [...statusFilters.values()].some(Boolean);
599
+ const filter = (testCase) => {
600
+ const titleWithTags = [...testCase.tests[0].titlePath(), ...testCase.tests[0].tags].join(" ").toLowerCase();
601
+ if (!tokens.every((token) => titleWithTags.includes(token)) && !testCase.tests.some((t) => runningTestIds == null ? void 0 : runningTestIds.has(t.id)))
602
+ return false;
603
+ testCase.children = testCase.children.filter((test) => {
604
+ return !filtersStatuses || (runningTestIds == null ? void 0 : runningTestIds.has(test.test.id)) || statusFilters.get(test.status);
605
+ });
606
+ testCase.tests = testCase.children.map((c) => c.test);
607
+ return !!testCase.children.length;
608
+ };
609
+ const visit = (treeItem) => {
610
+ const newChildren = [];
611
+ for (const child of treeItem.children) {
612
+ if (child.kind === "case") {
613
+ if (filter(child))
614
+ newChildren.push(child);
615
+ } else {
616
+ visit(child);
617
+ if (child.children.length || child.hasLoadErrors)
618
+ newChildren.push(child);
619
+ }
620
+ }
621
+ treeItem.children = newChildren;
622
+ };
623
+ visit(this.rootItem);
624
+ }
625
+ _fileItem(filePath, isFile) {
626
+ if (filePath.length === 0)
627
+ return this.rootItem;
628
+ const fileName = filePath.join(this.pathSeparator);
629
+ const existingFileItem = this._treeItemById.get(fileName);
630
+ if (existingFileItem)
631
+ return existingFileItem;
632
+ const parentFileItem = this._fileItem(filePath.slice(0, filePath.length - 1), false);
633
+ const fileItem = {
634
+ kind: "group",
635
+ subKind: isFile ? "file" : "folder",
636
+ id: fileName,
637
+ title: filePath[filePath.length - 1],
638
+ location: { file: fileName, line: 0, column: 0 },
639
+ duration: 0,
640
+ parent: parentFileItem,
641
+ children: [],
642
+ status: "none",
643
+ hasLoadErrors: false
644
+ };
645
+ this._addChild(parentFileItem, fileItem);
646
+ return fileItem;
647
+ }
648
+ _defaultDescribeItem() {
649
+ let defaultDescribeItem = this._treeItemById.get("<anonymous>");
650
+ if (!defaultDescribeItem) {
651
+ defaultDescribeItem = {
652
+ kind: "group",
653
+ subKind: "describe",
654
+ id: "<anonymous>",
655
+ title: "<anonymous>",
656
+ location: { file: "", line: 0, column: 0 },
657
+ duration: 0,
658
+ parent: this.rootItem,
659
+ children: [],
660
+ status: "none",
661
+ hasLoadErrors: false
662
+ };
663
+ this._addChild(this.rootItem, defaultDescribeItem);
664
+ }
665
+ return defaultDescribeItem;
666
+ }
667
+ sortAndPropagateStatus() {
668
+ sortAndPropagateStatus(this.rootItem);
669
+ }
670
+ flattenForSingleProject() {
671
+ const visit = (treeItem) => {
672
+ if (treeItem.kind === "case" && treeItem.children.length === 1) {
673
+ treeItem.project = treeItem.children[0].project;
674
+ treeItem.test = treeItem.children[0].test;
675
+ treeItem.children = [];
676
+ this._treeItemByTestId.set(treeItem.test.id, treeItem);
677
+ } else {
678
+ treeItem.children.forEach(visit);
679
+ }
680
+ };
681
+ visit(this.rootItem);
682
+ }
683
+ shortenRoot() {
684
+ let shortRoot = this.rootItem;
685
+ while (shortRoot.children.length === 1 && shortRoot.children[0].kind === "group" && shortRoot.children[0].subKind === "folder")
686
+ shortRoot = shortRoot.children[0];
687
+ shortRoot.location = this.rootItem.location;
688
+ this.rootItem = shortRoot;
689
+ }
690
+ testIds() {
691
+ const result = /* @__PURE__ */ new Set();
692
+ const visit = (treeItem) => {
693
+ if (treeItem.kind === "case")
694
+ treeItem.tests.forEach((t) => result.add(t.id));
695
+ treeItem.children.forEach(visit);
696
+ };
697
+ visit(this.rootItem);
698
+ return result;
699
+ }
700
+ fileNames() {
701
+ const result = /* @__PURE__ */ new Set();
702
+ const visit = (treeItem) => {
703
+ if (treeItem.kind === "group" && treeItem.subKind === "file")
704
+ result.add(treeItem.id);
705
+ else
706
+ treeItem.children.forEach(visit);
707
+ };
708
+ visit(this.rootItem);
709
+ return [...result];
710
+ }
711
+ flatTreeItems() {
712
+ const result = [];
713
+ const visit = (treeItem) => {
714
+ result.push(treeItem);
715
+ treeItem.children.forEach(visit);
716
+ };
717
+ visit(this.rootItem);
718
+ return result;
719
+ }
720
+ treeItemById(id) {
721
+ return this._treeItemById.get(id);
722
+ }
723
+ collectTestIds(treeItem) {
724
+ return treeItem ? collectTestIds(treeItem) : /* @__PURE__ */ new Set();
725
+ }
726
+ }
727
+ function sortAndPropagateStatus(treeItem) {
728
+ for (const child of treeItem.children)
729
+ sortAndPropagateStatus(child);
730
+ if (treeItem.kind === "group") {
731
+ treeItem.children.sort((a, b) => {
732
+ const fc = a.location.file.localeCompare(b.location.file);
733
+ return fc || a.location.line - b.location.line;
734
+ });
735
+ }
736
+ let allPassed = treeItem.children.length > 0;
737
+ let allSkipped = treeItem.children.length > 0;
738
+ let hasFailed = false;
739
+ let hasRunning = false;
740
+ let hasScheduled = false;
741
+ for (const child of treeItem.children) {
742
+ allSkipped = allSkipped && child.status === "skipped";
743
+ allPassed = allPassed && (child.status === "passed" || child.status === "skipped");
744
+ hasFailed = hasFailed || child.status === "failed";
745
+ hasRunning = hasRunning || child.status === "running";
746
+ hasScheduled = hasScheduled || child.status === "scheduled";
747
+ }
748
+ if (hasRunning)
749
+ treeItem.status = "running";
750
+ else if (hasScheduled)
751
+ treeItem.status = "scheduled";
752
+ else if (hasFailed)
753
+ treeItem.status = "failed";
754
+ else if (allSkipped)
755
+ treeItem.status = "skipped";
756
+ else if (allPassed)
757
+ treeItem.status = "passed";
758
+ }
759
+ function collectTestIds(treeItem) {
760
+ const testIds = /* @__PURE__ */ new Set();
761
+ const visit = (treeItem2) => {
762
+ var _a;
763
+ if (treeItem2.kind === "case")
764
+ treeItem2.tests.map((t) => t.id).forEach((id) => testIds.add(id));
765
+ else if (treeItem2.kind === "test")
766
+ testIds.add(treeItem2.id);
767
+ else
768
+ (_a = treeItem2.children) == null ? void 0 : _a.forEach(visit);
769
+ };
770
+ visit(treeItem);
771
+ return testIds;
772
+ }
773
+ const statusEx = Symbol("statusEx");
774
+ class TeleSuiteUpdater {
775
+ constructor(options) {
776
+ this.loadErrors = [];
777
+ this.progress = {
778
+ total: 0,
779
+ passed: 0,
780
+ failed: 0,
781
+ skipped: 0
782
+ };
783
+ this._lastRunTestCount = 0;
784
+ this._receiver = new TeleReporterReceiver(this._createReporter(), {
785
+ mergeProjects: true,
786
+ mergeTestCases: true,
787
+ resolvePath: (rootDir, relativePath) => rootDir + options.pathSeparator + relativePath,
788
+ clearPreviousResultsWhenTestBegins: true
789
+ });
790
+ this._options = options;
791
+ }
792
+ _createReporter() {
793
+ return {
794
+ version: () => "v2",
795
+ onConfigure: (c) => {
796
+ this.config = c;
797
+ this._lastRunReceiver = new TeleReporterReceiver({
798
+ version: () => "v2",
799
+ onBegin: (suite) => {
800
+ this._lastRunTestCount = suite.allTests().length;
801
+ this._lastRunReceiver = void 0;
802
+ }
803
+ }, {
804
+ mergeProjects: true,
805
+ mergeTestCases: false,
806
+ resolvePath: (rootDir, relativePath) => rootDir + this._options.pathSeparator + relativePath
807
+ });
808
+ },
809
+ onBegin: (suite) => {
810
+ var _a;
811
+ if (!this.rootSuite)
812
+ this.rootSuite = suite;
813
+ if (this._testResultsSnapshot) {
814
+ for (const test of this.rootSuite.allTests())
815
+ test.results = ((_a = this._testResultsSnapshot) == null ? void 0 : _a.get(test.id)) || test.results;
816
+ this._testResultsSnapshot = void 0;
817
+ }
818
+ this.progress.total = this._lastRunTestCount;
819
+ this.progress.passed = 0;
820
+ this.progress.failed = 0;
821
+ this.progress.skipped = 0;
822
+ this._options.onUpdate(true);
823
+ },
824
+ onEnd: () => {
825
+ this._options.onUpdate(true);
826
+ },
827
+ onTestBegin: (test, testResult) => {
828
+ testResult[statusEx] = "running";
829
+ this._options.onUpdate();
830
+ },
831
+ onTestEnd: (test, testResult) => {
832
+ if (test.outcome() === "skipped")
833
+ ++this.progress.skipped;
834
+ else if (test.outcome() === "unexpected")
835
+ ++this.progress.failed;
836
+ else
837
+ ++this.progress.passed;
838
+ testResult[statusEx] = testResult.status;
839
+ this._options.onUpdate();
840
+ },
841
+ onError: (error) => this._handleOnError(error),
842
+ printsToStdio: () => false
843
+ };
844
+ }
845
+ processGlobalReport(report) {
846
+ const receiver = new TeleReporterReceiver({
847
+ version: () => "v2",
848
+ onConfigure: (c) => {
849
+ this.config = c;
850
+ },
851
+ onError: (error) => this._handleOnError(error)
852
+ });
853
+ for (const message of report)
854
+ void receiver.dispatch(message);
855
+ }
856
+ processListReport(report) {
857
+ var _a;
858
+ const tests = ((_a = this.rootSuite) == null ? void 0 : _a.allTests()) || [];
859
+ this._testResultsSnapshot = new Map(tests.map((test) => [test.id, test.results]));
860
+ this._receiver.reset();
861
+ for (const message of report)
862
+ void this._receiver.dispatch(message);
863
+ }
864
+ processTestReportEvent(message) {
865
+ var _a, _b, _c;
866
+ (_b = (_a = this._lastRunReceiver) == null ? void 0 : _a.dispatch(message)) == null ? void 0 : _b.catch(() => {
867
+ });
868
+ (_c = this._receiver.dispatch(message)) == null ? void 0 : _c.catch(() => {
869
+ });
870
+ }
871
+ _handleOnError(error) {
872
+ var _a, _b;
873
+ this.loadErrors.push(error);
874
+ (_b = (_a = this._options).onError) == null ? void 0 : _b.call(_a, error);
875
+ this._options.onUpdate();
876
+ }
877
+ asModel() {
878
+ return {
879
+ rootSuite: this.rootSuite || new TeleSuite("", "root"),
880
+ config: this.config,
881
+ loadErrors: this.loadErrors,
882
+ progress: this.progress
883
+ };
884
+ }
885
+ }
886
+ const XtermWrapper = ({
887
+ source
888
+ }) => {
889
+ const [measure, xtermElement] = useMeasure();
890
+ const [theme, setTheme] = reactExports.useState(currentTheme());
891
+ const [modulePromise] = reactExports.useState(__vitePreload(() => import("./assets/xtermModule-DDw6eROI.js"), true ? __vite__mapDeps([0,1]) : void 0, import.meta.url).then((m) => m.default));
892
+ const terminal = reactExports.useRef(null);
893
+ reactExports.useEffect(() => {
894
+ addThemeListener(setTheme);
895
+ return () => removeThemeListener(setTheme);
896
+ }, []);
897
+ reactExports.useEffect(() => {
898
+ const oldSourceWrite = source.write;
899
+ const oldSourceClear = source.clear;
900
+ (async () => {
901
+ const { Terminal, FitAddon } = await modulePromise;
902
+ const element = xtermElement.current;
903
+ if (!element)
904
+ return;
905
+ const terminalTheme = theme === "dark-mode" ? darkTheme : lightTheme;
906
+ if (terminal.current && terminal.current.terminal.options.theme === terminalTheme)
907
+ return;
908
+ if (terminal.current)
909
+ element.textContent = "";
910
+ const newTerminal = new Terminal({
911
+ convertEol: true,
912
+ fontSize: 13,
913
+ scrollback: 1e4,
914
+ fontFamily: "monospace",
915
+ theme: terminalTheme
916
+ });
917
+ const fitAddon = new FitAddon();
918
+ newTerminal.loadAddon(fitAddon);
919
+ for (const p of source.pending)
920
+ newTerminal.write(p);
921
+ source.write = ((data) => {
922
+ source.pending.push(data);
923
+ newTerminal.write(data);
924
+ });
925
+ source.clear = () => {
926
+ source.pending = [];
927
+ newTerminal.clear();
928
+ };
929
+ newTerminal.open(element);
930
+ fitAddon.fit();
931
+ terminal.current = { terminal: newTerminal, fitAddon };
932
+ })();
933
+ return () => {
934
+ source.clear = oldSourceClear;
935
+ source.write = oldSourceWrite;
936
+ };
937
+ }, [modulePromise, terminal, xtermElement, source, theme]);
938
+ reactExports.useEffect(() => {
939
+ setTimeout(() => {
940
+ if (!terminal.current)
941
+ return;
942
+ terminal.current.fitAddon.fit();
943
+ source.resize(terminal.current.terminal.cols, terminal.current.terminal.rows);
944
+ }, 250);
945
+ }, [measure, source]);
946
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "output", className: "xterm-wrapper", style: { flex: "auto" }, ref: xtermElement });
947
+ };
948
+ const lightTheme = {
949
+ foreground: "#383a42",
950
+ background: "#fafafa",
951
+ cursor: "#383a42",
952
+ black: "#000000",
953
+ red: "#e45649",
954
+ green: "#50a14f",
955
+ yellow: "#c18401",
956
+ blue: "#4078f2",
957
+ magenta: "#a626a4",
958
+ cyan: "#0184bc",
959
+ white: "#a0a0a0",
960
+ brightBlack: "#000000",
961
+ brightRed: "#e06c75",
962
+ brightGreen: "#98c379",
963
+ brightYellow: "#d19a66",
964
+ brightBlue: "#4078f2",
965
+ brightMagenta: "#a626a4",
966
+ brightCyan: "#0184bc",
967
+ brightWhite: "#383a42",
968
+ selectionBackground: "#d7d7d7",
969
+ selectionForeground: "#383a42"
970
+ };
971
+ const darkTheme = {
972
+ foreground: "#f8f8f2",
973
+ background: "#1e1e1e",
974
+ cursor: "#f8f8f0",
975
+ black: "#000000",
976
+ red: "#ff5555",
977
+ green: "#50fa7b",
978
+ yellow: "#f1fa8c",
979
+ blue: "#bd93f9",
980
+ magenta: "#ff79c6",
981
+ cyan: "#8be9fd",
982
+ white: "#bfbfbf",
983
+ brightBlack: "#4d4d4d",
984
+ brightRed: "#ff6e6e",
985
+ brightGreen: "#69ff94",
986
+ brightYellow: "#ffffa5",
987
+ brightBlue: "#d6acff",
988
+ brightMagenta: "#ff92df",
989
+ brightCyan: "#a4ffff",
990
+ brightWhite: "#e6e6e6",
991
+ selectionBackground: "#44475a",
992
+ selectionForeground: "#f8f8f2"
993
+ };
994
+ const FiltersView = ({ filterText, setFilterText, statusFilters, setStatusFilters, projectFilters, setProjectFilters, testModel, runTests }) => {
995
+ const [expanded, setExpanded] = React.useState(false);
996
+ const inputRef = React.useRef(null);
997
+ React.useEffect(() => {
998
+ var _a;
999
+ (_a = inputRef.current) == null ? void 0 : _a.focus();
1000
+ }, []);
1001
+ const statusLine = [...statusFilters.entries()].filter(([_, v]) => v).map(([s]) => s).join(" ") || "all";
1002
+ const projectsLine = [...projectFilters.entries()].filter(([_, v]) => v).map(([p]) => p).join(" ") || "all";
1003
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "filters", children: [
1004
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1005
+ Expandable,
1006
+ {
1007
+ expanded,
1008
+ setExpanded,
1009
+ title: /* @__PURE__ */ jsxRuntimeExports.jsx(
1010
+ "input",
1011
+ {
1012
+ ref: inputRef,
1013
+ type: "search",
1014
+ placeholder: "Filter (e.g. text, @tag)",
1015
+ spellCheck: false,
1016
+ value: filterText,
1017
+ onChange: (e) => {
1018
+ setFilterText(e.target.value);
1019
+ },
1020
+ onKeyDown: (e) => {
1021
+ if (e.key === "Enter")
1022
+ runTests();
1023
+ }
1024
+ }
1025
+ )
1026
+ }
1027
+ ),
1028
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "filter-summary", title: "Status: " + statusLine + "\nProjects: " + projectsLine, onClick: () => setExpanded(!expanded), children: [
1029
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "filter-label", children: "Status:" }),
1030
+ " ",
1031
+ statusLine,
1032
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "filter-label", children: "Projects:" }),
1033
+ " ",
1034
+ projectsLine
1035
+ ] }),
1036
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox", style: { marginLeft: 14, maxHeight: 200, overflowY: "auto" }, children: [
1037
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-list", role: "list", "data-testid": "status-filters", children: [...statusFilters.entries()].map(([status, value]) => {
1038
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-entry", role: "listitem", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
1039
+ /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: value, onChange: () => {
1040
+ const copy = new Map(statusFilters);
1041
+ copy.set(status, !copy.get(status));
1042
+ setStatusFilters(copy);
1043
+ } }),
1044
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: status })
1045
+ ] }) }, status);
1046
+ }) }),
1047
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-list", role: "list", "data-testid": "project-filters", children: [...projectFilters.entries()].map(([projectName, value]) => {
1048
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "filter-entry", role: "listitem", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { children: [
1049
+ /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "checkbox", checked: value, onChange: () => {
1050
+ var _a;
1051
+ const copy = new Map(projectFilters);
1052
+ copy.set(projectName, !copy.get(projectName));
1053
+ setProjectFilters(copy);
1054
+ const configFile = (_a = testModel == null ? void 0 : testModel.config) == null ? void 0 : _a.configFile;
1055
+ if (configFile)
1056
+ settings.setObject(configFile + ":projects", [...copy.entries()].filter(([_, v]) => v).map(([k]) => k));
1057
+ } }),
1058
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: projectName || "untitled" })
1059
+ ] }) }, projectName);
1060
+ }) })
1061
+ ] })
1062
+ ] });
1063
+ };
1064
+ const TagView = ({ tag, style, onClick }) => {
1065
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1066
+ "span",
1067
+ {
1068
+ className: clsx("tag", `tag-color-${tagNameToColor(tag)}`),
1069
+ onClick,
1070
+ style: { margin: "6px 0 0 6px", ...style },
1071
+ title: `Click to filter by tag: ${tag}`,
1072
+ children: tag
1073
+ }
1074
+ );
1075
+ };
1076
+ function tagNameToColor(str) {
1077
+ let hash = 0;
1078
+ for (let i = 0; i < str.length; i++)
1079
+ hash = str.charCodeAt(i) + ((hash << 8) - hash);
1080
+ return Math.abs(hash % 6);
1081
+ }
1082
+ const TestTreeView = TreeView;
1083
+ const TestListView = ({ filterText, testModel, testServerConnection, testTree, runTests, runningState, watchAll, watchedTreeIds, setWatchedTreeIds, isLoading, onItemSelected, requestedCollapseAllCount, requestedExpandAllCount, setFilterText, onRevealSource }) => {
1084
+ const [treeState, setTreeState] = React.useState({ expandedItems: /* @__PURE__ */ new Map() });
1085
+ const [selectedTreeItemId, setSelectedTreeItemId] = React.useState();
1086
+ const [collapseAllCount, setCollapseAllCount] = React.useState(requestedCollapseAllCount);
1087
+ const [expandAllCount, setExpandAllCount] = React.useState(requestedExpandAllCount);
1088
+ React.useEffect(() => {
1089
+ if (collapseAllCount !== requestedCollapseAllCount) {
1090
+ treeState.expandedItems.clear();
1091
+ for (const item of testTree.flatTreeItems())
1092
+ treeState.expandedItems.set(item.id, false);
1093
+ setCollapseAllCount(requestedCollapseAllCount);
1094
+ setSelectedTreeItemId(void 0);
1095
+ setTreeState({ ...treeState });
1096
+ return;
1097
+ }
1098
+ if (expandAllCount !== requestedExpandAllCount) {
1099
+ treeState.expandedItems.clear();
1100
+ for (const item of testTree.flatTreeItems())
1101
+ treeState.expandedItems.set(item.id, true);
1102
+ setExpandAllCount(requestedExpandAllCount);
1103
+ setSelectedTreeItemId(void 0);
1104
+ setTreeState({ ...treeState });
1105
+ return;
1106
+ }
1107
+ if (!runningState || runningState.itemSelectedByUser)
1108
+ return;
1109
+ let selectedTreeItem2;
1110
+ const visit = (treeItem) => {
1111
+ var _a;
1112
+ treeItem.children.forEach(visit);
1113
+ if (selectedTreeItem2)
1114
+ return;
1115
+ if (treeItem.status === "failed") {
1116
+ if (treeItem.kind === "test" && runningState.testIds.has(treeItem.test.id))
1117
+ selectedTreeItem2 = treeItem;
1118
+ else if (treeItem.kind === "case" && runningState.testIds.has((_a = treeItem.tests[0]) == null ? void 0 : _a.id))
1119
+ selectedTreeItem2 = treeItem;
1120
+ }
1121
+ };
1122
+ visit(testTree.rootItem);
1123
+ if (selectedTreeItem2)
1124
+ setSelectedTreeItemId(selectedTreeItem2.id);
1125
+ }, [runningState, setSelectedTreeItemId, testTree, collapseAllCount, setCollapseAllCount, requestedCollapseAllCount, expandAllCount, setExpandAllCount, requestedExpandAllCount, treeState, setTreeState]);
1126
+ const selectedTreeItem = React.useMemo(() => {
1127
+ if (!selectedTreeItemId)
1128
+ return void 0;
1129
+ return testTree.treeItemById(selectedTreeItemId);
1130
+ }, [selectedTreeItemId, testTree]);
1131
+ React.useEffect(() => {
1132
+ if (!testModel)
1133
+ return;
1134
+ const testFile = itemLocation(selectedTreeItem, testModel);
1135
+ let selectedTest;
1136
+ if ((selectedTreeItem == null ? void 0 : selectedTreeItem.kind) === "test")
1137
+ selectedTest = selectedTreeItem.test;
1138
+ else if ((selectedTreeItem == null ? void 0 : selectedTreeItem.kind) === "case" && selectedTreeItem.tests.length === 1)
1139
+ selectedTest = selectedTreeItem.tests[0];
1140
+ onItemSelected({ treeItem: selectedTreeItem, testCase: selectedTest, testFile });
1141
+ }, [testModel, selectedTreeItem, onItemSelected]);
1142
+ React.useEffect(() => {
1143
+ if (isLoading)
1144
+ return;
1145
+ if (watchAll) {
1146
+ testServerConnection == null ? void 0 : testServerConnection.watchNoReply({ fileNames: testTree.fileNames() });
1147
+ } else {
1148
+ const fileNames = /* @__PURE__ */ new Set();
1149
+ for (const itemId of watchedTreeIds.value) {
1150
+ const treeItem = testTree.treeItemById(itemId);
1151
+ const fileName = treeItem == null ? void 0 : treeItem.location.file;
1152
+ if (fileName)
1153
+ fileNames.add(fileName);
1154
+ }
1155
+ testServerConnection == null ? void 0 : testServerConnection.watchNoReply({ fileNames: [...fileNames] });
1156
+ }
1157
+ }, [isLoading, testTree, watchAll, watchedTreeIds, testServerConnection]);
1158
+ const runTreeItem = (treeItem) => {
1159
+ setSelectedTreeItemId(treeItem.id);
1160
+ runTests("bounce-if-busy", testTree.collectTestIds(treeItem));
1161
+ };
1162
+ const handleTagClick = (e, tag) => {
1163
+ e.preventDefault();
1164
+ e.stopPropagation();
1165
+ if (e.metaKey || e.ctrlKey) {
1166
+ const parts = filterText.split(" ");
1167
+ if (parts.includes(tag))
1168
+ setFilterText(parts.filter((t) => t !== tag).join(" ").trim());
1169
+ else
1170
+ setFilterText((filterText + " " + tag).trim());
1171
+ } else {
1172
+ setFilterText((filterText.split(" ").filter((t) => !t.startsWith("@")).join(" ") + " " + tag).trim());
1173
+ }
1174
+ };
1175
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1176
+ TestTreeView,
1177
+ {
1178
+ name: "tests",
1179
+ treeState,
1180
+ setTreeState,
1181
+ rootItem: testTree.rootItem,
1182
+ dataTestId: "test-tree",
1183
+ render: (treeItem) => {
1184
+ const prefixId = treeItem.id.replace(/[^\w\d-_]/g, "-");
1185
+ const labelId = prefixId + "-label";
1186
+ const timeId = prefixId + "-time";
1187
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox ui-mode-tree-item", "aria-labelledby": `${labelId} ${timeId}`, children: [
1188
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { id: labelId, className: "ui-mode-tree-item-title", children: [
1189
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: treeItem.title }),
1190
+ treeItem.kind === "case" ? treeItem.tags.map((tag) => /* @__PURE__ */ jsxRuntimeExports.jsx(TagView, { tag: tag.slice(1), onClick: (e) => handleTagClick(e, tag) }, tag)) : null
1191
+ ] }),
1192
+ !!treeItem.duration && treeItem.status !== "skipped" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: timeId, className: "ui-mode-tree-item-time", children: msToString(treeItem.duration) }),
1193
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noMinHeight: true, noShadow: true, children: [
1194
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "play", title: "Run", onClick: () => runTreeItem(treeItem), disabled: !!runningState && !runningState.completed }),
1195
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "go-to-file", title: "Show source", onClick: onRevealSource, style: treeItem.kind === "group" && treeItem.subKind === "folder" ? { visibility: "hidden" } : {} }),
1196
+ !watchAll && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "eye", title: "Watch", onClick: () => {
1197
+ if (watchedTreeIds.value.has(treeItem.id))
1198
+ watchedTreeIds.value.delete(treeItem.id);
1199
+ else
1200
+ watchedTreeIds.value.add(treeItem.id);
1201
+ setWatchedTreeIds({ ...watchedTreeIds });
1202
+ }, toggled: watchedTreeIds.value.has(treeItem.id) })
1203
+ ] })
1204
+ ] });
1205
+ },
1206
+ icon: (treeItem) => testStatusIcon(treeItem.status),
1207
+ title: (treeItem) => treeItem.title,
1208
+ selectedItem: selectedTreeItem,
1209
+ onAccepted: runTreeItem,
1210
+ onSelected: (treeItem) => {
1211
+ if (runningState)
1212
+ runningState.itemSelectedByUser = true;
1213
+ setSelectedTreeItemId(treeItem.id);
1214
+ },
1215
+ isError: (treeItem) => treeItem.kind === "group" ? treeItem.hasLoadErrors : false,
1216
+ autoExpandDepth: filterText ? 5 : 1,
1217
+ noItemsMessage: isLoading ? "Loading…" : "No tests"
1218
+ }
1219
+ );
1220
+ };
1221
+ function itemLocation(item, model) {
1222
+ if (!item || !model)
1223
+ return;
1224
+ return {
1225
+ file: item.location.file,
1226
+ line: item.location.line,
1227
+ column: item.location.column,
1228
+ source: {
1229
+ errors: model.loadErrors.filter((e) => {
1230
+ var _a;
1231
+ return ((_a = e.location) == null ? void 0 : _a.file) === item.location.file;
1232
+ }).map((e) => ({ line: e.location.line, message: e.message })),
1233
+ content: void 0
1234
+ }
1235
+ };
1236
+ }
1237
+ function artifactsFolderName(workerIndex) {
1238
+ return `.playwright-artifacts-${workerIndex}`;
1239
+ }
1240
+ const TraceView = ({ item, rootDir, onOpenExternally, revealSource, pathSeparator }) => {
1241
+ var _a, _b;
1242
+ const [model, setModel] = React.useState(void 0);
1243
+ const [counter, setCounter] = React.useState(0);
1244
+ const pollTimer = React.useRef(null);
1245
+ const { outputDir } = React.useMemo(() => {
1246
+ const outputDir2 = item.testCase ? outputDirForTestCase(item.testCase) : void 0;
1247
+ return { outputDir: outputDir2 };
1248
+ }, [item]);
1249
+ React.useEffect(() => {
1250
+ var _a2, _b2;
1251
+ if (pollTimer.current)
1252
+ clearTimeout(pollTimer.current);
1253
+ const result = (_a2 = item.testCase) == null ? void 0 : _a2.results[0];
1254
+ if (!result) {
1255
+ setModel(void 0);
1256
+ return;
1257
+ }
1258
+ const attachment = result && result.duration >= 0 && result.attachments.find((a) => a.name === "trace");
1259
+ if (attachment && attachment.path) {
1260
+ loadSingleTraceFile(attachment.path).then((model2) => setModel({ model: model2, isLive: false }));
1261
+ return;
1262
+ }
1263
+ if (!outputDir) {
1264
+ setModel(void 0);
1265
+ return;
1266
+ }
1267
+ const traceLocation = [
1268
+ outputDir,
1269
+ artifactsFolderName(result.workerIndex),
1270
+ "traces",
1271
+ `${(_b2 = item.testCase) == null ? void 0 : _b2.id}.json`
1272
+ ].join(pathSeparator);
1273
+ pollTimer.current = setTimeout(async () => {
1274
+ try {
1275
+ const model2 = await loadSingleTraceFile(traceLocation);
1276
+ setModel({ model: model2, isLive: true });
1277
+ } catch {
1278
+ const model2 = new MultiTraceModel("", []);
1279
+ model2.errorDescriptors.push(...result.errors.flatMap((error) => !!error.message ? [{ message: error.message }] : []));
1280
+ setModel({ model: model2, isLive: false });
1281
+ } finally {
1282
+ setCounter(counter + 1);
1283
+ }
1284
+ }, 500);
1285
+ return () => {
1286
+ if (pollTimer.current)
1287
+ clearTimeout(pollTimer.current);
1288
+ };
1289
+ }, [outputDir, item, setModel, counter, setCounter, pathSeparator]);
1290
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1291
+ Workbench,
1292
+ {
1293
+ model: model == null ? void 0 : model.model,
1294
+ showSourcesFirst: true,
1295
+ rootDir,
1296
+ fallbackLocation: item.testFile,
1297
+ isLive: model == null ? void 0 : model.isLive,
1298
+ status: (_a = item.treeItem) == null ? void 0 : _a.status,
1299
+ annotations: ((_b = item.testCase) == null ? void 0 : _b.annotations) ?? [],
1300
+ onOpenExternally,
1301
+ revealSource
1302
+ },
1303
+ "workbench"
1304
+ );
1305
+ };
1306
+ const outputDirForTestCase = (testCase) => {
1307
+ var _a;
1308
+ for (let suite = testCase.parent; suite; suite = suite.parent) {
1309
+ if (suite.project())
1310
+ return (_a = suite.project()) == null ? void 0 : _a.outputDir;
1311
+ }
1312
+ return void 0;
1313
+ };
1314
+ async function loadSingleTraceFile(url) {
1315
+ const params = new URLSearchParams();
1316
+ params.set("trace", url);
1317
+ const response = await fetch(`contexts?${params.toString()}`);
1318
+ const contextEntries = await response.json();
1319
+ return new MultiTraceModel(url, contextEntries);
1320
+ }
1321
+ let xtermSize = { cols: 80 };
1322
+ const xtermDataSource = {
1323
+ pending: [],
1324
+ clear: () => {
1325
+ },
1326
+ write: (data) => xtermDataSource.pending.push(data),
1327
+ resize: () => {
1328
+ }
1329
+ };
1330
+ const searchParams = new URLSearchParams(window.location.search);
1331
+ const testServerBaseUrl = new URL(searchParams.get("server") ?? "../", window.location.href);
1332
+ const wsURL = new URL(searchParams.get("ws"), testServerBaseUrl);
1333
+ wsURL.protocol = wsURL.protocol === "https:" ? "wss:" : "ws:";
1334
+ const queryParams = {
1335
+ args: searchParams.getAll("arg"),
1336
+ grep: searchParams.get("grep") || void 0,
1337
+ grepInvert: searchParams.get("grepInvert") || void 0,
1338
+ projects: searchParams.getAll("project"),
1339
+ workers: searchParams.get("workers") || void 0,
1340
+ headed: searchParams.has("headed"),
1341
+ updateSnapshots: searchParams.get("updateSnapshots") || void 0,
1342
+ reporters: searchParams.has("reporter") ? searchParams.getAll("reporter") : void 0,
1343
+ pathSeparator: searchParams.get("pathSeparator") || "/"
1344
+ };
1345
+ if (queryParams.updateSnapshots && !["all", "changed", "none", "missing"].includes(queryParams.updateSnapshots))
1346
+ queryParams.updateSnapshots = void 0;
1347
+ const isMac = navigator.platform === "MacIntel";
1348
+ const UIModeView = ({}) => {
1349
+ var _a;
1350
+ const [filterText, setFilterText] = React.useState("");
1351
+ const [isShowingOutput, setIsShowingOutput] = React.useState(false);
1352
+ const [outputContainsError, setOutputContainsError] = React.useState(false);
1353
+ const [statusFilters, setStatusFilters] = React.useState(/* @__PURE__ */ new Map([
1354
+ ["passed", false],
1355
+ ["failed", false],
1356
+ ["skipped", false]
1357
+ ]));
1358
+ const [projectFilters, setProjectFilters] = React.useState(/* @__PURE__ */ new Map());
1359
+ const [testModel, setTestModel] = React.useState();
1360
+ const [progress, setProgress] = React.useState();
1361
+ const [selectedItem, setSelectedItem] = React.useState({});
1362
+ const [visibleTestIds, setVisibleTestIds] = React.useState(/* @__PURE__ */ new Set());
1363
+ const [isLoading, setIsLoading] = React.useState(false);
1364
+ const [runningState, setRunningState] = React.useState();
1365
+ const isRunningTest = runningState && !runningState.completed;
1366
+ const [watchAll, setWatchAll] = useSetting("watch-all", false);
1367
+ const [watchedTreeIds, setWatchedTreeIds] = React.useState({ value: /* @__PURE__ */ new Set() });
1368
+ const commandQueue = React.useRef(Promise.resolve());
1369
+ const runTestBacklog = React.useRef(/* @__PURE__ */ new Set());
1370
+ const [collapseAllCount, setCollapseAllCount] = React.useState(0);
1371
+ const [expandAllCount, setExpandAllCount] = React.useState(0);
1372
+ const [isDisconnected, setIsDisconnected] = React.useState(false);
1373
+ const [hasBrowsers, setHasBrowsers] = React.useState(true);
1374
+ const [testServerConnection, setTestServerConnection] = React.useState();
1375
+ const [teleSuiteUpdater, setTeleSuiteUpdater] = React.useState();
1376
+ const [settingsVisible, setSettingsVisible] = React.useState(false);
1377
+ const [testingOptionsVisible, setTestingOptionsVisible] = React.useState(false);
1378
+ const [revealSource, setRevealSource] = React.useState(false);
1379
+ const onRevealSource = React.useCallback(() => setRevealSource(true), [setRevealSource]);
1380
+ const [singleWorker, setSingleWorker] = useSetting("single-worker", false);
1381
+ const [updateSnapshots, setUpdateSnapshots] = useSetting("updateSnapshots", "missing");
1382
+ const [mergeFiles] = useSetting("mergeFiles", false);
1383
+ const inputRef = React.useRef(null);
1384
+ const reloadTests = React.useCallback(() => {
1385
+ setTestServerConnection((prevConnection) => {
1386
+ prevConnection == null ? void 0 : prevConnection.close();
1387
+ return new TestServerConnection(new WebSocketTestServerTransport(wsURL));
1388
+ });
1389
+ }, []);
1390
+ React.useEffect(() => {
1391
+ var _a2;
1392
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
1393
+ setIsLoading(true);
1394
+ reloadTests();
1395
+ }, [reloadTests]);
1396
+ React.useEffect(() => {
1397
+ if (!testServerConnection)
1398
+ return;
1399
+ const disposables = [
1400
+ testServerConnection.onStdio((params) => {
1401
+ if (params.buffer) {
1402
+ const data = atob(params.buffer);
1403
+ xtermDataSource.write(data);
1404
+ } else {
1405
+ xtermDataSource.write(params.text);
1406
+ }
1407
+ if (params.type === "stderr")
1408
+ setOutputContainsError(true);
1409
+ }),
1410
+ testServerConnection.onClose(() => setIsDisconnected(true))
1411
+ ];
1412
+ xtermDataSource.resize = (cols, rows) => {
1413
+ xtermSize = { cols, rows };
1414
+ testServerConnection.resizeTerminalNoReply({ cols, rows });
1415
+ };
1416
+ return () => {
1417
+ for (const disposable of disposables)
1418
+ disposable.dispose();
1419
+ };
1420
+ }, [testServerConnection]);
1421
+ React.useEffect(() => {
1422
+ if (!testServerConnection)
1423
+ return;
1424
+ let throttleTimer;
1425
+ const teleSuiteUpdater2 = new TeleSuiteUpdater({
1426
+ onUpdate: (immediate) => {
1427
+ clearTimeout(throttleTimer);
1428
+ throttleTimer = void 0;
1429
+ if (immediate) {
1430
+ setTestModel(teleSuiteUpdater2.asModel());
1431
+ } else if (!throttleTimer) {
1432
+ throttleTimer = setTimeout(() => {
1433
+ setTestModel(teleSuiteUpdater2.asModel());
1434
+ }, 250);
1435
+ }
1436
+ },
1437
+ onError: (error) => {
1438
+ xtermDataSource.write((error.stack || error.value || "") + "\n");
1439
+ setOutputContainsError(true);
1440
+ },
1441
+ pathSeparator: queryParams.pathSeparator
1442
+ });
1443
+ setTeleSuiteUpdater(teleSuiteUpdater2);
1444
+ setTestModel(void 0);
1445
+ setIsLoading(true);
1446
+ setWatchedTreeIds({ value: /* @__PURE__ */ new Set() });
1447
+ (async () => {
1448
+ try {
1449
+ await testServerConnection.initialize({
1450
+ interceptStdio: true,
1451
+ watchTestDirs: true
1452
+ });
1453
+ const { status, report } = await testServerConnection.runGlobalSetup({});
1454
+ teleSuiteUpdater2.processGlobalReport(report);
1455
+ if (status !== "passed")
1456
+ return;
1457
+ const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
1458
+ teleSuiteUpdater2.processListReport(result.report);
1459
+ testServerConnection.onReport((params) => {
1460
+ teleSuiteUpdater2.processTestReportEvent(params);
1461
+ });
1462
+ const { hasBrowsers: hasBrowsers2 } = await testServerConnection.checkBrowsers({});
1463
+ setHasBrowsers(hasBrowsers2);
1464
+ } finally {
1465
+ setIsLoading(false);
1466
+ }
1467
+ })();
1468
+ return () => {
1469
+ clearTimeout(throttleTimer);
1470
+ };
1471
+ }, [testServerConnection]);
1472
+ React.useEffect(() => {
1473
+ if (!testModel)
1474
+ return;
1475
+ const { config, rootSuite } = testModel;
1476
+ const selectedProjects = config.configFile ? settings.getObject(config.configFile + ":projects", void 0) : void 0;
1477
+ const newFilter = new Map(projectFilters);
1478
+ for (const projectName of newFilter.keys()) {
1479
+ if (!rootSuite.suites.find((s) => s.title === projectName))
1480
+ newFilter.delete(projectName);
1481
+ }
1482
+ for (const projectSuite of rootSuite.suites) {
1483
+ if (!newFilter.has(projectSuite.title))
1484
+ newFilter.set(projectSuite.title, !!(selectedProjects == null ? void 0 : selectedProjects.includes(projectSuite.title)));
1485
+ }
1486
+ if (!selectedProjects && newFilter.size && ![...newFilter.values()].includes(true))
1487
+ newFilter.set(newFilter.entries().next().value[0], true);
1488
+ if (projectFilters.size !== newFilter.size || [...projectFilters].some(([k, v]) => newFilter.get(k) !== v))
1489
+ setProjectFilters(newFilter);
1490
+ }, [projectFilters, testModel]);
1491
+ React.useEffect(() => {
1492
+ if (isRunningTest && (testModel == null ? void 0 : testModel.progress))
1493
+ setProgress(testModel.progress);
1494
+ else if (!testModel)
1495
+ setProgress(void 0);
1496
+ }, [testModel, isRunningTest]);
1497
+ const { testTree } = React.useMemo(() => {
1498
+ if (!testModel)
1499
+ return { testTree: new TestTree("", new TeleSuite("", "root"), [], projectFilters, queryParams.pathSeparator, mergeFiles) };
1500
+ const testTree2 = new TestTree("", testModel.rootSuite, testModel.loadErrors, projectFilters, queryParams.pathSeparator, mergeFiles);
1501
+ testTree2.filterTree(filterText, statusFilters, isRunningTest ? runningState == null ? void 0 : runningState.testIds : void 0);
1502
+ testTree2.sortAndPropagateStatus();
1503
+ testTree2.shortenRoot();
1504
+ testTree2.flattenForSingleProject();
1505
+ setVisibleTestIds(testTree2.testIds());
1506
+ return { testTree: testTree2 };
1507
+ }, [filterText, testModel, statusFilters, projectFilters, setVisibleTestIds, runningState, isRunningTest, mergeFiles]);
1508
+ const runTests = React.useCallback((mode, testIds) => {
1509
+ if (!testServerConnection || !testModel)
1510
+ return;
1511
+ if (mode === "bounce-if-busy" && isRunningTest)
1512
+ return;
1513
+ runTestBacklog.current = /* @__PURE__ */ new Set([...runTestBacklog.current, ...testIds]);
1514
+ commandQueue.current = commandQueue.current.then(async () => {
1515
+ var _a2, _b, _c;
1516
+ const testIds2 = runTestBacklog.current;
1517
+ runTestBacklog.current = /* @__PURE__ */ new Set();
1518
+ if (!testIds2.size)
1519
+ return;
1520
+ {
1521
+ for (const test of ((_a2 = testModel.rootSuite) == null ? void 0 : _a2.allTests()) || []) {
1522
+ if (testIds2.has(test.id)) {
1523
+ test.results = [];
1524
+ const result = test._createTestResult("pending");
1525
+ result[statusEx] = "scheduled";
1526
+ }
1527
+ }
1528
+ setTestModel({ ...testModel });
1529
+ }
1530
+ const time = " [" + (/* @__PURE__ */ new Date()).toLocaleTimeString() + "]";
1531
+ xtermDataSource.write("\x1B[2m—".repeat(Math.max(0, xtermSize.cols - time.length)) + time + "\x1B[22m");
1532
+ setProgress({ total: 0, passed: 0, failed: 0, skipped: 0 });
1533
+ setRunningState({ testIds: testIds2 });
1534
+ await testServerConnection.runTests({
1535
+ locations: queryParams.args,
1536
+ grep: queryParams.grep,
1537
+ grepInvert: queryParams.grepInvert,
1538
+ testIds: [...testIds2],
1539
+ projects: [...projectFilters].filter(([_, v]) => v).map(([p]) => p),
1540
+ updateSnapshots,
1541
+ reporters: queryParams.reporters,
1542
+ workers: singleWorker ? 1 : void 0,
1543
+ trace: "on"
1544
+ });
1545
+ for (const test of ((_b = testModel.rootSuite) == null ? void 0 : _b.allTests()) || []) {
1546
+ if (((_c = test.results[0]) == null ? void 0 : _c.duration) === -1)
1547
+ test.results = [];
1548
+ }
1549
+ setTestModel({ ...testModel });
1550
+ setRunningState((oldState) => oldState ? { ...oldState, completed: true } : void 0);
1551
+ });
1552
+ }, [projectFilters, isRunningTest, testModel, testServerConnection, updateSnapshots, singleWorker]);
1553
+ React.useEffect(() => {
1554
+ if (!testServerConnection || !teleSuiteUpdater)
1555
+ return;
1556
+ const disposable = testServerConnection.onTestFilesChanged(async (params) => {
1557
+ commandQueue.current = commandQueue.current.then(async () => {
1558
+ setIsLoading(true);
1559
+ try {
1560
+ const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args, grep: queryParams.grep, grepInvert: queryParams.grepInvert });
1561
+ teleSuiteUpdater.processListReport(result.report);
1562
+ } catch (e) {
1563
+ console.log(e);
1564
+ } finally {
1565
+ setIsLoading(false);
1566
+ }
1567
+ });
1568
+ await commandQueue.current;
1569
+ if (params.testFiles.length === 0)
1570
+ return;
1571
+ const testModel2 = teleSuiteUpdater.asModel();
1572
+ const testTree2 = new TestTree("", testModel2.rootSuite, testModel2.loadErrors, projectFilters, queryParams.pathSeparator, mergeFiles);
1573
+ const testIds = [];
1574
+ const set = new Set(params.testFiles);
1575
+ if (watchAll) {
1576
+ const visit = (treeItem) => {
1577
+ const fileName = treeItem.location.file;
1578
+ if (fileName && set.has(fileName))
1579
+ testIds.push(...testTree2.collectTestIds(treeItem));
1580
+ if (treeItem.kind === "group" && treeItem.subKind === "folder")
1581
+ treeItem.children.forEach(visit);
1582
+ };
1583
+ visit(testTree2.rootItem);
1584
+ } else {
1585
+ for (const treeId of watchedTreeIds.value) {
1586
+ const treeItem = testTree2.treeItemById(treeId);
1587
+ const fileName = treeItem == null ? void 0 : treeItem.location.file;
1588
+ if (fileName && set.has(fileName))
1589
+ testIds.push(...testTree2.collectTestIds(treeItem));
1590
+ }
1591
+ }
1592
+ runTests("queue-if-busy", new Set(testIds));
1593
+ });
1594
+ return () => disposable.dispose();
1595
+ }, [runTests, testServerConnection, watchAll, watchedTreeIds, teleSuiteUpdater, projectFilters, mergeFiles]);
1596
+ React.useEffect(() => {
1597
+ if (!testServerConnection)
1598
+ return;
1599
+ const onShortcutEvent = (e) => {
1600
+ if (e.code === "Backquote" && e.ctrlKey) {
1601
+ e.preventDefault();
1602
+ setIsShowingOutput(!isShowingOutput);
1603
+ } else if (e.code === "F5" && e.shiftKey) {
1604
+ e.preventDefault();
1605
+ testServerConnection == null ? void 0 : testServerConnection.stopTestsNoReply({});
1606
+ } else if (e.code === "F5") {
1607
+ e.preventDefault();
1608
+ runTests("bounce-if-busy", visibleTestIds);
1609
+ }
1610
+ };
1611
+ addEventListener("keydown", onShortcutEvent);
1612
+ return () => {
1613
+ removeEventListener("keydown", onShortcutEvent);
1614
+ };
1615
+ }, [runTests, reloadTests, testServerConnection, visibleTestIds, isShowingOutput]);
1616
+ const dialogRef = React.useRef(null);
1617
+ const openInstallDialog = React.useCallback((e) => {
1618
+ var _a2;
1619
+ e.preventDefault();
1620
+ e.stopPropagation();
1621
+ (_a2 = dialogRef.current) == null ? void 0 : _a2.showModal();
1622
+ }, []);
1623
+ const closeInstallDialog = React.useCallback((e) => {
1624
+ var _a2;
1625
+ e.preventDefault();
1626
+ e.stopPropagation();
1627
+ (_a2 = dialogRef.current) == null ? void 0 : _a2.close();
1628
+ }, []);
1629
+ const installBrowsers = React.useCallback((e) => {
1630
+ closeInstallDialog(e);
1631
+ setIsShowingOutput(true);
1632
+ testServerConnection == null ? void 0 : testServerConnection.installBrowsers({}).then(async () => {
1633
+ setIsShowingOutput(false);
1634
+ const { hasBrowsers: hasBrowsers2 } = await (testServerConnection == null ? void 0 : testServerConnection.checkBrowsers({}));
1635
+ setHasBrowsers(hasBrowsers2);
1636
+ });
1637
+ }, [closeInstallDialog, testServerConnection]);
1638
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox ui-mode", children: [
1639
+ !hasBrowsers && /* @__PURE__ */ jsxRuntimeExports.jsxs("dialog", { ref: dialogRef, children: [
1640
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "title", children: [
1641
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-lightbulb" }),
1642
+ "Install browsers"
1643
+ ] }),
1644
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "body", children: [
1645
+ "Playwright did not find installed browsers.",
1646
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
1647
+ "Would you like to run `playwright install`?",
1648
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
1649
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "button", onClick: installBrowsers, children: "Install" }),
1650
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "button secondary", onClick: closeInstallDialog, children: "Dismiss" })
1651
+ ] })
1652
+ ] }),
1653
+ isDisconnected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "disconnected", children: [
1654
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "title", children: "UI Mode disconnected" }),
1655
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1656
+ /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "#", onClick: () => window.location.href = "/", children: "Reload the page" }),
1657
+ " to reconnect"
1658
+ ] })
1659
+ ] }),
1660
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1661
+ SplitView,
1662
+ {
1663
+ sidebarSize: 250,
1664
+ minSidebarSize: 150,
1665
+ orientation: "horizontal",
1666
+ sidebarIsFirst: true,
1667
+ settingName: "testListSidebar",
1668
+ main: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
1669
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("vbox", !isShowingOutput && "hidden"), children: [
1670
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { children: [
1671
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", style: { flex: "none" }, children: "Output" }),
1672
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "circle-slash", title: "Clear output", onClick: () => {
1673
+ xtermDataSource.clear();
1674
+ setOutputContainsError(false);
1675
+ } }),
1676
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
1677
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "close", title: "Close", onClick: () => setIsShowingOutput(false) })
1678
+ ] }),
1679
+ /* @__PURE__ */ jsxRuntimeExports.jsx(XtermWrapper, { source: xtermDataSource })
1680
+ ] }),
1681
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx("vbox", isShowingOutput && "hidden"), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1682
+ TraceView,
1683
+ {
1684
+ pathSeparator: queryParams.pathSeparator,
1685
+ item: selectedItem,
1686
+ rootDir: (_a = testModel == null ? void 0 : testModel.config) == null ? void 0 : _a.rootDir,
1687
+ revealSource,
1688
+ onOpenExternally: (location) => testServerConnection == null ? void 0 : testServerConnection.openNoReply({ location: { file: location.file, line: location.line, column: location.column } })
1689
+ }
1690
+ ) })
1691
+ ] }),
1692
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox ui-mode-sidebar", children: [
1693
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noShadow: true, noMinHeight: true, children: [
1694
+ /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: "playwright-logo.svg", alt: "Playwright logo" }),
1695
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Playwright" }),
1696
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "refresh", title: "Reload", onClick: () => reloadTests(), disabled: isRunningTest || isLoading }),
1697
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative" }, children: [
1698
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "terminal", title: "Toggle output — " + (isMac ? "⌃`" : "Ctrl + `"), toggled: isShowingOutput, onClick: () => {
1699
+ setIsShowingOutput(!isShowingOutput);
1700
+ } }),
1701
+ outputContainsError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { title: "Output contains error", style: { position: "absolute", top: 2, right: 2, width: 7, height: 7, borderRadius: "50%", backgroundColor: "var(--vscode-notificationsErrorIcon-foreground)" } })
1702
+ ] }),
1703
+ !hasBrowsers && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "lightbulb-autofix", style: { color: "var(--vscode-list-warningForeground)" }, title: "Playwright browsers are missing", onClick: openInstallDialog })
1704
+ ] }),
1705
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1706
+ FiltersView,
1707
+ {
1708
+ filterText,
1709
+ setFilterText,
1710
+ statusFilters,
1711
+ setStatusFilters,
1712
+ projectFilters,
1713
+ setProjectFilters,
1714
+ testModel,
1715
+ runTests: () => runTests("bounce-if-busy", visibleTestIds)
1716
+ }
1717
+ ),
1718
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { className: "section-toolbar", noMinHeight: true, children: [
1719
+ !isRunningTest && !progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Tests" }),
1720
+ !isRunningTest && progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "status-line", className: "status-line", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1721
+ progress.passed,
1722
+ "/",
1723
+ progress.total,
1724
+ " passed (",
1725
+ progress.passed / progress.total * 100 | 0,
1726
+ "%)"
1727
+ ] }) }),
1728
+ isRunningTest && progress && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "status-line", className: "status-line", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1729
+ "Running ",
1730
+ progress.passed,
1731
+ "/",
1732
+ runningState.testIds.size,
1733
+ " passed (",
1734
+ progress.passed / runningState.testIds.size * 100 | 0,
1735
+ "%)"
1736
+ ] }) }),
1737
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "play", title: "Run all — F5", onClick: () => runTests("bounce-if-busy", visibleTestIds), disabled: isRunningTest || isLoading }),
1738
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "debug-stop", title: "Stop — " + (isMac ? "⇧F5" : "Shift + F5"), onClick: () => testServerConnection == null ? void 0 : testServerConnection.stopTests({}), disabled: !isRunningTest || isLoading }),
1739
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "eye", title: "Watch all", toggled: watchAll, onClick: () => {
1740
+ setWatchedTreeIds({ value: /* @__PURE__ */ new Set() });
1741
+ setWatchAll(!watchAll);
1742
+ } }),
1743
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "collapse-all", title: "Collapse all", onClick: () => {
1744
+ setCollapseAllCount(collapseAllCount + 1);
1745
+ } }),
1746
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "expand-all", title: "Expand all", onClick: () => {
1747
+ setExpandAllCount(expandAllCount + 1);
1748
+ } })
1749
+ ] }),
1750
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1751
+ TestListView,
1752
+ {
1753
+ filterText,
1754
+ testModel,
1755
+ testTree,
1756
+ testServerConnection,
1757
+ runningState,
1758
+ runTests,
1759
+ onItemSelected: setSelectedItem,
1760
+ watchAll,
1761
+ watchedTreeIds,
1762
+ setWatchedTreeIds,
1763
+ isLoading,
1764
+ requestedCollapseAllCount: collapseAllCount,
1765
+ requestedExpandAllCount: expandAllCount,
1766
+ setFilterText,
1767
+ onRevealSource
1768
+ }
1769
+ ),
1770
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noShadow: true, noMinHeight: true, className: "settings-toolbar", onClick: () => setTestingOptionsVisible(!testingOptionsVisible), children: [
1771
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1772
+ "span",
1773
+ {
1774
+ className: `codicon codicon-${testingOptionsVisible ? "chevron-down" : "chevron-right"}`,
1775
+ style: { marginLeft: 5 },
1776
+ title: testingOptionsVisible ? "Hide Testing Options" : "Show Testing Options"
1777
+ }
1778
+ ),
1779
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Testing Options" })
1780
+ ] }),
1781
+ testingOptionsVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(SettingsView, { settings: [
1782
+ { type: "check", value: singleWorker, set: setSingleWorker, name: "Single worker" },
1783
+ { type: "select", options: [
1784
+ { label: "All", value: "all" },
1785
+ { label: "Changed", value: "changed" },
1786
+ { label: "Missing", value: "missing" },
1787
+ { label: "None", value: "none" }
1788
+ ], value: updateSnapshots, set: setUpdateSnapshots, name: "Update snapshots" }
1789
+ ] }),
1790
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Toolbar, { noShadow: true, noMinHeight: true, className: "settings-toolbar", onClick: () => setSettingsVisible(!settingsVisible), children: [
1791
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1792
+ "span",
1793
+ {
1794
+ className: `codicon codicon-${settingsVisible ? "chevron-down" : "chevron-right"}`,
1795
+ style: { marginLeft: 5 },
1796
+ title: settingsVisible ? "Hide Settings" : "Show Settings"
1797
+ }
1798
+ ),
1799
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "section-title", children: "Settings" })
1800
+ ] }),
1801
+ settingsVisible && /* @__PURE__ */ jsxRuntimeExports.jsx(DefaultSettingsView, { location: "ui-mode" })
1802
+ ] })
1803
+ }
1804
+ )
1805
+ ] });
1806
+ };
1807
+ (async () => {
1808
+ applyTheme();
1809
+ if (window.location.protocol !== "file:") {
1810
+ if (window.location.href.includes("isUnderTest=true"))
1811
+ await new Promise((f) => setTimeout(f, 1e3));
1812
+ if (!navigator.serviceWorker)
1813
+ throw new Error(`Service workers are not supported.
1814
+ Make sure to serve the website (${window.location}) via HTTPS or localhost.`);
1815
+ navigator.serviceWorker.register("sw.bundle.js");
1816
+ if (!navigator.serviceWorker.controller) {
1817
+ await new Promise((f) => {
1818
+ navigator.serviceWorker.oncontrollerchange = () => f();
1819
+ });
1820
+ }
1821
+ setInterval(function() {
1822
+ fetch("ping");
1823
+ }, 1e4);
1824
+ }
1825
+ clientExports.createRoot(document.querySelector("#root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(UIModeView, {}));
1826
+ })();
1827
+
1828
+
1829
+ //# sourceMappingURL=data:application/json;base64,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LGVBQWUsR0FDekg7QUFBQSxZQUFBRDtBQUFBQSxjQUFDO0FBQUE7QUFBQSxnQkFDQyxXQUFXLG1CQUFtQixrQkFBa0IsaUJBQWlCLGVBQWU7QUFBQSxnQkFDaEYsT0FBTyxFQUFFLFlBQVk7QUFBQSxnQkFDckIsT0FBTyxrQkFBa0Isa0JBQWtCO0FBQUE7QUFBQTtBQUFBLFlBRTdDQSxzQ0FBQyxTQUFJLFdBQVUsaUJBQWdCLHNCQUFRO0FBQUEsYUFDekM7QUFBQSxVQUNDLG1CQUFtQkEsc0NBQUMsdUJBQW9CLFVBQVMsV0FBVTtBQUFBLFdBQzlEO0FBQUE7QUFBQTtBQUFBLEVBRUYsR0FDRjtBQUNGO0FBQUEsQ0N6ZkMsWUFBWTtBQUNYO0FBQ0EsTUFBSSxPQUFPLFNBQVMsYUFBYSxTQUFTO0FBQ3hDLFFBQUksT0FBTyxTQUFTLEtBQUssU0FBUyxrQkFBa0I7QUFDbEQsWUFBTSxJQUFJLFFBQVEsT0FBSyxXQUFXLEdBQUcsR0FBSSxDQUFDO0FBQzVDLFFBQUksQ0FBQyxVQUFVO0FBQ2IsWUFBTSxJQUFJLE1BQU07QUFBQSxrQ0FBdUUsT0FBTyxRQUFRLDJCQUEyQjtBQUNuSSxjQUFVLGNBQWMsU0FBUyxjQUFjO0FBQy9DLFFBQUksQ0FBQyxVQUFVLGNBQWMsWUFBWTtBQUN2QyxZQUFNLElBQUksUUFBYyxPQUFLO0FBQzNCLGtCQUFVLGNBQWMscUJBQXFCLE1BQU07QUFBQSxNQUNyRCxDQUFDO0FBQUEsSUFDSDtBQUdBLGdCQUFZLFdBQVc7QUFBRSxZQUFNLE1BQU07QUFBQSxJQUFHLEdBQUcsR0FBSztBQUFBLEVBQ2xEO0FBRUFZLDJCQUFvQixTQUFTLGNBQWMsT0FBTyxDQUFFLEVBQUUsT0FBT1osc0NBQUMsY0FBVSxDQUFFO0FBQzVFIiwibmFtZXMiOlsidHJlZUl0ZW0iLCJSZWFjdC51c2VTdGF0ZSIsIlJlYWN0LnVzZVJlZiIsIlJlYWN0LnVzZUVmZmVjdCIsImpzeCIsImpzeHMiLCJzZWxlY3RlZFRyZWVJdGVtIiwib3V0cHV0RGlyIiwiX2EiLCJtb2RlbCIsIl9iIiwidGVsZVN1aXRlVXBkYXRlciIsImhhc0Jyb3dzZXJzIiwidGVzdFRyZWUiLCJ0ZXN0SWRzIiwidGVzdE1vZGVsIiwiUmVhY3RET00uY3JlYXRlUm9vdCJdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wbGF5d3JpZ2h0L3NyYy9pc29tb3JwaGljL3RlbGVSZWNlaXZlci50cyIsIi4uLy4uLy4uLy4uL3BsYXl3cmlnaHQvc3JjL2lzb21vcnBoaWMvdGVzdFRyZWUudHMiLCIuLi8uLi8uLi8uLi9wbGF5d3JpZ2h0L3NyYy9pc29tb3JwaGljL3RlbGVTdWl0ZVVwZGF0ZXIudHMiLCIuLi8uLi8uLi8uLi93ZWIvc3JjL2NvbXBvbmVudHMveHRlcm1XcmFwcGVyLnRzeCIsIi4uLy4uLy4uLy4uL3RyYWNlLXZpZXdlci9zcmMvdWkvdWlNb2RlRmlsdGVyc1ZpZXcudHN4IiwiLi4vLi4vLi4vLi4vdHJhY2Utdmlld2VyL3NyYy91aS90YWcudHN4IiwiLi4vLi4vLi4vLi4vdHJhY2Utdmlld2VyL3NyYy91aS91aU1vZGVUZXN0TGlzdFZpZXcudHN4IiwiLi4vLi4vLi4vLi4vcGxheXdyaWdodC9zcmMvaXNvbW9ycGhpYy9mb2xkZXJzLnRzIiwiLi4vLi4vLi4vLi4vdHJhY2Utdmlld2VyL3NyYy91aS91aU1vZGVUcmFjZVZpZXcudHN4IiwiLi4vLi4vLi4vLi4vdHJhY2Utdmlld2VyL3NyYy91aS91aU1vZGVWaWV3LnRzeCIsIi4uLy4uLy4uLy4uL3RyYWNlLXZpZXdlci9zcmMvdWlNb2RlLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB0eXBlIHsgTWV0YWRhdGEsIFRlc3RBbm5vdGF0aW9uIH0gZnJvbSAnLi4vLi4vdHlwZXMvdGVzdCc7XG5pbXBvcnQgdHlwZSAqIGFzIHJlcG9ydGVyVHlwZXMgZnJvbSAnLi4vLi4vdHlwZXMvdGVzdFJlcG9ydGVyJztcbmltcG9ydCB0eXBlIHsgUmVwb3J0ZXJWMiB9IGZyb20gJy4uL3JlcG9ydGVycy9yZXBvcnRlclYyJztcblxuZXhwb3J0IHR5cGUgU3RyaW5nSW50ZXJuID0gKHM6IHN0cmluZykgPT4gc3RyaW5nO1xuZXhwb3J0IHR5cGUgSnNvbkxvY2F0aW9uID0gcmVwb3J0ZXJUeXBlcy5Mb2NhdGlvbjtcbmV4cG9ydCB0eXBlIEpzb25FcnJvciA9IHN0cmluZztcbmV4cG9ydCB0eXBlIEpzb25TdGFja0ZyYW1lID0geyBmaWxlOiBzdHJpbmcsIGxpbmU6IG51bWJlciwgY29sdW1uOiBudW1iZXIgfTtcblxuZXhwb3J0IHR5cGUgSnNvblN0ZElPVHlwZSA9ICdzdGRvdXQnIHwgJ3N0ZGVycic7XG5cbmV4cG9ydCB0eXBlIEpzb25Db25maWcgPSBQaWNrPHJlcG9ydGVyVHlwZXMuRnVsbENvbmZpZywgJ2NvbmZpZ0ZpbGUnIHwgJ2dsb2JhbFRpbWVvdXQnIHwgJ21heEZhaWx1cmVzJyB8ICdtZXRhZGF0YScgfCAncm9vdERpcicgfCAndmVyc2lvbicgfCAnd29ya2VycycgfCAnZ2xvYmFsU2V0dXAnIHwgJ2dsb2JhbFRlYXJkb3duJz4gJiB7XG4gIC8vIG9wdGlvbmFsIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICB0YWdzPzogcmVwb3J0ZXJUeXBlcy5GdWxsQ29uZmlnWyd0YWdzJ10sXG4gIHdlYlNlcnZlcj86IHJlcG9ydGVyVHlwZXMuRnVsbENvbmZpZ1snd2ViU2VydmVyJ10sXG59O1xuXG5leHBvcnQgdHlwZSBKc29uUGF0dGVybiA9IHtcbiAgcz86IHN0cmluZztcbiAgcj86IHsgc291cmNlOiBzdHJpbmcsIGZsYWdzOiBzdHJpbmcgfTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25Qcm9qZWN0ID0ge1xuICBncmVwOiBKc29uUGF0dGVybltdO1xuICBncmVwSW52ZXJ0OiBKc29uUGF0dGVybltdO1xuICBtZXRhZGF0YTogTWV0YWRhdGE7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVwZW5kZW5jaWVzOiBzdHJpbmdbXTtcbiAgLy8gVGhpcyBpcyByZWxhdGl2ZSB0byByb290IGRpci5cbiAgc25hcHNob3REaXI6IHN0cmluZztcbiAgLy8gVGhpcyBpcyByZWxhdGl2ZSB0byByb290IGRpci5cbiAgb3V0cHV0RGlyOiBzdHJpbmc7XG4gIHJlcGVhdEVhY2g6IG51bWJlcjtcbiAgcmV0cmllczogbnVtYmVyO1xuICBzdWl0ZXM6IEpzb25TdWl0ZVtdO1xuICB0ZWFyZG93bj86IHN0cmluZztcbiAgLy8gVGhpcyBpcyByZWxhdGl2ZSB0byByb290IGRpci5cbiAgdGVzdERpcjogc3RyaW5nO1xuICB0ZXN0SWdub3JlOiBKc29uUGF0dGVybltdO1xuICB0ZXN0TWF0Y2g6IEpzb25QYXR0ZXJuW107XG4gIHRpbWVvdXQ6IG51bWJlcjtcbiAgdXNlOiB7IFtrZXk6IHN0cmluZ106IGFueSB9O1xufTtcblxuZXhwb3J0IHR5cGUgSnNvblN1aXRlID0ge1xuICB0aXRsZTogc3RyaW5nO1xuICBsb2NhdGlvbj86IEpzb25Mb2NhdGlvbjtcbiAgZW50cmllczogKEpzb25TdWl0ZSB8IEpzb25UZXN0Q2FzZSlbXTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25UZXN0Q2FzZSA9IHtcbiAgdGVzdElkOiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGxvY2F0aW9uOiBKc29uTG9jYXRpb247XG4gIHJldHJpZXM6IG51bWJlcjtcbiAgdGFncz86IHN0cmluZ1tdO1xuICByZXBlYXRFYWNoSW5kZXg6IG51bWJlcjtcbiAgYW5ub3RhdGlvbnM/OiBUZXN0QW5ub3RhdGlvbltdO1xufTtcblxuZXhwb3J0IHR5cGUgSnNvblRlc3RFbmQgPSB7XG4gIHRlc3RJZDogc3RyaW5nO1xuICBleHBlY3RlZFN0YXR1czogcmVwb3J0ZXJUeXBlcy5UZXN0U3RhdHVzO1xuICB0aW1lb3V0OiBudW1iZXI7XG4gIC8vIERyb3BwZWQgaW4gMS41Mi4gS2VwdCBhcyBlbXB0eSBhcnJheSBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gIGFubm90YXRpb25zOiBbXTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25UZXN0UmVzdWx0U3RhcnQgPSB7XG4gIGlkOiBzdHJpbmc7XG4gIHJldHJ5OiBudW1iZXI7XG4gIHdvcmtlckluZGV4OiBudW1iZXI7XG4gIHBhcmFsbGVsSW5kZXg6IG51bWJlcjtcbiAgc3RhcnRUaW1lOiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBKc29uQXR0YWNobWVudCA9IE9taXQ8cmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0WydhdHRhY2htZW50cyddWzBdLCAnYm9keSc+ICYgeyBiYXNlNjQ/OiBzdHJpbmc7IH07XG5cbmV4cG9ydCB0eXBlIEpzb25UZXN0UmVzdWx0RW5kID0ge1xuICBpZDogc3RyaW5nO1xuICBkdXJhdGlvbjogbnVtYmVyO1xuICBzdGF0dXM6IHJlcG9ydGVyVHlwZXMuVGVzdFN0YXR1cztcbiAgZXJyb3JzOiByZXBvcnRlclR5cGVzLlRlc3RFcnJvcltdO1xuICAvKiogTm8gbG9uZ2VyIGVtaXR0ZWQsIGJ1dCBrZXB0IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSAqL1xuICBhdHRhY2htZW50cz86IEpzb25BdHRhY2htZW50W107XG4gIGFubm90YXRpb25zPzogVGVzdEFubm90YXRpb25bXTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25UZXN0U3RlcFN0YXJ0ID0ge1xuICBpZDogc3RyaW5nO1xuICBwYXJlbnRTdGVwSWQ/OiBzdHJpbmc7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGNhdGVnb3J5OiBzdHJpbmcsXG4gIHN0YXJ0VGltZTogbnVtYmVyO1xuICBsb2NhdGlvbj86IHJlcG9ydGVyVHlwZXMuTG9jYXRpb247XG59O1xuXG5leHBvcnQgdHlwZSBKc29uVGVzdFN0ZXBFbmQgPSB7XG4gIGlkOiBzdHJpbmc7XG4gIGR1cmF0aW9uOiBudW1iZXI7XG4gIGVycm9yPzogcmVwb3J0ZXJUeXBlcy5UZXN0RXJyb3I7XG4gIGF0dGFjaG1lbnRzPzogbnVtYmVyW107IC8vIGluZGV4IG9mIEpzb25UZXN0UmVzdWx0RW5kLmF0dGFjaG1lbnRzXG4gIGFubm90YXRpb25zPzogVGVzdEFubm90YXRpb25bXTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25UZXN0UmVzdWx0T25BdHRhY2ggPSB7XG4gIHRlc3RJZDogc3RyaW5nO1xuICByZXN1bHRJZDogc3RyaW5nO1xuICBhdHRhY2htZW50czogSnNvbkF0dGFjaG1lbnRbXTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25GdWxsUmVzdWx0ID0ge1xuICBzdGF0dXM6IHJlcG9ydGVyVHlwZXMuRnVsbFJlc3VsdFsnc3RhdHVzJ107XG4gIHN0YXJ0VGltZTogbnVtYmVyO1xuICBkdXJhdGlvbjogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgSnNvbkV2ZW50ID0gSnNvbk9uQ29uZmlndXJlRXZlbnQgfCBKc29uT25CbG9iUmVwb3J0TWV0YWRhdGFFdmVudCB8IEpzb25PbkVuZEV2ZW50IHwgSnNvbk9uRXhpdEV2ZW50IHwgSnNvbk9uUHJvamVjdEV2ZW50IHwgSnNvbk9uQmVnaW5FdmVudCB8IEpzb25PblRlc3RCZWdpbkV2ZW50XG4gIHwgSnNvbk9uVGVzdEVuZEV2ZW50IHwgSnNvbk9uU3RlcEJlZ2luRXZlbnQgfCBKc29uT25TdGVwRW5kRXZlbnQgfCBKc29uT25BdHRhY2hFdmVudCB8IEpzb25PbkVycm9yRXZlbnQgfCBKc29uT25TdGRJT0V2ZW50O1xuXG5leHBvcnQgdHlwZSBKc29uT25Db25maWd1cmVFdmVudCA9IHtcbiAgbWV0aG9kOiAnb25Db25maWd1cmUnO1xuICBwYXJhbXM6IHtcbiAgICBjb25maWc6IEpzb25Db25maWc7XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25CbG9iUmVwb3J0TWV0YWRhdGFFdmVudCA9IHtcbiAgbWV0aG9kOiAnb25CbG9iUmVwb3J0TWV0YWRhdGEnO1xuICBwYXJhbXM6IEJsb2JSZXBvcnRNZXRhZGF0YTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25PblByb2plY3RFdmVudCA9IHtcbiAgbWV0aG9kOiAnb25Qcm9qZWN0JztcbiAgcGFyYW1zOiB7XG4gICAgcHJvamVjdDogSnNvblByb2plY3Q7XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25CZWdpbkV2ZW50ID0ge1xuICBtZXRob2Q6ICdvbkJlZ2luJztcbiAgcGFyYW1zOiB1bmRlZmluZWQ7XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25UZXN0QmVnaW5FdmVudCA9IHtcbiAgbWV0aG9kOiAnb25UZXN0QmVnaW4nO1xuICBwYXJhbXM6IHtcbiAgICB0ZXN0SWQ6IHN0cmluZztcbiAgICByZXN1bHQ6IEpzb25UZXN0UmVzdWx0U3RhcnQ7XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25UZXN0RW5kRXZlbnQgPSB7XG4gIG1ldGhvZDogJ29uVGVzdEVuZCc7XG4gIHBhcmFtczoge1xuICAgIHRlc3Q6IEpzb25UZXN0RW5kO1xuICAgIHRlc3RJZD86IHN0cmluZztcbiAgICByZXN1bHQ6IEpzb25UZXN0UmVzdWx0RW5kO1xuICB9O1xufTtcblxuZXhwb3J0IHR5cGUgSnNvbk9uU3RlcEJlZ2luRXZlbnQgPSB7XG4gIG1ldGhvZDogJ29uU3RlcEJlZ2luJztcbiAgcGFyYW1zOiB7XG4gICAgdGVzdElkOiBzdHJpbmc7XG4gICAgcmVzdWx0SWQ6IHN0cmluZztcbiAgICBzdGVwOiBKc29uVGVzdFN0ZXBTdGFydDtcbiAgfTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25PblN0ZXBFbmRFdmVudCA9IHtcbiAgbWV0aG9kOiAnb25TdGVwRW5kJztcbiAgcGFyYW1zOiB7XG4gICAgdGVzdElkOiBzdHJpbmc7XG4gICAgcmVzdWx0SWQ6IHN0cmluZztcbiAgICBzdGVwOiBKc29uVGVzdFN0ZXBFbmQ7XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25BdHRhY2hFdmVudCA9IHtcbiAgbWV0aG9kOiAnb25BdHRhY2gnO1xuICBwYXJhbXM6IEpzb25UZXN0UmVzdWx0T25BdHRhY2g7XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25FcnJvckV2ZW50ID0ge1xuICBtZXRob2Q6ICdvbkVycm9yJztcbiAgcGFyYW1zOiB7XG4gICAgZXJyb3I6IHJlcG9ydGVyVHlwZXMuVGVzdEVycm9yO1xuICB9O1xufTtcblxuZXhwb3J0IHR5cGUgSnNvbk9uU3RkSU9FdmVudCA9IHtcbiAgbWV0aG9kOiAnb25TdGRJTyc7XG4gIHBhcmFtczoge1xuICAgIHR5cGU6IEpzb25TdGRJT1R5cGU7XG4gICAgdGVzdElkPzogc3RyaW5nO1xuICAgIHJlc3VsdElkPzogc3RyaW5nO1xuICAgIGRhdGE6IHN0cmluZztcbiAgICBpc0Jhc2U2NDogYm9vbGVhbjtcbiAgfTtcbn07XG5cbmV4cG9ydCB0eXBlIEpzb25PbkVuZEV2ZW50ID0ge1xuICBtZXRob2Q6ICdvbkVuZCc7XG4gIHBhcmFtczoge1xuICAgIHJlc3VsdDogSnNvbkZ1bGxSZXN1bHQ7XG4gIH07XG59O1xuXG5leHBvcnQgdHlwZSBKc29uT25FeGl0RXZlbnQgPSB7XG4gIG1ldGhvZDogJ29uRXhpdCc7XG4gIHBhcmFtczogdW5kZWZpbmVkO1xufTtcblxuZXhwb3J0IHR5cGUgQmxvYlJlcG9ydE1ldGFkYXRhID0ge1xuICB2ZXJzaW9uOiBudW1iZXI7XG4gIHVzZXJBZ2VudDogc3RyaW5nO1xuICBuYW1lPzogc3RyaW5nO1xuICBzaGFyZD86IHsgdG90YWw6IG51bWJlciwgY3VycmVudDogbnVtYmVyIH07XG4gIHBhdGhTZXBhcmF0b3I/OiBzdHJpbmc7XG59O1xuXG50eXBlIFRlbGVSZXBvcnRlclJlY2VpdmVyT3B0aW9ucyA9IHtcbiAgbWVyZ2VQcm9qZWN0cz86IGJvb2xlYW47XG4gIG1lcmdlVGVzdENhc2VzPzogYm9vbGVhbjtcbiAgcmVzb2x2ZVBhdGg/OiAocm9vdERpcjogc3RyaW5nLCByZWxhdGl2ZVBhdGg6IHN0cmluZykgPT4gc3RyaW5nO1xuICBjb25maWdPdmVycmlkZXM/OiBQaWNrPHJlcG9ydGVyVHlwZXMuRnVsbENvbmZpZywgJ2NvbmZpZ0ZpbGUnIHwgJ3F1aWV0JyB8ICdyZXBvcnRTbG93VGVzdHMnIHwgJ3JlcG9ydGVyJz47XG4gIGNsZWFyUHJldmlvdXNSZXN1bHRzV2hlblRlc3RCZWdpbnM/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGNsYXNzIFRlbGVSZXBvcnRlclJlY2VpdmVyIHtcbiAgcHVibGljIGlzTGlzdGluZyA9IGZhbHNlO1xuICBwcml2YXRlIF9yb290U3VpdGU6IFRlbGVTdWl0ZTtcbiAgcHJpdmF0ZSBfb3B0aW9uczogVGVsZVJlcG9ydGVyUmVjZWl2ZXJPcHRpb25zO1xuICBwcml2YXRlIF9yZXBvcnRlcjogUmVwb3J0ZXJWMjtcbiAgcHJpdmF0ZSBfdGVzdHMgPSBuZXcgTWFwPHN0cmluZywgVGVsZVRlc3RDYXNlPigpO1xuICBwcml2YXRlIF9yb290RGlyITogc3RyaW5nO1xuICBwcml2YXRlIF9jb25maWchOiByZXBvcnRlclR5cGVzLkZ1bGxDb25maWc7XG5cbiAgY29uc3RydWN0b3IocmVwb3J0ZXI6IFJlcG9ydGVyVjIsIG9wdGlvbnM6IFRlbGVSZXBvcnRlclJlY2VpdmVyT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcm9vdFN1aXRlID0gbmV3IFRlbGVTdWl0ZSgnJywgJ3Jvb3QnKTtcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLl9yZXBvcnRlciA9IHJlcG9ydGVyO1xuICB9XG5cbiAgcmVzZXQoKSB7XG4gICAgdGhpcy5fcm9vdFN1aXRlLl9lbnRyaWVzID0gW107XG4gICAgdGhpcy5fdGVzdHMuY2xlYXIoKTtcbiAgfVxuXG4gIGRpc3BhdGNoKG1lc3NhZ2U6IEpzb25FdmVudCk6IFByb21pc2U8dm9pZD4gfCB2b2lkIHtcbiAgICBjb25zdCB7IG1ldGhvZCwgcGFyYW1zIH0gPSBtZXNzYWdlO1xuICAgIGlmIChtZXRob2QgPT09ICdvbkNvbmZpZ3VyZScpIHtcbiAgICAgIHRoaXMuX29uQ29uZmlndXJlKHBhcmFtcy5jb25maWcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobWV0aG9kID09PSAnb25Qcm9qZWN0Jykge1xuICAgICAgdGhpcy5fb25Qcm9qZWN0KHBhcmFtcy5wcm9qZWN0KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1ldGhvZCA9PT0gJ29uQmVnaW4nKSB7XG4gICAgICB0aGlzLl9vbkJlZ2luKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChtZXRob2QgPT09ICdvblRlc3RCZWdpbicpIHtcbiAgICAgIHRoaXMuX29uVGVzdEJlZ2luKHBhcmFtcy50ZXN0SWQsIHBhcmFtcy5yZXN1bHQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAobWV0aG9kID09PSAnb25UZXN0RW5kJykge1xuICAgICAgdGhpcy5fb25UZXN0RW5kKHBhcmFtcy50ZXN0LCBwYXJhbXMucmVzdWx0KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1ldGhvZCA9PT0gJ29uU3RlcEJlZ2luJykge1xuICAgICAgdGhpcy5fb25TdGVwQmVnaW4ocGFyYW1zLnRlc3RJZCwgcGFyYW1zLnJlc3VsdElkLCBwYXJhbXMuc3RlcCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChtZXRob2QgPT09ICdvbkF0dGFjaCcpIHtcbiAgICAgIHRoaXMuX29uQXR0YWNoKHBhcmFtcy50ZXN0SWQsIHBhcmFtcy5yZXN1bHRJZCwgcGFyYW1zLmF0dGFjaG1lbnRzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1ldGhvZCA9PT0gJ29uU3RlcEVuZCcpIHtcbiAgICAgIHRoaXMuX29uU3RlcEVuZChwYXJhbXMudGVzdElkLCBwYXJhbXMucmVzdWx0SWQsIHBhcmFtcy5zdGVwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1ldGhvZCA9PT0gJ29uRXJyb3InKSB7XG4gICAgICB0aGlzLl9vbkVycm9yKHBhcmFtcy5lcnJvcik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChtZXRob2QgPT09ICdvblN0ZElPJykge1xuICAgICAgdGhpcy5fb25TdGRJTyhwYXJhbXMudHlwZSwgcGFyYW1zLnRlc3RJZCwgcGFyYW1zLnJlc3VsdElkLCBwYXJhbXMuZGF0YSwgcGFyYW1zLmlzQmFzZTY0KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKG1ldGhvZCA9PT0gJ29uRW5kJylcbiAgICAgIHJldHVybiB0aGlzLl9vbkVuZChwYXJhbXMucmVzdWx0KTtcbiAgICBpZiAobWV0aG9kID09PSAnb25FeGl0JylcbiAgICAgIHJldHVybiB0aGlzLl9vbkV4aXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uQ29uZmlndXJlKGNvbmZpZzogSnNvbkNvbmZpZykge1xuICAgIHRoaXMuX3Jvb3REaXIgPSBjb25maWcucm9vdERpcjtcbiAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9wYXJzZUNvbmZpZyhjb25maWcpO1xuICAgIHRoaXMuX3JlcG9ydGVyLm9uQ29uZmlndXJlPy4odGhpcy5fY29uZmlnKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uUHJvamVjdChwcm9qZWN0OiBKc29uUHJvamVjdCkge1xuICAgIGxldCBwcm9qZWN0U3VpdGUgPSB0aGlzLl9vcHRpb25zLm1lcmdlUHJvamVjdHMgPyB0aGlzLl9yb290U3VpdGUuc3VpdGVzLmZpbmQoc3VpdGUgPT4gc3VpdGUucHJvamVjdCgpIS5uYW1lID09PSBwcm9qZWN0Lm5hbWUpIDogdW5kZWZpbmVkO1xuICAgIGlmICghcHJvamVjdFN1aXRlKSB7XG4gICAgICBwcm9qZWN0U3VpdGUgPSBuZXcgVGVsZVN1aXRlKHByb2plY3QubmFtZSwgJ3Byb2plY3QnKTtcbiAgICAgIHRoaXMuX3Jvb3RTdWl0ZS5fYWRkU3VpdGUocHJvamVjdFN1aXRlKTtcbiAgICB9XG4gICAgLy8gQWx3YXlzIHVwZGF0ZSBwcm9qZWN0IGluIHdhdGNoIG1vZGUuXG4gICAgcHJvamVjdFN1aXRlLl9wcm9qZWN0ID0gdGhpcy5fcGFyc2VQcm9qZWN0KHByb2plY3QpO1xuICAgIGZvciAoY29uc3Qgc3VpdGUgb2YgcHJvamVjdC5zdWl0ZXMpXG4gICAgICB0aGlzLl9tZXJnZVN1aXRlSW50byhzdWl0ZSwgcHJvamVjdFN1aXRlKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uQmVnaW4oKSB7XG4gICAgdGhpcy5fcmVwb3J0ZXIub25CZWdpbj8uKHRoaXMuX3Jvb3RTdWl0ZSk7XG4gIH1cblxuICBwcml2YXRlIF9vblRlc3RCZWdpbih0ZXN0SWQ6IHN0cmluZywgcGF5bG9hZDogSnNvblRlc3RSZXN1bHRTdGFydCkge1xuICAgIGNvbnN0IHRlc3QgPSB0aGlzLl90ZXN0cy5nZXQodGVzdElkKSE7XG4gICAgaWYgKHRoaXMuX29wdGlvbnMuY2xlYXJQcmV2aW91c1Jlc3VsdHNXaGVuVGVzdEJlZ2lucylcbiAgICAgIHRlc3QucmVzdWx0cyA9IFtdO1xuICAgIGNvbnN0IHRlc3RSZXN1bHQgPSB0ZXN0Ll9jcmVhdGVUZXN0UmVzdWx0KHBheWxvYWQuaWQpO1xuICAgIHRlc3RSZXN1bHQucmV0cnkgPSBwYXlsb2FkLnJldHJ5O1xuICAgIHRlc3RSZXN1bHQud29ya2VySW5kZXggPSBwYXlsb2FkLndvcmtlckluZGV4O1xuICAgIHRlc3RSZXN1bHQucGFyYWxsZWxJbmRleCA9IHBheWxvYWQucGFyYWxsZWxJbmRleDtcbiAgICB0ZXN0UmVzdWx0LnNldFN0YXJ0VGltZU51bWJlcihwYXlsb2FkLnN0YXJ0VGltZSk7XG4gICAgdGhpcy5fcmVwb3J0ZXIub25UZXN0QmVnaW4/Lih0ZXN0LCB0ZXN0UmVzdWx0KTtcbiAgfVxuXG4gIHByaXZhdGUgX29uVGVzdEVuZCh0ZXN0RW5kUGF5bG9hZDogSnNvblRlc3RFbmQsIHBheWxvYWQ6IEpzb25UZXN0UmVzdWx0RW5kKSB7XG4gICAgY29uc3QgdGVzdCA9IHRoaXMuX3Rlc3RzLmdldCh0ZXN0RW5kUGF5bG9hZC50ZXN0SWQpITtcbiAgICB0ZXN0LnRpbWVvdXQgPSB0ZXN0RW5kUGF5bG9hZC50aW1lb3V0O1xuICAgIHRlc3QuZXhwZWN0ZWRTdGF0dXMgPSB0ZXN0RW5kUGF5bG9hZC5leHBlY3RlZFN0YXR1cztcbiAgICBjb25zdCByZXN1bHQgPSB0ZXN0LnJlc3VsdHMuZmluZChyID0+IHIuX2lkID09PSBwYXlsb2FkLmlkKSE7XG4gICAgcmVzdWx0LmR1cmF0aW9uID0gcGF5bG9hZC5kdXJhdGlvbjtcbiAgICByZXN1bHQuc3RhdHVzID0gcGF5bG9hZC5zdGF0dXM7XG4gICAgcmVzdWx0LmVycm9ycyA9IHBheWxvYWQuZXJyb3JzO1xuICAgIHJlc3VsdC5lcnJvciA9IHJlc3VsdC5lcnJvcnM/LlswXTtcbiAgICAvLyBBdHRhY2htZW50cyBhcmUgb25seSBwcmVzZW50IGhlcmUgZnJvbSBsZWdhY3kgYmxvYnMuIFRoZXNlIG92ZXJyaWRlIGFsbCBfb25BdHRhY2ggZXZlbnRzXG4gICAgaWYgKCEhcGF5bG9hZC5hdHRhY2htZW50cylcbiAgICAgIHJlc3VsdC5hdHRhY2htZW50cyA9IHRoaXMuX3BhcnNlQXR0YWNobWVudHMocGF5bG9hZC5hdHRhY2htZW50cyk7XG4gICAgaWYgKHBheWxvYWQuYW5ub3RhdGlvbnMpIHtcbiAgICAgIHRoaXMuX2Fic29sdXRlQW5ub3RhdGlvbkxvY2F0aW9uc0lucGxhY2UocGF5bG9hZC5hbm5vdGF0aW9ucyk7XG4gICAgICByZXN1bHQuYW5ub3RhdGlvbnMgPSBwYXlsb2FkLmFubm90YXRpb25zO1xuICAgICAgdGVzdC5hbm5vdGF0aW9ucyA9IHBheWxvYWQuYW5ub3RhdGlvbnM7XG4gICAgfVxuICAgIHRoaXMuX3JlcG9ydGVyLm9uVGVzdEVuZD8uKHRlc3QsIHJlc3VsdCk7XG4gICAgLy8gRnJlZSB1cCB0aGUgbWVtb3J5IGFzIHdvbid0IHNlZSB0aGVzZSBzdGVwIGlkcy5cbiAgICByZXN1bHQuX3N0ZXBNYXAgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBwcml2YXRlIF9vblN0ZXBCZWdpbih0ZXN0SWQ6IHN0cmluZywgcmVzdWx0SWQ6IHN0cmluZywgcGF5bG9hZDogSnNvblRlc3RTdGVwU3RhcnQpIHtcbiAgICBjb25zdCB0ZXN0ID0gdGhpcy5fdGVzdHMuZ2V0KHRlc3RJZCkhO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRlc3QucmVzdWx0cy5maW5kKHIgPT4gci5faWQgPT09IHJlc3VsdElkKSE7XG4gICAgY29uc3QgcGFyZW50U3RlcCA9IHBheWxvYWQucGFyZW50U3RlcElkID8gcmVzdWx0Ll9zdGVwTWFwLmdldChwYXlsb2FkLnBhcmVudFN0ZXBJZCkgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBsb2NhdGlvbiA9IHRoaXMuX2Fic29sdXRlTG9jYXRpb24ocGF5bG9hZC5sb2NhdGlvbik7XG4gICAgY29uc3Qgc3RlcCA9IG5ldyBUZWxlVGVzdFN0ZXAocGF5bG9hZCwgcGFyZW50U3RlcCwgbG9jYXRpb24sIHJlc3VsdCk7XG4gICAgaWYgKHBhcmVudFN0ZXApXG4gICAgICBwYXJlbnRTdGVwLnN0ZXBzLnB1c2goc3RlcCk7XG4gICAgZWxzZVxuICAgICAgcmVzdWx0LnN0ZXBzLnB1c2goc3RlcCk7XG4gICAgcmVzdWx0Ll9zdGVwTWFwLnNldChwYXlsb2FkLmlkLCBzdGVwKTtcbiAgICB0aGlzLl9yZXBvcnRlci5vblN0ZXBCZWdpbj8uKHRlc3QsIHJlc3VsdCwgc3RlcCk7XG4gIH1cblxuICBwcml2YXRlIF9vblN0ZXBFbmQodGVzdElkOiBzdHJpbmcsIHJlc3VsdElkOiBzdHJpbmcsIHBheWxvYWQ6IEpzb25UZXN0U3RlcEVuZCkge1xuICAgIGNvbnN0IHRlc3QgPSB0aGlzLl90ZXN0cy5nZXQodGVzdElkKSE7XG4gICAgY29uc3QgcmVzdWx0ID0gdGVzdC5yZXN1bHRzLmZpbmQociA9PiByLl9pZCA9PT0gcmVzdWx0SWQpITtcbiAgICBjb25zdCBzdGVwID0gcmVzdWx0Ll9zdGVwTWFwLmdldChwYXlsb2FkLmlkKSE7XG4gICAgc3RlcC5fZW5kUGF5bG9hZCA9IHBheWxvYWQ7XG4gICAgc3RlcC5kdXJhdGlvbiA9IHBheWxvYWQuZHVyYXRpb247XG4gICAgc3RlcC5lcnJvciA9IHBheWxvYWQuZXJyb3I7XG4gICAgdGhpcy5fcmVwb3J0ZXIub25TdGVwRW5kPy4odGVzdCwgcmVzdWx0LCBzdGVwKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uQXR0YWNoKHRlc3RJZDogc3RyaW5nLCByZXN1bHRJZDogc3RyaW5nLCBhdHRhY2htZW50czogSnNvbkF0dGFjaG1lbnRbXSkge1xuICAgIGNvbnN0IHRlc3QgPSB0aGlzLl90ZXN0cy5nZXQodGVzdElkKSE7XG4gICAgY29uc3QgcmVzdWx0ID0gdGVzdC5yZXN1bHRzLmZpbmQociA9PiByLl9pZCA9PT0gcmVzdWx0SWQpITtcbiAgICByZXN1bHQuYXR0YWNobWVudHMucHVzaCguLi5hdHRhY2htZW50cy5tYXAoYSA9PiAoe1xuICAgICAgbmFtZTogYS5uYW1lLFxuICAgICAgY29udGVudFR5cGU6IGEuY29udGVudFR5cGUsXG4gICAgICBwYXRoOiBhLnBhdGgsXG4gICAgICBib2R5OiBhLmJhc2U2NCAmJiAoZ2xvYmFsVGhpcyBhcyBhbnkpLkJ1ZmZlciA/IEJ1ZmZlci5mcm9tKGEuYmFzZTY0LCAnYmFzZTY0JykgOiB1bmRlZmluZWQsXG4gICAgfSkpKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uRXJyb3IoZXJyb3I6IHJlcG9ydGVyVHlwZXMuVGVzdEVycm9yKSB7XG4gICAgdGhpcy5fcmVwb3J0ZXIub25FcnJvcj8uKGVycm9yKTtcbiAgfVxuXG4gIHByaXZhdGUgX29uU3RkSU8odHlwZTogSnNvblN0ZElPVHlwZSwgdGVzdElkOiBzdHJpbmcgfCB1bmRlZmluZWQsIHJlc3VsdElkOiBzdHJpbmcgfCB1bmRlZmluZWQsIGRhdGE6IHN0cmluZywgaXNCYXNlNjQ6IGJvb2xlYW4pIHtcbiAgICBjb25zdCBjaHVuayA9IGlzQmFzZTY0ID8gKChnbG9iYWxUaGlzIGFzIGFueSkuQnVmZmVyID8gQnVmZmVyLmZyb20oZGF0YSwgJ2Jhc2U2NCcpIDogYXRvYihkYXRhKSkgOiBkYXRhO1xuICAgIGNvbnN0IHRlc3QgPSB0ZXN0SWQgPyB0aGlzLl90ZXN0cy5nZXQodGVzdElkKSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCByZXN1bHQgPSB0ZXN0ICYmIHJlc3VsdElkID8gdGVzdC5yZXN1bHRzLmZpbmQociA9PiByLl9pZCA9PT0gcmVzdWx0SWQpIDogdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlID09PSAnc3Rkb3V0Jykge1xuICAgICAgcmVzdWx0Py5zdGRvdXQucHVzaChjaHVuayk7XG4gICAgICB0aGlzLl9yZXBvcnRlci5vblN0ZE91dD8uKGNodW5rLCB0ZXN0LCByZXN1bHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQ/LnN0ZGVyci5wdXNoKGNodW5rKTtcbiAgICAgIHRoaXMuX3JlcG9ydGVyLm9uU3RkRXJyPy4oY2h1bmssIHRlc3QsIHJlc3VsdCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfb25FbmQocmVzdWx0OiBKc29uRnVsbFJlc3VsdCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuX3JlcG9ydGVyLm9uRW5kPy4oe1xuICAgICAgc3RhdHVzOiByZXN1bHQuc3RhdHVzLFxuICAgICAgc3RhcnRUaW1lOiBuZXcgRGF0ZShyZXN1bHQuc3RhcnRUaW1lKSxcbiAgICAgIGR1cmF0aW9uOiByZXN1bHQuZHVyYXRpb24sXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9vbkV4aXQoKTogUHJvbWlzZTx2b2lkPiB8IHZvaWQge1xuICAgIHJldHVybiB0aGlzLl9yZXBvcnRlci5vbkV4aXQ/LigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcGFyc2VDb25maWcoY29uZmlnOiBKc29uQ29uZmlnKTogcmVwb3J0ZXJUeXBlcy5GdWxsQ29uZmlnIHtcbiAgICBjb25zdCByZXN1bHQgPSB7IC4uLmJhc2VGdWxsQ29uZmlnLCAuLi5jb25maWcgfTtcbiAgICBpZiAodGhpcy5fb3B0aW9ucy5jb25maWdPdmVycmlkZXMpIHtcbiAgICAgIHJlc3VsdC5jb25maWdGaWxlID0gdGhpcy5fb3B0aW9ucy5jb25maWdPdmVycmlkZXMuY29uZmlnRmlsZTtcbiAgICAgIHJlc3VsdC5yZXBvcnRTbG93VGVzdHMgPSB0aGlzLl9vcHRpb25zLmNvbmZpZ092ZXJyaWRlcy5yZXBvcnRTbG93VGVzdHM7XG4gICAgICByZXN1bHQucXVpZXQgPSB0aGlzLl9vcHRpb25zLmNvbmZpZ092ZXJyaWRlcy5xdWlldDtcbiAgICAgIHJlc3VsdC5yZXBvcnRlciA9IFsuLi50aGlzLl9vcHRpb25zLmNvbmZpZ092ZXJyaWRlcy5yZXBvcnRlcl07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIF9wYXJzZVByb2plY3QocHJvamVjdDogSnNvblByb2plY3QpOiBUZWxlRnVsbFByb2plY3Qge1xuICAgIHJldHVybiB7XG4gICAgICBtZXRhZGF0YTogcHJvamVjdC5tZXRhZGF0YSxcbiAgICAgIG5hbWU6IHByb2plY3QubmFtZSxcbiAgICAgIG91dHB1dERpcjogdGhpcy5fYWJzb2x1dGVQYXRoKHByb2plY3Qub3V0cHV0RGlyKSxcbiAgICAgIHJlcGVhdEVhY2g6IHByb2plY3QucmVwZWF0RWFjaCxcbiAgICAgIHJldHJpZXM6IHByb2plY3QucmV0cmllcyxcbiAgICAgIHRlc3REaXI6IHRoaXMuX2Fic29sdXRlUGF0aChwcm9qZWN0LnRlc3REaXIpLFxuICAgICAgdGVzdElnbm9yZTogcGFyc2VSZWdleFBhdHRlcm5zKHByb2plY3QudGVzdElnbm9yZSksXG4gICAgICB0ZXN0TWF0Y2g6IHBhcnNlUmVnZXhQYXR0ZXJucyhwcm9qZWN0LnRlc3RNYXRjaCksXG4gICAgICB0aW1lb3V0OiBwcm9qZWN0LnRpbWVvdXQsXG4gICAgICBncmVwOiBwYXJzZVJlZ2V4UGF0dGVybnMocHJvamVjdC5ncmVwKSBhcyBSZWdFeHBbXSxcbiAgICAgIGdyZXBJbnZlcnQ6IHBhcnNlUmVnZXhQYXR0ZXJucyhwcm9qZWN0LmdyZXBJbnZlcnQpIGFzIFJlZ0V4cFtdLFxuICAgICAgZGVwZW5kZW5jaWVzOiBwcm9qZWN0LmRlcGVuZGVuY2llcyxcbiAgICAgIHRlYXJkb3duOiBwcm9qZWN0LnRlYXJkb3duLFxuICAgICAgc25hcHNob3REaXI6IHRoaXMuX2Fic29sdXRlUGF0aChwcm9qZWN0LnNuYXBzaG90RGlyKSxcbiAgICAgIHVzZTogcHJvamVjdC51c2UsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgX3BhcnNlQXR0YWNobWVudHMoYXR0YWNobWVudHM6IEpzb25BdHRhY2htZW50W10pOiByZXBvcnRlclR5cGVzLlRlc3RSZXN1bHRbJ2F0dGFjaG1lbnRzJ10ge1xuICAgIHJldHVybiBhdHRhY2htZW50cy5tYXAoYSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5hLFxuICAgICAgICBib2R5OiBhLmJhc2U2NCAmJiAoZ2xvYmFsVGhpcyBhcyBhbnkpLkJ1ZmZlciA/IEJ1ZmZlci5mcm9tKGEuYmFzZTY0LCAnYmFzZTY0JykgOiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfbWVyZ2VTdWl0ZUludG8oanNvblN1aXRlOiBKc29uU3VpdGUsIHBhcmVudDogVGVsZVN1aXRlKTogdm9pZCB7XG4gICAgbGV0IHRhcmdldFN1aXRlID0gcGFyZW50LnN1aXRlcy5maW5kKHMgPT4gcy50aXRsZSA9PT0ganNvblN1aXRlLnRpdGxlKTtcbiAgICBpZiAoIXRhcmdldFN1aXRlKSB7XG4gICAgICB0YXJnZXRTdWl0ZSA9IG5ldyBUZWxlU3VpdGUoanNvblN1aXRlLnRpdGxlLCBwYXJlbnQudHlwZSA9PT0gJ3Byb2plY3QnID8gJ2ZpbGUnIDogJ2Rlc2NyaWJlJyk7XG4gICAgICBwYXJlbnQuX2FkZFN1aXRlKHRhcmdldFN1aXRlKTtcbiAgICB9XG4gICAgdGFyZ2V0U3VpdGUubG9jYXRpb24gPSB0aGlzLl9hYnNvbHV0ZUxvY2F0aW9uKGpzb25TdWl0ZS5sb2NhdGlvbik7XG4gICAganNvblN1aXRlLmVudHJpZXMuZm9yRWFjaChlID0+IHtcbiAgICAgIGlmICgndGVzdElkJyBpbiBlKVxuICAgICAgICB0aGlzLl9tZXJnZVRlc3RJbnRvKGUsIHRhcmdldFN1aXRlISk7XG4gICAgICBlbHNlXG4gICAgICAgIHRoaXMuX21lcmdlU3VpdGVJbnRvKGUsIHRhcmdldFN1aXRlISk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9tZXJnZVRlc3RJbnRvKGpzb25UZXN0OiBKc29uVGVzdENhc2UsIHBhcmVudDogVGVsZVN1aXRlKSB7XG4gICAgbGV0IHRhcmdldFRlc3QgPSB0aGlzLl9vcHRpb25zLm1lcmdlVGVzdENhc2VzID8gcGFyZW50LnRlc3RzLmZpbmQocyA9PiBzLnRpdGxlID09PSBqc29uVGVzdC50aXRsZSAmJiBzLnJlcGVhdEVhY2hJbmRleCA9PT0ganNvblRlc3QucmVwZWF0RWFjaEluZGV4KSA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIXRhcmdldFRlc3QpIHtcbiAgICAgIHRhcmdldFRlc3QgPSBuZXcgVGVsZVRlc3RDYXNlKGpzb25UZXN0LnRlc3RJZCwganNvblRlc3QudGl0bGUsIHRoaXMuX2Fic29sdXRlTG9jYXRpb24oanNvblRlc3QubG9jYXRpb24pLCBqc29uVGVzdC5yZXBlYXRFYWNoSW5kZXgpO1xuICAgICAgcGFyZW50Ll9hZGRUZXN0KHRhcmdldFRlc3QpO1xuICAgICAgdGhpcy5fdGVzdHMuc2V0KHRhcmdldFRlc3QuaWQsIHRhcmdldFRlc3QpO1xuICAgIH1cbiAgICB0aGlzLl91cGRhdGVUZXN0KGpzb25UZXN0LCB0YXJnZXRUZXN0KTtcbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZVRlc3QocGF5bG9hZDogSnNvblRlc3RDYXNlLCB0ZXN0OiBUZWxlVGVzdENhc2UpOiBUZWxlVGVzdENhc2Uge1xuICAgIHRlc3QuaWQgPSBwYXlsb2FkLnRlc3RJZDtcbiAgICB0ZXN0LmxvY2F0aW9uID0gdGhpcy5fYWJzb2x1dGVMb2NhdGlvbihwYXlsb2FkLmxvY2F0aW9uKTtcbiAgICB0ZXN0LnJldHJpZXMgPSBwYXlsb2FkLnJldHJpZXM7XG4gICAgdGVzdC50YWdzID0gcGF5bG9hZC50YWdzID8/IFtdO1xuICAgIHRlc3QuYW5ub3RhdGlvbnMgPSBwYXlsb2FkLmFubm90YXRpb25zID8/IFtdO1xuICAgIHRoaXMuX2Fic29sdXRlQW5ub3RhdGlvbkxvY2F0aW9uc0lucGxhY2UodGVzdC5hbm5vdGF0aW9ucyk7XG4gICAgcmV0dXJuIHRlc3Q7XG4gIH1cblxuICBwcml2YXRlIF9hYnNvbHV0ZUFubm90YXRpb25Mb2NhdGlvbnNJbnBsYWNlKGFubm90YXRpb25zOiBUZXN0QW5ub3RhdGlvbltdKSB7XG4gICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7XG4gICAgICBpZiAoYW5ub3RhdGlvbi5sb2NhdGlvbilcbiAgICAgICAgYW5ub3RhdGlvbi5sb2NhdGlvbiA9IHRoaXMuX2Fic29sdXRlTG9jYXRpb24oYW5ub3RhdGlvbi5sb2NhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYWJzb2x1dGVMb2NhdGlvbihsb2NhdGlvbjogcmVwb3J0ZXJUeXBlcy5Mb2NhdGlvbik6IHJlcG9ydGVyVHlwZXMuTG9jYXRpb247XG4gIHByaXZhdGUgX2Fic29sdXRlTG9jYXRpb24obG9jYXRpb24/OiByZXBvcnRlclR5cGVzLkxvY2F0aW9uKTogcmVwb3J0ZXJUeXBlcy5Mb2NhdGlvbiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfYWJzb2x1dGVMb2NhdGlvbihsb2NhdGlvbjogcmVwb3J0ZXJUeXBlcy5Mb2NhdGlvbiB8IHVuZGVmaW5lZCk6IHJlcG9ydGVyVHlwZXMuTG9jYXRpb24gfCB1bmRlZmluZWQge1xuICAgIGlmICghbG9jYXRpb24pXG4gICAgICByZXR1cm4gbG9jYXRpb247XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmxvY2F0aW9uLFxuICAgICAgZmlsZTogdGhpcy5fYWJzb2x1dGVQYXRoKGxvY2F0aW9uLmZpbGUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9hYnNvbHV0ZVBhdGgocmVsYXRpdmVQYXRoOiBzdHJpbmcpOiBzdHJpbmc7XG4gIHByaXZhdGUgX2Fic29sdXRlUGF0aChyZWxhdGl2ZVBhdGg/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2Fic29sdXRlUGF0aChyZWxhdGl2ZVBhdGg/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmIChyZWxhdGl2ZVBhdGggPT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybjtcbiAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5yZXNvbHZlUGF0aCA/IHRoaXMuX29wdGlvbnMucmVzb2x2ZVBhdGgodGhpcy5fcm9vdERpciwgcmVsYXRpdmVQYXRoKSA6IHRoaXMuX3Jvb3REaXIgKyAnLycgKyByZWxhdGl2ZVBhdGg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRlbGVTdWl0ZSBpbXBsZW1lbnRzIHJlcG9ydGVyVHlwZXMuU3VpdGUge1xuICB0aXRsZTogc3RyaW5nO1xuICBsb2NhdGlvbj86IHJlcG9ydGVyVHlwZXMuTG9jYXRpb247XG4gIHBhcmVudD86IFRlbGVTdWl0ZTtcbiAgX2VudHJpZXM6IChUZWxlU3VpdGUgfCBUZWxlVGVzdENhc2UpW10gPSBbXTtcbiAgX3JlcXVpcmVGaWxlOiBzdHJpbmcgPSAnJztcbiAgX3RpbWVvdXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgX3JldHJpZXM6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgX3Byb2plY3Q6IFRlbGVGdWxsUHJvamVjdCB8IHVuZGVmaW5lZDtcbiAgX3BhcmFsbGVsTW9kZTogJ25vbmUnIHwgJ2RlZmF1bHQnIHwgJ3NlcmlhbCcgfCAncGFyYWxsZWwnID0gJ25vbmUnO1xuICBwcml2YXRlIHJlYWRvbmx5IF90eXBlOiAncm9vdCcgfCAncHJvamVjdCcgfCAnZmlsZScgfCAnZGVzY3JpYmUnO1xuXG4gIGNvbnN0cnVjdG9yKHRpdGxlOiBzdHJpbmcsIHR5cGU6ICdyb290JyB8ICdwcm9qZWN0JyB8ICdmaWxlJyB8ICdkZXNjcmliZScpIHtcbiAgICB0aGlzLnRpdGxlID0gdGl0bGU7XG4gICAgdGhpcy5fdHlwZSA9IHR5cGU7XG4gIH1cblxuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdHlwZTtcbiAgfVxuXG4gIGdldCBzdWl0ZXMoKTogVGVsZVN1aXRlW10ge1xuICAgIHJldHVybiB0aGlzLl9lbnRyaWVzLmZpbHRlcihlID0+IGUudHlwZSAhPT0gJ3Rlc3QnKSBhcyBUZWxlU3VpdGVbXTtcbiAgfVxuXG4gIGdldCB0ZXN0cygpOiBUZWxlVGVzdENhc2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2VudHJpZXMuZmlsdGVyKGUgPT4gZS50eXBlID09PSAndGVzdCcpIGFzIFRlbGVUZXN0Q2FzZVtdO1xuICB9XG5cbiAgZW50cmllcygpIHtcbiAgICByZXR1cm4gdGhpcy5fZW50cmllcztcbiAgfVxuXG4gIGFsbFRlc3RzKCk6IHJlcG9ydGVyVHlwZXMuVGVzdENhc2VbXSB7XG4gICAgY29uc3QgcmVzdWx0OiByZXBvcnRlclR5cGVzLlRlc3RDYXNlW10gPSBbXTtcbiAgICBjb25zdCB2aXNpdCA9IChzdWl0ZTogcmVwb3J0ZXJUeXBlcy5TdWl0ZSkgPT4ge1xuICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBzdWl0ZS5lbnRyaWVzKCkpIHtcbiAgICAgICAgaWYgKGVudHJ5LnR5cGUgPT09ICd0ZXN0JylcbiAgICAgICAgICByZXN1bHQucHVzaChlbnRyeSk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICB2aXNpdChlbnRyeSk7XG4gICAgICB9XG4gICAgfTtcbiAgICB2aXNpdCh0aGlzKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdGl0bGVQYXRoKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0aXRsZVBhdGggPSB0aGlzLnBhcmVudCA/IHRoaXMucGFyZW50LnRpdGxlUGF0aCgpIDogW107XG4gICAgLy8gSWdub3JlIGFub255bW91cyBkZXNjcmliZSBibG9ja3MuXG4gICAgaWYgKHRoaXMudGl0bGUgfHwgdGhpcy5fdHlwZSAhPT0gJ2Rlc2NyaWJlJylcbiAgICAgIHRpdGxlUGF0aC5wdXNoKHRoaXMudGl0bGUpO1xuICAgIHJldHVybiB0aXRsZVBhdGg7XG4gIH1cblxuICBwcm9qZWN0KCk6IFRlbGVGdWxsUHJvamVjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3Byb2plY3QgPz8gdGhpcy5wYXJlbnQ/LnByb2plY3QoKTtcbiAgfVxuXG4gIF9hZGRUZXN0KHRlc3Q6IFRlbGVUZXN0Q2FzZSkge1xuICAgIHRlc3QucGFyZW50ID0gdGhpcztcbiAgICB0aGlzLl9lbnRyaWVzLnB1c2godGVzdCk7XG4gIH1cblxuICBfYWRkU3VpdGUoc3VpdGU6IFRlbGVTdWl0ZSkge1xuICAgIHN1aXRlLnBhcmVudCA9IHRoaXM7XG4gICAgdGhpcy5fZW50cmllcy5wdXNoKHN1aXRlKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgVGVsZVRlc3RDYXNlIGltcGxlbWVudHMgcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSB7XG4gIHRpdGxlOiBzdHJpbmc7XG4gIGZuID0gKCkgPT4ge307XG4gIHJlc3VsdHM6IFRlbGVUZXN0UmVzdWx0W10gPSBbXTtcbiAgbG9jYXRpb246IHJlcG9ydGVyVHlwZXMuTG9jYXRpb247XG4gIHBhcmVudCE6IFRlbGVTdWl0ZTtcbiAgdHlwZTogJ3Rlc3QnID0gJ3Rlc3QnO1xuXG4gIGV4cGVjdGVkU3RhdHVzOiByZXBvcnRlclR5cGVzLlRlc3RTdGF0dXMgPSAncGFzc2VkJztcbiAgdGltZW91dCA9IDA7XG4gIGFubm90YXRpb25zOiBUZXN0QW5ub3RhdGlvbltdID0gW107XG4gIHJldHJpZXMgPSAwO1xuICB0YWdzOiBzdHJpbmdbXSA9IFtdO1xuICByZXBlYXRFYWNoSW5kZXggPSAwO1xuICBpZDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGlkOiBzdHJpbmcsIHRpdGxlOiBzdHJpbmcsIGxvY2F0aW9uOiByZXBvcnRlclR5cGVzLkxvY2F0aW9uLCByZXBlYXRFYWNoSW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLnRpdGxlID0gdGl0bGU7XG4gICAgdGhpcy5sb2NhdGlvbiA9IGxvY2F0aW9uO1xuICAgIHRoaXMucmVwZWF0RWFjaEluZGV4ID0gcmVwZWF0RWFjaEluZGV4O1xuICB9XG5cbiAgdGl0bGVQYXRoKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0aXRsZVBhdGggPSB0aGlzLnBhcmVudCA/IHRoaXMucGFyZW50LnRpdGxlUGF0aCgpIDogW107XG4gICAgdGl0bGVQYXRoLnB1c2godGhpcy50aXRsZSk7XG4gICAgcmV0dXJuIHRpdGxlUGF0aDtcbiAgfVxuXG4gIG91dGNvbWUoKTogJ3NraXBwZWQnIHwgJ2V4cGVjdGVkJyB8ICd1bmV4cGVjdGVkJyB8ICdmbGFreScge1xuICAgIHJldHVybiBjb21wdXRlVGVzdENhc2VPdXRjb21lKHRoaXMpO1xuICB9XG5cbiAgb2soKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc3RhdHVzID0gdGhpcy5vdXRjb21lKCk7XG4gICAgcmV0dXJuIHN0YXR1cyA9PT0gJ2V4cGVjdGVkJyB8fCBzdGF0dXMgPT09ICdmbGFreScgfHwgc3RhdHVzID09PSAnc2tpcHBlZCc7XG4gIH1cblxuICBfY3JlYXRlVGVzdFJlc3VsdChpZDogc3RyaW5nKTogVGVsZVRlc3RSZXN1bHQge1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBUZWxlVGVzdFJlc3VsdCh0aGlzLnJlc3VsdHMubGVuZ3RoLCBpZCk7XG4gICAgdGhpcy5yZXN1bHRzLnB1c2gocmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbmNsYXNzIFRlbGVUZXN0U3RlcCBpbXBsZW1lbnRzIHJlcG9ydGVyVHlwZXMuVGVzdFN0ZXAge1xuICB0aXRsZTogc3RyaW5nO1xuICBjYXRlZ29yeTogc3RyaW5nO1xuICBsb2NhdGlvbjogcmVwb3J0ZXJUeXBlcy5Mb2NhdGlvbiB8IHVuZGVmaW5lZDtcbiAgcGFyZW50OiByZXBvcnRlclR5cGVzLlRlc3RTdGVwIHwgdW5kZWZpbmVkO1xuICBkdXJhdGlvbjogbnVtYmVyID0gLTE7XG4gIHN0ZXBzOiByZXBvcnRlclR5cGVzLlRlc3RTdGVwW10gPSBbXTtcbiAgZXJyb3I6IHJlcG9ydGVyVHlwZXMuVGVzdEVycm9yIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgX3Jlc3VsdDogVGVsZVRlc3RSZXN1bHQ7XG4gIF9lbmRQYXlsb2FkPzogSnNvblRlc3RTdGVwRW5kO1xuXG4gIHByaXZhdGUgX3N0YXJ0VGltZTogbnVtYmVyID0gMDtcblxuICBjb25zdHJ1Y3RvcihwYXlsb2FkOiBKc29uVGVzdFN0ZXBTdGFydCwgcGFyZW50U3RlcDogcmVwb3J0ZXJUeXBlcy5UZXN0U3RlcCB8IHVuZGVmaW5lZCwgbG9jYXRpb246IHJlcG9ydGVyVHlwZXMuTG9jYXRpb24gfCB1bmRlZmluZWQsIHJlc3VsdDogVGVsZVRlc3RSZXN1bHQpIHtcbiAgICB0aGlzLnRpdGxlID0gcGF5bG9hZC50aXRsZTtcbiAgICB0aGlzLmNhdGVnb3J5ID0gcGF5bG9hZC5jYXRlZ29yeTtcbiAgICB0aGlzLmxvY2F0aW9uID0gbG9jYXRpb247XG4gICAgdGhpcy5wYXJlbnQgPSBwYXJlbnRTdGVwO1xuICAgIHRoaXMuX3N0YXJ0VGltZSA9IHBheWxvYWQuc3RhcnRUaW1lO1xuICAgIHRoaXMuX3Jlc3VsdCA9IHJlc3VsdDtcbiAgfVxuXG4gIHRpdGxlUGF0aCgpIHtcbiAgICBjb25zdCBwYXJlbnRQYXRoID0gdGhpcy5wYXJlbnQ/LnRpdGxlUGF0aCgpIHx8IFtdO1xuICAgIHJldHVybiBbLi4ucGFyZW50UGF0aCwgdGhpcy50aXRsZV07XG4gIH1cblxuICBnZXQgc3RhcnRUaW1lKCk6IERhdGUge1xuICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLl9zdGFydFRpbWUpO1xuICB9XG5cbiAgc2V0IHN0YXJ0VGltZSh2YWx1ZTogRGF0ZSkge1xuICAgIHRoaXMuX3N0YXJ0VGltZSA9ICt2YWx1ZTtcbiAgfVxuXG4gIGdldCBhdHRhY2htZW50cygpIHtcbiAgICByZXR1cm4gdGhpcy5fZW5kUGF5bG9hZD8uYXR0YWNobWVudHM/Lm1hcChpbmRleCA9PiB0aGlzLl9yZXN1bHQuYXR0YWNobWVudHNbaW5kZXhdKSA/PyBbXTtcbiAgfVxuXG4gIGdldCBhbm5vdGF0aW9ucygpIHtcbiAgICByZXR1cm4gdGhpcy5fZW5kUGF5bG9hZD8uYW5ub3RhdGlvbnMgPz8gW107XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRlbGVUZXN0UmVzdWx0IGltcGxlbWVudHMgcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0IHtcbiAgcmV0cnk6IHJlcG9ydGVyVHlwZXMuVGVzdFJlc3VsdFsncmV0cnknXTtcbiAgcGFyYWxsZWxJbmRleDogcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0WydwYXJhbGxlbEluZGV4J10gPSAtMTtcbiAgd29ya2VySW5kZXg6IHJlcG9ydGVyVHlwZXMuVGVzdFJlc3VsdFsnd29ya2VySW5kZXgnXSA9IC0xO1xuICBkdXJhdGlvbjogcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0WydkdXJhdGlvbiddID0gLTE7XG4gIHN0ZG91dDogcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0WydzdGRvdXQnXSA9IFtdO1xuICBzdGRlcnI6IHJlcG9ydGVyVHlwZXMuVGVzdFJlc3VsdFsnc3RkZXJyJ10gPSBbXTtcbiAgYXR0YWNobWVudHM6IHJlcG9ydGVyVHlwZXMuVGVzdFJlc3VsdFsnYXR0YWNobWVudHMnXSA9IFtdO1xuICBhbm5vdGF0aW9uczogcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0Wydhbm5vdGF0aW9ucyddID0gW107XG4gIHN0YXR1czogcmVwb3J0ZXJUeXBlcy5UZXN0U3RhdHVzID0gJ3NraXBwZWQnO1xuICBzdGVwczogVGVsZVRlc3RTdGVwW10gPSBbXTtcbiAgZXJyb3JzOiByZXBvcnRlclR5cGVzLlRlc3RSZXN1bHRbJ2Vycm9ycyddID0gW107XG4gIGVycm9yOiByZXBvcnRlclR5cGVzLlRlc3RSZXN1bHRbJ2Vycm9yJ107XG5cbiAgX3N0ZXBNYXAgPSBuZXcgTWFwPHN0cmluZywgVGVsZVRlc3RTdGVwPigpO1xuICBfaWQ6IHN0cmluZztcblxuICBwcml2YXRlIF9zdGFydFRpbWU6IG51bWJlciA9IDA7XG5cbiAgY29uc3RydWN0b3IocmV0cnk6IG51bWJlciwgaWQ6IHN0cmluZykge1xuICAgIHRoaXMucmV0cnkgPSByZXRyeTtcbiAgICB0aGlzLl9pZCA9IGlkO1xuICB9XG5cbiAgc2V0U3RhcnRUaW1lTnVtYmVyKHN0YXJ0VGltZTogbnVtYmVyKSB7XG4gICAgdGhpcy5fc3RhcnRUaW1lID0gc3RhcnRUaW1lO1xuICB9XG5cbiAgZ2V0IHN0YXJ0VGltZSgpOiBEYXRlIHtcbiAgICByZXR1cm4gbmV3IERhdGUodGhpcy5fc3RhcnRUaW1lKTtcbiAgfVxuXG4gIHNldCBzdGFydFRpbWUodmFsdWU6IERhdGUpIHtcbiAgICB0aGlzLl9zdGFydFRpbWUgPSArdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgVGVsZUZ1bGxQcm9qZWN0ID0gcmVwb3J0ZXJUeXBlcy5GdWxsUHJvamVjdDtcblxuZXhwb3J0IGNvbnN0IGJhc2VGdWxsQ29uZmlnOiByZXBvcnRlclR5cGVzLkZ1bGxDb25maWcgPSB7XG4gIGZvcmJpZE9ubHk6IGZhbHNlLFxuICBmdWxseVBhcmFsbGVsOiBmYWxzZSxcbiAgZ2xvYmFsU2V0dXA6IG51bGwsXG4gIGdsb2JhbFRlYXJkb3duOiBudWxsLFxuICBnbG9iYWxUaW1lb3V0OiAwLFxuICBncmVwOiAvLiovLFxuICBncmVwSW52ZXJ0OiBudWxsLFxuICBtYXhGYWlsdXJlczogMCxcbiAgbWV0YWRhdGE6IHt9LFxuICBwcmVzZXJ2ZU91dHB1dDogJ2Fsd2F5cycsXG4gIHByb2plY3RzOiBbXSxcbiAgcmVwb3J0ZXI6IFtbcHJvY2Vzcy5lbnYuQ0kgPyAnZG90JyA6ICdsaXN0J11dLFxuICByZXBvcnRTbG93VGVzdHM6IHsgbWF4OiA1LCB0aHJlc2hvbGQ6IDMwMF8wMDAgLyogNSBtaW51dGVzICovIH0sXG4gIGNvbmZpZ0ZpbGU6ICcnLFxuICByb290RGlyOiAnJyxcbiAgcXVpZXQ6IGZhbHNlLFxuICBzaGFyZDogbnVsbCxcbiAgdGFnczogW10sXG4gIHVwZGF0ZVNuYXBzaG90czogJ21pc3NpbmcnLFxuICB1cGRhdGVTb3VyY2VNZXRob2Q6ICdwYXRjaCcsXG4gIHZlcnNpb246ICcnLFxuICB3b3JrZXJzOiAwLFxuICB3ZWJTZXJ2ZXI6IG51bGwsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplUmVnZXhQYXR0ZXJucyhwYXR0ZXJuczogc3RyaW5nIHwgUmVnRXhwIHwgKHN0cmluZyB8IFJlZ0V4cClbXSk6IEpzb25QYXR0ZXJuW10ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkocGF0dGVybnMpKVxuICAgIHBhdHRlcm5zID0gW3BhdHRlcm5zXTtcbiAgcmV0dXJuIHBhdHRlcm5zLm1hcChzID0+IHtcbiAgICBpZiAodHlwZW9mIHMgPT09ICdzdHJpbmcnKVxuICAgICAgcmV0dXJuIHsgcyB9O1xuICAgIHJldHVybiB7IHI6IHsgc291cmNlOiBzLnNvdXJjZSwgZmxhZ3M6IHMuZmxhZ3MgfSB9O1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUmVnZXhQYXR0ZXJucyhwYXR0ZXJuczogSnNvblBhdHRlcm5bXSk6IChzdHJpbmcgfCBSZWdFeHApW10ge1xuICByZXR1cm4gcGF0dGVybnMubWFwKHAgPT4ge1xuICAgIGlmIChwLnMgIT09IHVuZGVmaW5lZClcbiAgICAgIHJldHVybiBwLnM7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAocC5yIS5zb3VyY2UsIHAuciEuZmxhZ3MpO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVUZXN0Q2FzZU91dGNvbWUodGVzdDogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSkge1xuICBsZXQgc2tpcHBlZCA9IDA7XG4gIGxldCBkaWROb3RSdW4gPSAwO1xuICBsZXQgZXhwZWN0ZWQgPSAwO1xuICBsZXQgaW50ZXJydXB0ZWQgPSAwO1xuICBsZXQgdW5leHBlY3RlZCA9IDA7XG4gIGZvciAoY29uc3QgcmVzdWx0IG9mIHRlc3QucmVzdWx0cykge1xuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAnaW50ZXJydXB0ZWQnKSB7XG4gICAgICArK2ludGVycnVwdGVkOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gZWxzZSBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3NraXBwZWQnICYmIHRlc3QuZXhwZWN0ZWRTdGF0dXMgPT09ICdza2lwcGVkJykge1xuICAgICAgLy8gT25seSB0ZXN0cyBcImV4cGVjdGVkIHRvIGJlIHNraXBwZWRcIiBhcmUgc2tpcHBlZC4gVGhlc2Ugd2VyZSBzcGVjaWZpY2FsbHlcbiAgICAgIC8vIG1hcmtlZCB3aXRoIHRlc3Quc2tpcCBvciB0ZXN0LmZpeG1lLlxuICAgICAgKytza2lwcGVkO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ3NraXBwZWQnKSB7XG4gICAgICAvLyBUZXN0cyB0aGF0IHdlcmUgZXhwZWN0ZWQgdG8gcnVuLCBidXQgd2VyZSBza2lwcGVkIGFyZSBcImRpZCBub3QgcnVuXCIuXG4gICAgICAvLyBUaGlzIGhhcHBlbnMgd2hlbjpcbiAgICAgIC8vIC0gdGVzdGluZyBmaW5pc2hlZCBlYXJseTtcbiAgICAgIC8vIC0gdGVzdCBmYWlsdXJlIHByZXZlbnRlZCBvdGhlciB0ZXN0cyBpbiB0aGUgc2VyaWFsIHN1aXRlIHRvIHJ1bjtcbiAgICAgIC8vIC0gcHJvYmFibHkgbW9yZSBjYXNlcyFcbiAgICAgICsrZGlkTm90UnVuOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gZWxzZSBpZiAocmVzdWx0LnN0YXR1cyA9PT0gdGVzdC5leHBlY3RlZFN0YXR1cykge1xuICAgICAgLy8gRWl0aGVyIHBhc3NlZCBhbmQgZXhwZWN0ZWQgdG8gcGFzcywgb3IgZmFpbGVkIGFuZCBleHBlY3RlZCB0byBmYWlsLlxuICAgICAgKytleHBlY3RlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgKyt1bmV4cGVjdGVkO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRlc3RzIHRoYXQgd2VyZSBcInNraXBwZWQgYXMgZXhwZWN0ZWRcIiBhcmUgY29uc2lkZXJlZCBlcXVhbCB0byBcImV4cGVjdGVkXCIgYmVsb3csXG4gIC8vIGJlY2F1c2UgdGhhdCdzIHRoZSBleHBlY3RlZCBvdXRjb21lLlxuICAvL1xuICAvLyBIb3dldmVyLCB3ZSBzcGVjaWZpY2FsbHkgZGlmZmVyZW50aWF0ZSB0aGUgY2FzZSBvZiBcIm9ubHkgc2tpcHBlZFwiXG4gIC8vIGFuZCBzaG93IGl0IGFzIFwic2tpcHBlZFwiIGluIGFsbCByZXBvcnRlcnMuXG4gIC8vXG4gIC8vIE1vcmUgZXhvdGljIGNhc2VzIGxpa2UgXCJmYWlsZWQgb24gZmlyc3QgcnVuIGFuZCBza2lwcGVkIG9uIHJldHJ5XCIgYXJlIGZsYWt5LlxuICBpZiAoZXhwZWN0ZWQgPT09IDAgJiYgdW5leHBlY3RlZCA9PT0gMClcbiAgICByZXR1cm4gJ3NraXBwZWQnOyAgLy8gYWxsIHJlc3VsdHMgd2VyZSBza2lwcGVkIG9yIGludGVycnVwdGVkXG4gIGlmICh1bmV4cGVjdGVkID09PSAwKVxuICAgIHJldHVybiAnZXhwZWN0ZWQnOyAgLy8gbm8gZmFpbHVyZXMsIGp1c3QgZXhwZWN0ZWQrc2tpcHBlZFxuICBpZiAoZXhwZWN0ZWQgPT09IDAgJiYgc2tpcHBlZCA9PT0gMClcbiAgICByZXR1cm4gJ3VuZXhwZWN0ZWQnOyAgLy8gb25seSBmYWlsdXJlc1xuICByZXR1cm4gJ2ZsYWt5JzsgIC8vIGV4cGVjdGVkK3VuZXhwZWN0ZWQgb3Igc2tpcHBlZCt1bmV4cGVjdGVkXG59XG4iLCIvKipcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgdHlwZSBUZXN0SXRlbVN0YXR1cyA9ICdub25lJyB8ICdydW5uaW5nJyB8ICdzY2hlZHVsZWQnIHwgJ3Bhc3NlZCcgfCAnZmFpbGVkJyB8ICdza2lwcGVkJztcbmltcG9ydCB0eXBlICogYXMgcmVwb3J0ZXJUeXBlcyBmcm9tICcuLi8uLi90eXBlcy90ZXN0UmVwb3J0ZXInO1xuXG4vLyAtLSBSZXVzZSBib3VuZGFyeSAtLSBFdmVyeXRoaW5nIGJlbG93IHRoaXMgbGluZSBpcyByZXVzZWQgaW4gdGhlIHZzY29kZSBleHRlbnNpb24uXG5cbmV4cG9ydCB0eXBlIFRyZWVJdGVtQmFzZSA9IHtcbiAga2luZDogJ3Jvb3QnIHwgJ2dyb3VwJyB8ICdjYXNlJyB8ICd0ZXN0JyxcbiAgaWQ6IHN0cmluZztcbiAgdGl0bGU6IHN0cmluZztcbiAgbG9jYXRpb246IHJlcG9ydGVyVHlwZXMuTG9jYXRpb24sXG4gIGR1cmF0aW9uOiBudW1iZXI7XG4gIHBhcmVudDogVHJlZUl0ZW0gfCB1bmRlZmluZWQ7XG4gIGNoaWxkcmVuOiBUcmVlSXRlbVtdO1xuICBzdGF0dXM6IFRlc3RJdGVtU3RhdHVzO1xufTtcblxuZXhwb3J0IHR5cGUgR3JvdXBJdGVtID0gVHJlZUl0ZW1CYXNlICYge1xuICBraW5kOiAnZ3JvdXAnO1xuICBzdWJLaW5kOiAnZm9sZGVyJyB8ICdmaWxlJyB8ICdkZXNjcmliZSc7XG4gIGhhc0xvYWRFcnJvcnM6IGJvb2xlYW47XG4gIGNoaWxkcmVuOiAoVGVzdENhc2VJdGVtIHwgR3JvdXBJdGVtKVtdO1xufTtcblxuZXhwb3J0IHR5cGUgVGVzdENhc2VJdGVtID0gVHJlZUl0ZW1CYXNlICYge1xuICBraW5kOiAnY2FzZScsXG4gIHRlc3RzOiByZXBvcnRlclR5cGVzLlRlc3RDYXNlW107XG4gIGNoaWxkcmVuOiBUZXN0SXRlbVtdO1xuICB0ZXN0OiByZXBvcnRlclR5cGVzLlRlc3RDYXNlIHwgdW5kZWZpbmVkO1xuICBwcm9qZWN0OiByZXBvcnRlclR5cGVzLkZ1bGxQcm9qZWN0IHwgdW5kZWZpbmVkO1xuICB0YWdzOiBBcnJheTxzdHJpbmc+O1xufTtcblxuZXhwb3J0IHR5cGUgVGVzdEl0ZW0gPSBUcmVlSXRlbUJhc2UgJiB7XG4gIGtpbmQ6ICd0ZXN0JyxcbiAgdGVzdDogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZTtcbiAgcHJvamVjdDogcmVwb3J0ZXJUeXBlcy5GdWxsUHJvamVjdDtcbn07XG5cbmV4cG9ydCB0eXBlIFRyZWVJdGVtID0gR3JvdXBJdGVtIHwgVGVzdENhc2VJdGVtIHwgVGVzdEl0ZW07XG5cbmV4cG9ydCBjbGFzcyBUZXN0VHJlZSB7XG4gIHJvb3RJdGVtOiBHcm91cEl0ZW07XG4gIHByaXZhdGUgX3RyZWVJdGVtQnlJZCA9IG5ldyBNYXA8c3RyaW5nLCBUcmVlSXRlbT4oKTtcbiAgcHJpdmF0ZSBfdHJlZUl0ZW1CeVRlc3RJZCA9IG5ldyBNYXA8c3RyaW5nLCBUZXN0SXRlbSB8IFRlc3RDYXNlSXRlbT4oKTtcbiAgcmVhZG9ubHkgcGF0aFNlcGFyYXRvcjogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHJvb3RGb2xkZXI6IHN0cmluZywgcm9vdFN1aXRlOiByZXBvcnRlclR5cGVzLlN1aXRlIHwgdW5kZWZpbmVkLCBsb2FkRXJyb3JzOiByZXBvcnRlclR5cGVzLlRlc3RFcnJvcltdLCBwcm9qZWN0RmlsdGVyczogTWFwPHN0cmluZywgYm9vbGVhbj4gfCB1bmRlZmluZWQsIHBhdGhTZXBhcmF0b3I6IHN0cmluZywgaGlkZUZpbGVzOiBib29sZWFuKSB7XG4gICAgY29uc3QgZmlsdGVyUHJvamVjdHMgPSBwcm9qZWN0RmlsdGVycyAmJiBbLi4ucHJvamVjdEZpbHRlcnMudmFsdWVzKCldLnNvbWUoQm9vbGVhbik7XG4gICAgdGhpcy5wYXRoU2VwYXJhdG9yID0gcGF0aFNlcGFyYXRvcjtcbiAgICB0aGlzLnJvb3RJdGVtID0ge1xuICAgICAga2luZDogJ2dyb3VwJyxcbiAgICAgIHN1YktpbmQ6ICdmb2xkZXInLFxuICAgICAgaWQ6IHJvb3RGb2xkZXIsXG4gICAgICB0aXRsZTogJycsXG4gICAgICBsb2NhdGlvbjogeyBmaWxlOiAnJywgbGluZTogMCwgY29sdW1uOiAwIH0sXG4gICAgICBkdXJhdGlvbjogMCxcbiAgICAgIHBhcmVudDogdW5kZWZpbmVkLFxuICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgc3RhdHVzOiAnbm9uZScsXG4gICAgICBoYXNMb2FkRXJyb3JzOiBmYWxzZSxcbiAgICB9O1xuICAgIHRoaXMuX3RyZWVJdGVtQnlJZC5zZXQocm9vdEZvbGRlciwgdGhpcy5yb290SXRlbSk7XG5cbiAgICBjb25zdCB2aXNpdFN1aXRlID0gKHByb2plY3Q6IHJlcG9ydGVyVHlwZXMuRnVsbFByb2plY3QsIHBhcmVudFN1aXRlOiByZXBvcnRlclR5cGVzLlN1aXRlLCBwYXJlbnRHcm91cDogR3JvdXBJdGVtLCBtb2RlOiAndGVzdHMnIHwgJ3N1aXRlcycgfCAnYWxsJykgPT4ge1xuICAgICAgZm9yIChjb25zdCBzdWl0ZSBvZiBtb2RlID09PSAndGVzdHMnID8gW10gOiBwYXJlbnRTdWl0ZS5zdWl0ZXMpIHtcbiAgICAgICAgaWYgKCFzdWl0ZS50aXRsZSkge1xuICAgICAgICAgIC8vIEZsYXR0ZW4gYW5vbnltb3VzIGRlc2NyaWJlcy5cbiAgICAgICAgICB2aXNpdFN1aXRlKHByb2plY3QsIHN1aXRlLCBwYXJlbnRHcm91cCwgJ2FsbCcpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGdyb3VwID0gcGFyZW50R3JvdXAuY2hpbGRyZW4uZmluZChpdGVtID0+IGl0ZW0ua2luZCA9PT0gJ2dyb3VwJyAmJiBpdGVtLnRpdGxlID09PSBzdWl0ZS50aXRsZSkgYXMgR3JvdXBJdGVtIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoIWdyb3VwKSB7XG4gICAgICAgICAgZ3JvdXAgPSB7XG4gICAgICAgICAgICBraW5kOiAnZ3JvdXAnLFxuICAgICAgICAgICAgc3ViS2luZDogJ2Rlc2NyaWJlJyxcbiAgICAgICAgICAgIGlkOiAnc3VpdGU6JyArIHBhcmVudFN1aXRlLnRpdGxlUGF0aCgpLmpvaW4oJ1xceDFlJykgKyAnXFx4MWUnICsgc3VpdGUudGl0bGUsICAvLyBhY2NvdW50IGZvciBhbm9ueW1vdXMgc3VpdGVzXG4gICAgICAgICAgICB0aXRsZTogc3VpdGUudGl0bGUsXG4gICAgICAgICAgICBsb2NhdGlvbjogc3VpdGUubG9jYXRpb24hLFxuICAgICAgICAgICAgZHVyYXRpb246IDAsXG4gICAgICAgICAgICBwYXJlbnQ6IHBhcmVudEdyb3VwLFxuICAgICAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgICAgICAgc3RhdHVzOiAnbm9uZScsXG4gICAgICAgICAgICBoYXNMb2FkRXJyb3JzOiBmYWxzZSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRoaXMuX2FkZENoaWxkKHBhcmVudEdyb3VwLCBncm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlzaXRTdWl0ZShwcm9qZWN0LCBzdWl0ZSwgZ3JvdXAsICdhbGwnKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCB0ZXN0IG9mIG1vZGUgPT09ICdzdWl0ZXMnID8gW10gOiBwYXJlbnRTdWl0ZS50ZXN0cykge1xuICAgICAgICBjb25zdCB0aXRsZSA9IHRlc3QudGl0bGU7XG4gICAgICAgIGxldCB0ZXN0Q2FzZUl0ZW0gPSBwYXJlbnRHcm91cC5jaGlsZHJlbi5maW5kKHQgPT4gdC5raW5kICE9PSAnZ3JvdXAnICYmIHQudGl0bGUgPT09IHRpdGxlKSBhcyBUZXN0Q2FzZUl0ZW07XG4gICAgICAgIGlmICghdGVzdENhc2VJdGVtKSB7XG4gICAgICAgICAgdGVzdENhc2VJdGVtID0ge1xuICAgICAgICAgICAga2luZDogJ2Nhc2UnLFxuICAgICAgICAgICAgaWQ6ICd0ZXN0OicgKyB0ZXN0LnRpdGxlUGF0aCgpLmpvaW4oJ1xceDFlJyksXG4gICAgICAgICAgICB0aXRsZSxcbiAgICAgICAgICAgIHBhcmVudDogcGFyZW50R3JvdXAsXG4gICAgICAgICAgICBjaGlsZHJlbjogW10sXG4gICAgICAgICAgICB0ZXN0czogW10sXG4gICAgICAgICAgICBsb2NhdGlvbjogdGVzdC5sb2NhdGlvbixcbiAgICAgICAgICAgIGR1cmF0aW9uOiAwLFxuICAgICAgICAgICAgc3RhdHVzOiAnbm9uZScsXG4gICAgICAgICAgICBwcm9qZWN0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICB0ZXN0OiB1bmRlZmluZWQsXG4gICAgICAgICAgICB0YWdzOiB0ZXN0LnRhZ3MsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLl9hZGRDaGlsZChwYXJlbnRHcm91cCwgdGVzdENhc2VJdGVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRlc3QucmVzdWx0c1swXTtcbiAgICAgICAgbGV0IHN0YXR1czogJ25vbmUnIHwgJ3J1bm5pbmcnIHwgJ3NjaGVkdWxlZCcgfCAncGFzc2VkJyB8ICdmYWlsZWQnIHwgJ3NraXBwZWQnID0gJ25vbmUnO1xuICAgICAgICBpZiAoKHJlc3VsdCBhcyBhbnkpPy5bc3RhdHVzRXhdID09PSAnc2NoZWR1bGVkJylcbiAgICAgICAgICBzdGF0dXMgPSAnc2NoZWR1bGVkJztcbiAgICAgICAgZWxzZSBpZiAoKHJlc3VsdCBhcyBhbnkpPy5bc3RhdHVzRXhdID09PSAncnVubmluZycpXG4gICAgICAgICAgc3RhdHVzID0gJ3J1bm5pbmcnO1xuICAgICAgICBlbHNlIGlmIChyZXN1bHQ/LnN0YXR1cyA9PT0gJ3NraXBwZWQnKVxuICAgICAgICAgIHN0YXR1cyA9ICdza2lwcGVkJztcbiAgICAgICAgZWxzZSBpZiAocmVzdWx0Py5zdGF0dXMgPT09ICdpbnRlcnJ1cHRlZCcpXG4gICAgICAgICAgc3RhdHVzID0gJ25vbmUnO1xuICAgICAgICBlbHNlIGlmIChyZXN1bHQgJiYgdGVzdC5vdXRjb21lKCkgIT09ICdleHBlY3RlZCcpXG4gICAgICAgICAgc3RhdHVzID0gJ2ZhaWxlZCc7XG4gICAgICAgIGVsc2UgaWYgKHJlc3VsdCAmJiB0ZXN0Lm91dGNvbWUoKSA9PT0gJ2V4cGVjdGVkJylcbiAgICAgICAgICBzdGF0dXMgPSAncGFzc2VkJztcblxuICAgICAgICB0ZXN0Q2FzZUl0ZW0udGVzdHMucHVzaCh0ZXN0KTtcbiAgICAgICAgY29uc3QgdGVzdEl0ZW06IFRlc3RJdGVtID0ge1xuICAgICAgICAgIGtpbmQ6ICd0ZXN0JyxcbiAgICAgICAgICBpZDogdGVzdC5pZCxcbiAgICAgICAgICB0aXRsZTogcHJvamVjdC5uYW1lLFxuICAgICAgICAgIGxvY2F0aW9uOiB0ZXN0LmxvY2F0aW9uISxcbiAgICAgICAgICB0ZXN0LFxuICAgICAgICAgIHBhcmVudDogdGVzdENhc2VJdGVtLFxuICAgICAgICAgIGNoaWxkcmVuOiBbXSxcbiAgICAgICAgICBzdGF0dXMsXG4gICAgICAgICAgZHVyYXRpb246IHRlc3QucmVzdWx0cy5sZW5ndGggPyBNYXRoLm1heCgwLCB0ZXN0LnJlc3VsdHNbMF0uZHVyYXRpb24pIDogMCxcbiAgICAgICAgICBwcm9qZWN0LFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLl9hZGRDaGlsZCh0ZXN0Q2FzZUl0ZW0sIHRlc3RJdGVtKTtcbiAgICAgICAgdGhpcy5fdHJlZUl0ZW1CeVRlc3RJZC5zZXQodGVzdC5pZCwgdGVzdEl0ZW0pO1xuICAgICAgICB0ZXN0Q2FzZUl0ZW0uZHVyYXRpb24gPSAodGVzdENhc2VJdGVtLmNoaWxkcmVuIGFzIFRlc3RJdGVtW10pLnJlZHVjZSgoYSwgYikgPT4gYSArIGIuZHVyYXRpb24sIDApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IHByb2plY3RTdWl0ZSBvZiByb290U3VpdGU/LnN1aXRlcyB8fCBbXSkge1xuICAgICAgaWYgKGZpbHRlclByb2plY3RzICYmICFwcm9qZWN0RmlsdGVycy5nZXQocHJvamVjdFN1aXRlLnRpdGxlKSlcbiAgICAgICAgY29udGludWU7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVTdWl0ZSBvZiBwcm9qZWN0U3VpdGUuc3VpdGVzKSB7XG4gICAgICAgIGlmIChoaWRlRmlsZXMpIHtcbiAgICAgICAgICB2aXNpdFN1aXRlKHByb2plY3RTdWl0ZS5wcm9qZWN0KCkhLCBmaWxlU3VpdGUsIHRoaXMucm9vdEl0ZW0sICdzdWl0ZXMnKTtcbiAgICAgICAgICBpZiAoZmlsZVN1aXRlLnRlc3RzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgZGVmYXVsdERlc2NyaWJlSXRlbSA9IHRoaXMuX2RlZmF1bHREZXNjcmliZUl0ZW0oKTtcbiAgICAgICAgICAgIHZpc2l0U3VpdGUocHJvamVjdFN1aXRlLnByb2plY3QoKSEsIGZpbGVTdWl0ZSwgZGVmYXVsdERlc2NyaWJlSXRlbSwgJ3Rlc3RzJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IGZpbGVJdGVtID0gdGhpcy5fZmlsZUl0ZW0oZmlsZVN1aXRlLmxvY2F0aW9uIS5maWxlLnNwbGl0KHBhdGhTZXBhcmF0b3IpLCB0cnVlKTtcbiAgICAgICAgICB2aXNpdFN1aXRlKHByb2plY3RTdWl0ZS5wcm9qZWN0KCkhLCBmaWxlU3VpdGUsIGZpbGVJdGVtLCAnYWxsJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGxvYWRFcnJvciBvZiBsb2FkRXJyb3JzKSB7XG4gICAgICBpZiAoIWxvYWRFcnJvci5sb2NhdGlvbilcbiAgICAgICAgY29udGludWU7XG4gICAgICBjb25zdCBmaWxlSXRlbSA9IHRoaXMuX2ZpbGVJdGVtKGxvYWRFcnJvci5sb2NhdGlvbi5maWxlLnNwbGl0KHBhdGhTZXBhcmF0b3IpLCB0cnVlKTtcbiAgICAgIGZpbGVJdGVtLmhhc0xvYWRFcnJvcnMgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2FkZENoaWxkKHBhcmVudDogVHJlZUl0ZW0sIGNoaWxkOiBUcmVlSXRlbSkge1xuICAgIHBhcmVudC5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICBjaGlsZC5wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5fdHJlZUl0ZW1CeUlkLnNldChjaGlsZC5pZCwgY2hpbGQpO1xuICB9XG5cbiAgZmlsdGVyVHJlZShmaWx0ZXJUZXh0OiBzdHJpbmcsIHN0YXR1c0ZpbHRlcnM6IE1hcDxzdHJpbmcsIGJvb2xlYW4+LCBydW5uaW5nVGVzdElkczogU2V0PHN0cmluZz4gfCB1bmRlZmluZWQpIHtcbiAgICBjb25zdCB0b2tlbnMgPSBmaWx0ZXJUZXh0LnRyaW0oKS50b0xvd2VyQ2FzZSgpLnNwbGl0KCcgJyk7XG4gICAgY29uc3QgZmlsdGVyc1N0YXR1c2VzID0gWy4uLnN0YXR1c0ZpbHRlcnMudmFsdWVzKCldLnNvbWUoQm9vbGVhbik7XG5cbiAgICBjb25zdCBmaWx0ZXIgPSAodGVzdENhc2U6IFRlc3RDYXNlSXRlbSkgPT4ge1xuICAgICAgY29uc3QgdGl0bGVXaXRoVGFncyA9IFsuLi50ZXN0Q2FzZS50ZXN0c1swXS50aXRsZVBhdGgoKSwgLi4udGVzdENhc2UudGVzdHNbMF0udGFnc10uam9pbignICcpLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAoIXRva2Vucy5ldmVyeSh0b2tlbiA9PiB0aXRsZVdpdGhUYWdzLmluY2x1ZGVzKHRva2VuKSkgJiYgIXRlc3RDYXNlLnRlc3RzLnNvbWUodCA9PiBydW5uaW5nVGVzdElkcz8uaGFzKHQuaWQpKSlcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgdGVzdENhc2UuY2hpbGRyZW4gPSAodGVzdENhc2UuY2hpbGRyZW4gYXMgVGVzdEl0ZW1bXSkuZmlsdGVyKHRlc3QgPT4ge1xuICAgICAgICByZXR1cm4gIWZpbHRlcnNTdGF0dXNlcyB8fCBydW5uaW5nVGVzdElkcz8uaGFzKHRlc3QudGVzdC5pZCkgfHwgc3RhdHVzRmlsdGVycy5nZXQodGVzdC5zdGF0dXMpO1xuICAgICAgfSk7XG4gICAgICB0ZXN0Q2FzZS50ZXN0cyA9ICh0ZXN0Q2FzZS5jaGlsZHJlbiBhcyBUZXN0SXRlbVtdKS5tYXAoYyA9PiBjLnRlc3QpO1xuICAgICAgcmV0dXJuICEhdGVzdENhc2UuY2hpbGRyZW4ubGVuZ3RoO1xuICAgIH07XG5cbiAgICBjb25zdCB2aXNpdCA9ICh0cmVlSXRlbTogR3JvdXBJdGVtKSA9PiB7XG4gICAgICBjb25zdCBuZXdDaGlsZHJlbjogKEdyb3VwSXRlbSB8IFRlc3RDYXNlSXRlbSlbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0cmVlSXRlbS5jaGlsZHJlbikge1xuICAgICAgICBpZiAoY2hpbGQua2luZCA9PT0gJ2Nhc2UnKSB7XG4gICAgICAgICAgaWYgKGZpbHRlcihjaGlsZCkpXG4gICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2aXNpdChjaGlsZCk7XG4gICAgICAgICAgaWYgKGNoaWxkLmNoaWxkcmVuLmxlbmd0aCB8fCBjaGlsZC5oYXNMb2FkRXJyb3JzKVxuICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChjaGlsZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRyZWVJdGVtLmNoaWxkcmVuID0gbmV3Q2hpbGRyZW47XG4gICAgfTtcbiAgICB2aXNpdCh0aGlzLnJvb3RJdGVtKTtcbiAgfVxuXG4gIHByaXZhdGUgX2ZpbGVJdGVtKGZpbGVQYXRoOiBzdHJpbmdbXSwgaXNGaWxlOiBib29sZWFuKTogR3JvdXBJdGVtIHtcbiAgICBpZiAoZmlsZVBhdGgubGVuZ3RoID09PSAwKVxuICAgICAgcmV0dXJuIHRoaXMucm9vdEl0ZW07XG4gICAgY29uc3QgZmlsZU5hbWUgPSBmaWxlUGF0aC5qb2luKHRoaXMucGF0aFNlcGFyYXRvcik7XG4gICAgY29uc3QgZXhpc3RpbmdGaWxlSXRlbSA9IHRoaXMuX3RyZWVJdGVtQnlJZC5nZXQoZmlsZU5hbWUpO1xuICAgIGlmIChleGlzdGluZ0ZpbGVJdGVtKVxuICAgICAgcmV0dXJuIGV4aXN0aW5nRmlsZUl0ZW0gYXMgR3JvdXBJdGVtO1xuICAgIGNvbnN0IHBhcmVudEZpbGVJdGVtID0gdGhpcy5fZmlsZUl0ZW0oZmlsZVBhdGguc2xpY2UoMCwgZmlsZVBhdGgubGVuZ3RoIC0gMSksIGZhbHNlKTtcbiAgICBjb25zdCBmaWxlSXRlbTogR3JvdXBJdGVtID0ge1xuICAgICAga2luZDogJ2dyb3VwJyxcbiAgICAgIHN1YktpbmQ6IGlzRmlsZSA/ICdmaWxlJyA6ICdmb2xkZXInLFxuICAgICAgaWQ6IGZpbGVOYW1lLFxuICAgICAgdGl0bGU6IGZpbGVQYXRoW2ZpbGVQYXRoLmxlbmd0aCAtIDFdLFxuICAgICAgbG9jYXRpb246IHsgZmlsZTogZmlsZU5hbWUsIGxpbmU6IDAsIGNvbHVtbjogMCB9LFxuICAgICAgZHVyYXRpb246IDAsXG4gICAgICBwYXJlbnQ6IHBhcmVudEZpbGVJdGVtLFxuICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgc3RhdHVzOiAnbm9uZScsXG4gICAgICBoYXNMb2FkRXJyb3JzOiBmYWxzZSxcbiAgICB9O1xuICAgIHRoaXMuX2FkZENoaWxkKHBhcmVudEZpbGVJdGVtLCBmaWxlSXRlbSk7XG4gICAgcmV0dXJuIGZpbGVJdGVtO1xuICB9XG5cbiAgcHJpdmF0ZSBfZGVmYXVsdERlc2NyaWJlSXRlbSgpOiBHcm91cEl0ZW0ge1xuICAgIGxldCBkZWZhdWx0RGVzY3JpYmVJdGVtID0gdGhpcy5fdHJlZUl0ZW1CeUlkLmdldCgnPGFub255bW91cz4nKSBhcyBHcm91cEl0ZW07XG4gICAgaWYgKCFkZWZhdWx0RGVzY3JpYmVJdGVtKSB7XG4gICAgICBkZWZhdWx0RGVzY3JpYmVJdGVtID0ge1xuICAgICAgICBraW5kOiAnZ3JvdXAnLFxuICAgICAgICBzdWJLaW5kOiAnZGVzY3JpYmUnLFxuICAgICAgICBpZDogJzxhbm9ueW1vdXM+JyxcbiAgICAgICAgdGl0bGU6ICc8YW5vbnltb3VzPicsXG4gICAgICAgIGxvY2F0aW9uOiB7IGZpbGU6ICcnLCBsaW5lOiAwLCBjb2x1bW46IDAgfSxcbiAgICAgICAgZHVyYXRpb246IDAsXG4gICAgICAgIHBhcmVudDogdGhpcy5yb290SXRlbSxcbiAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgICBzdGF0dXM6ICdub25lJyxcbiAgICAgICAgaGFzTG9hZEVycm9yczogZmFsc2UsXG4gICAgICB9O1xuICAgICAgdGhpcy5fYWRkQ2hpbGQodGhpcy5yb290SXRlbSwgZGVmYXVsdERlc2NyaWJlSXRlbSk7XG4gICAgfVxuICAgIHJldHVybiBkZWZhdWx0RGVzY3JpYmVJdGVtO1xuICB9XG5cbiAgc29ydEFuZFByb3BhZ2F0ZVN0YXR1cygpIHtcbiAgICBzb3J0QW5kUHJvcGFnYXRlU3RhdHVzKHRoaXMucm9vdEl0ZW0pO1xuICB9XG5cbiAgZmxhdHRlbkZvclNpbmdsZVByb2plY3QoKSB7XG4gICAgY29uc3QgdmlzaXQgPSAodHJlZUl0ZW06IFRyZWVJdGVtKSA9PiB7XG4gICAgICBpZiAodHJlZUl0ZW0ua2luZCA9PT0gJ2Nhc2UnICYmIHRyZWVJdGVtLmNoaWxkcmVuLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICB0cmVlSXRlbS5wcm9qZWN0ID0gdHJlZUl0ZW0uY2hpbGRyZW5bMF0ucHJvamVjdDtcbiAgICAgICAgdHJlZUl0ZW0udGVzdCA9IHRyZWVJdGVtLmNoaWxkcmVuWzBdLnRlc3Q7XG4gICAgICAgIHRyZWVJdGVtLmNoaWxkcmVuID0gW107XG4gICAgICAgIHRoaXMuX3RyZWVJdGVtQnlUZXN0SWQuc2V0KHRyZWVJdGVtLnRlc3QuaWQsIHRyZWVJdGVtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyZWVJdGVtLmNoaWxkcmVuLmZvckVhY2godmlzaXQpO1xuICAgICAgfVxuICAgIH07XG4gICAgdmlzaXQodGhpcy5yb290SXRlbSk7XG4gIH1cblxuICBzaG9ydGVuUm9vdCgpIHtcbiAgICBsZXQgc2hvcnRSb290ID0gdGhpcy5yb290SXRlbTtcbiAgICB3aGlsZSAoc2hvcnRSb290LmNoaWxkcmVuLmxlbmd0aCA9PT0gMSAmJiBzaG9ydFJvb3QuY2hpbGRyZW5bMF0ua2luZCA9PT0gJ2dyb3VwJyAmJiBzaG9ydFJvb3QuY2hpbGRyZW5bMF0uc3ViS2luZCA9PT0gJ2ZvbGRlcicpXG4gICAgICBzaG9ydFJvb3QgPSBzaG9ydFJvb3QuY2hpbGRyZW5bMF07XG4gICAgc2hvcnRSb290LmxvY2F0aW9uID0gdGhpcy5yb290SXRlbS5sb2NhdGlvbjtcbiAgICB0aGlzLnJvb3RJdGVtID0gc2hvcnRSb290O1xuICB9XG5cbiAgdGVzdElkcygpOiBTZXQ8c3RyaW5nPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgdmlzaXQgPSAodHJlZUl0ZW06IFRyZWVJdGVtKSA9PiB7XG4gICAgICBpZiAodHJlZUl0ZW0ua2luZCA9PT0gJ2Nhc2UnKVxuICAgICAgICB0cmVlSXRlbS50ZXN0cy5mb3JFYWNoKHQgPT4gcmVzdWx0LmFkZCh0LmlkKSk7XG4gICAgICB0cmVlSXRlbS5jaGlsZHJlbi5mb3JFYWNoKHZpc2l0KTtcbiAgICB9O1xuICAgIHZpc2l0KHRoaXMucm9vdEl0ZW0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmaWxlTmFtZXMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IHZpc2l0ID0gKHRyZWVJdGVtOiBUcmVlSXRlbSkgPT4ge1xuICAgICAgaWYgKHRyZWVJdGVtLmtpbmQgPT09ICdncm91cCcgJiYgdHJlZUl0ZW0uc3ViS2luZCA9PT0gJ2ZpbGUnKVxuICAgICAgICByZXN1bHQuYWRkKHRyZWVJdGVtLmlkKTtcbiAgICAgIGVsc2VcbiAgICAgICAgdHJlZUl0ZW0uY2hpbGRyZW4uZm9yRWFjaCh2aXNpdCk7XG4gICAgfTtcbiAgICB2aXNpdCh0aGlzLnJvb3RJdGVtKTtcbiAgICByZXR1cm4gWy4uLnJlc3VsdF07XG4gIH1cblxuICBmbGF0VHJlZUl0ZW1zKCk6IFRyZWVJdGVtW10ge1xuICAgIGNvbnN0IHJlc3VsdDogVHJlZUl0ZW1bXSA9IFtdO1xuICAgIGNvbnN0IHZpc2l0ID0gKHRyZWVJdGVtOiBUcmVlSXRlbSkgPT4ge1xuICAgICAgcmVzdWx0LnB1c2godHJlZUl0ZW0pO1xuICAgICAgdHJlZUl0ZW0uY2hpbGRyZW4uZm9yRWFjaCh2aXNpdCk7XG4gICAgfTtcbiAgICB2aXNpdCh0aGlzLnJvb3RJdGVtKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdHJlZUl0ZW1CeUlkKGlkOiBzdHJpbmcpOiBUcmVlSXRlbSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3RyZWVJdGVtQnlJZC5nZXQoaWQpO1xuICB9XG5cbiAgY29sbGVjdFRlc3RJZHModHJlZUl0ZW0/OiBUcmVlSXRlbSk6IFNldDxzdHJpbmc+IHtcbiAgICByZXR1cm4gdHJlZUl0ZW0gPyBjb2xsZWN0VGVzdElkcyh0cmVlSXRlbSkgOiBuZXcgU2V0KCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNvcnRBbmRQcm9wYWdhdGVTdGF0dXModHJlZUl0ZW06IFRyZWVJdGVtKSB7XG4gIGZvciAoY29uc3QgY2hpbGQgb2YgdHJlZUl0ZW0uY2hpbGRyZW4pXG4gICAgc29ydEFuZFByb3BhZ2F0ZVN0YXR1cyhjaGlsZCk7XG5cbiAgaWYgKHRyZWVJdGVtLmtpbmQgPT09ICdncm91cCcpIHtcbiAgICB0cmVlSXRlbS5jaGlsZHJlbi5zb3J0KChhLCBiKSA9PiB7XG4gICAgICBjb25zdCBmYyA9IGEubG9jYXRpb24uZmlsZS5sb2NhbGVDb21wYXJlKGIubG9jYXRpb24uZmlsZSk7XG4gICAgICByZXR1cm4gZmMgfHwgYS5sb2NhdGlvbi5saW5lIC0gYi5sb2NhdGlvbi5saW5lO1xuICAgIH0pO1xuICB9XG5cbiAgbGV0IGFsbFBhc3NlZCA9IHRyZWVJdGVtLmNoaWxkcmVuLmxlbmd0aCA+IDA7XG4gIGxldCBhbGxTa2lwcGVkID0gdHJlZUl0ZW0uY2hpbGRyZW4ubGVuZ3RoID4gMDtcbiAgbGV0IGhhc0ZhaWxlZCA9IGZhbHNlO1xuICBsZXQgaGFzUnVubmluZyA9IGZhbHNlO1xuICBsZXQgaGFzU2NoZWR1bGVkID0gZmFsc2U7XG5cbiAgZm9yIChjb25zdCBjaGlsZCBvZiB0cmVlSXRlbS5jaGlsZHJlbikge1xuICAgIGFsbFNraXBwZWQgPSBhbGxTa2lwcGVkICYmIGNoaWxkLnN0YXR1cyA9PT0gJ3NraXBwZWQnO1xuICAgIGFsbFBhc3NlZCA9IGFsbFBhc3NlZCAmJiAoY2hpbGQuc3RhdHVzID09PSAncGFzc2VkJyB8fCBjaGlsZC5zdGF0dXMgPT09ICdza2lwcGVkJyk7XG4gICAgaGFzRmFpbGVkID0gaGFzRmFpbGVkIHx8IGNoaWxkLnN0YXR1cyA9PT0gJ2ZhaWxlZCc7XG4gICAgaGFzUnVubmluZyA9IGhhc1J1bm5pbmcgfHwgY2hpbGQuc3RhdHVzID09PSAncnVubmluZyc7XG4gICAgaGFzU2NoZWR1bGVkID0gaGFzU2NoZWR1bGVkIHx8IGNoaWxkLnN0YXR1cyA9PT0gJ3NjaGVkdWxlZCc7XG4gIH1cblxuICBpZiAoaGFzUnVubmluZylcbiAgICB0cmVlSXRlbS5zdGF0dXMgPSAncnVubmluZyc7XG4gIGVsc2UgaWYgKGhhc1NjaGVkdWxlZClcbiAgICB0cmVlSXRlbS5zdGF0dXMgPSAnc2NoZWR1bGVkJztcbiAgZWxzZSBpZiAoaGFzRmFpbGVkKVxuICAgIHRyZWVJdGVtLnN0YXR1cyA9ICdmYWlsZWQnO1xuICBlbHNlIGlmIChhbGxTa2lwcGVkKVxuICAgIHRyZWVJdGVtLnN0YXR1cyA9ICdza2lwcGVkJztcbiAgZWxzZSBpZiAoYWxsUGFzc2VkKVxuICAgIHRyZWVJdGVtLnN0YXR1cyA9ICdwYXNzZWQnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29sbGVjdFRlc3RJZHModHJlZUl0ZW06IFRyZWVJdGVtKTogU2V0PHN0cmluZz4ge1xuICBjb25zdCB0ZXN0SWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGNvbnN0IHZpc2l0ID0gKHRyZWVJdGVtOiBUcmVlSXRlbSkgPT4ge1xuICAgIGlmICh0cmVlSXRlbS5raW5kID09PSAnY2FzZScpXG4gICAgICB0cmVlSXRlbS50ZXN0cy5tYXAodCA9PiB0LmlkKS5mb3JFYWNoKGlkID0+IHRlc3RJZHMuYWRkKGlkKSk7XG4gICAgZWxzZSBpZiAodHJlZUl0ZW0ua2luZCA9PT0gJ3Rlc3QnKVxuICAgICAgdGVzdElkcy5hZGQodHJlZUl0ZW0uaWQpO1xuICAgIGVsc2VcbiAgICAgIHRyZWVJdGVtLmNoaWxkcmVuPy5mb3JFYWNoKHZpc2l0KTtcbiAgfTtcbiAgdmlzaXQodHJlZUl0ZW0pO1xuICByZXR1cm4gdGVzdElkcztcbn1cblxuZXhwb3J0IGNvbnN0IHN0YXR1c0V4ID0gU3ltYm9sKCdzdGF0dXNFeCcpO1xuIiwiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgVGVsZVJlcG9ydGVyUmVjZWl2ZXIsIFRlbGVTdWl0ZSB9IGZyb20gJy4vdGVsZVJlY2VpdmVyJztcbmltcG9ydCB7IHN0YXR1c0V4IH0gZnJvbSAnLi90ZXN0VHJlZSc7XG5cbmltcG9ydCB0eXBlICogYXMgcmVwb3J0ZXJUeXBlcyBmcm9tICcuLi8uLi90eXBlcy90ZXN0UmVwb3J0ZXInO1xuaW1wb3J0IHR5cGUgeyBSZXBvcnRlclYyIH0gZnJvbSAnLi4vcmVwb3J0ZXJzL3JlcG9ydGVyVjInO1xuXG5leHBvcnQgdHlwZSBUZWxlU3VpdGVVcGRhdGVyUHJvZ3Jlc3MgPSB7XG4gIHRvdGFsOiBudW1iZXI7XG4gIHBhc3NlZDogbnVtYmVyO1xuICBmYWlsZWQ6IG51bWJlcjtcbiAgc2tpcHBlZDogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgVGVsZVN1aXRlVXBkYXRlclRlc3RNb2RlbCA9IHtcbiAgY29uZmlnOiByZXBvcnRlclR5cGVzLkZ1bGxDb25maWc7XG4gIHJvb3RTdWl0ZTogcmVwb3J0ZXJUeXBlcy5TdWl0ZTtcbiAgbG9hZEVycm9yczogcmVwb3J0ZXJUeXBlcy5UZXN0RXJyb3JbXTtcbiAgcHJvZ3Jlc3M6IFRlbGVTdWl0ZVVwZGF0ZXJQcm9ncmVzcztcbn07XG5cbmV4cG9ydCB0eXBlIFRlbGVTdWl0ZVVwZGF0ZXJPcHRpb25zID0ge1xuICBvblVwZGF0ZTogKGZvcmNlPzogYm9vbGVhbikgPT4gdm9pZCxcbiAgb25FcnJvcj86IChlcnJvcjogcmVwb3J0ZXJUeXBlcy5UZXN0RXJyb3IpID0+IHZvaWQ7XG4gIHBhdGhTZXBhcmF0b3I6IHN0cmluZztcbn07XG5cbmV4cG9ydCBjbGFzcyBUZWxlU3VpdGVVcGRhdGVyIHtcbiAgcm9vdFN1aXRlOiBUZWxlU3VpdGUgfCB1bmRlZmluZWQ7XG4gIGNvbmZpZzogcmVwb3J0ZXJUeXBlcy5GdWxsQ29uZmlnIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBsb2FkRXJyb3JzOiByZXBvcnRlclR5cGVzLlRlc3RFcnJvcltdID0gW107XG4gIHJlYWRvbmx5IHByb2dyZXNzOiBUZWxlU3VpdGVVcGRhdGVyUHJvZ3Jlc3MgPSB7XG4gICAgdG90YWw6IDAsXG4gICAgcGFzc2VkOiAwLFxuICAgIGZhaWxlZDogMCxcbiAgICBza2lwcGVkOiAwLFxuICB9O1xuXG4gIHByaXZhdGUgX3JlY2VpdmVyOiBUZWxlUmVwb3J0ZXJSZWNlaXZlcjtcbiAgcHJpdmF0ZSBfbGFzdFJ1blJlY2VpdmVyOiBUZWxlUmVwb3J0ZXJSZWNlaXZlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfbGFzdFJ1blRlc3RDb3VudCA9IDA7XG4gIHByaXZhdGUgX29wdGlvbnM6IFRlbGVTdWl0ZVVwZGF0ZXJPcHRpb25zO1xuICBwcml2YXRlIF90ZXN0UmVzdWx0c1NuYXBzaG90OiBNYXA8c3RyaW5nLCByZXBvcnRlclR5cGVzLlRlc3RSZXN1bHRbXT4gfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogVGVsZVN1aXRlVXBkYXRlck9wdGlvbnMpIHtcbiAgICB0aGlzLl9yZWNlaXZlciA9IG5ldyBUZWxlUmVwb3J0ZXJSZWNlaXZlcih0aGlzLl9jcmVhdGVSZXBvcnRlcigpLCB7XG4gICAgICBtZXJnZVByb2plY3RzOiB0cnVlLFxuICAgICAgbWVyZ2VUZXN0Q2FzZXM6IHRydWUsXG4gICAgICByZXNvbHZlUGF0aDogKHJvb3REaXIsIHJlbGF0aXZlUGF0aCkgPT4gcm9vdERpciArIG9wdGlvbnMucGF0aFNlcGFyYXRvciArIHJlbGF0aXZlUGF0aCxcbiAgICAgIGNsZWFyUHJldmlvdXNSZXN1bHRzV2hlblRlc3RCZWdpbnM6IHRydWUsXG4gICAgfSk7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICBwcml2YXRlIF9jcmVhdGVSZXBvcnRlcigpOiBSZXBvcnRlclYyIHtcbiAgICByZXR1cm4ge1xuICAgICAgdmVyc2lvbjogKCkgPT4gJ3YyJyxcblxuICAgICAgb25Db25maWd1cmU6IChjOiByZXBvcnRlclR5cGVzLkZ1bGxDb25maWcpID0+IHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjO1xuICAgICAgICAvLyBUZWxlUmVwb3J0UmVjZWl2ZXIgaXMgbWVyZ2luZyBldmVyeXRoaW5nIGludG8gYSBzaW5nbGUgc3VpdGUsIHNvIHdoZW4gd2VcbiAgICAgICAgLy8gcnVuIG9uZSB0ZXN0LCB3ZSBzdGlsbCBnZXQgbWFueSB0ZXN0cyB2aWEgcm9vdFN1aXRlLmFsbFRlc3RzKCkubGVuZ3RoLlxuICAgICAgICAvLyBUbyB3b3JrIGFyb3VuZCB0aGF0LCBoYXZlIGEgZGVkaWNhdGVkIHBlci1ydW4gcmVjZWl2ZXIgdGhhdCB3aWxsIG9ubHkgaGF2ZVxuICAgICAgICAvLyBzdWl0ZSBmb3IgYSBzaW5nbGUgdGVzdCBydW4sIGFuZCBoZW5jZSB3aWxsIGhhdmUgY29ycmVjdCB0b3RhbC5cbiAgICAgICAgdGhpcy5fbGFzdFJ1blJlY2VpdmVyID0gbmV3IFRlbGVSZXBvcnRlclJlY2VpdmVyKHtcbiAgICAgICAgICB2ZXJzaW9uOiAoKSA9PiAndjInLFxuICAgICAgICAgIG9uQmVnaW46IChzdWl0ZTogcmVwb3J0ZXJUeXBlcy5TdWl0ZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fbGFzdFJ1blRlc3RDb3VudCA9IHN1aXRlLmFsbFRlc3RzKCkubGVuZ3RoO1xuICAgICAgICAgICAgdGhpcy5fbGFzdFJ1blJlY2VpdmVyID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwge1xuICAgICAgICAgIG1lcmdlUHJvamVjdHM6IHRydWUsXG4gICAgICAgICAgbWVyZ2VUZXN0Q2FzZXM6IGZhbHNlLFxuICAgICAgICAgIHJlc29sdmVQYXRoOiAocm9vdERpciwgcmVsYXRpdmVQYXRoKSA9PiByb290RGlyICsgdGhpcy5fb3B0aW9ucy5wYXRoU2VwYXJhdG9yICsgcmVsYXRpdmVQYXRoLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG5cbiAgICAgIG9uQmVnaW46IChzdWl0ZTogcmVwb3J0ZXJUeXBlcy5TdWl0ZSkgPT4ge1xuICAgICAgICBpZiAoIXRoaXMucm9vdFN1aXRlKVxuICAgICAgICAgIHRoaXMucm9vdFN1aXRlID0gc3VpdGUgYXMgVGVsZVN1aXRlO1xuICAgICAgICAvLyBBcyBzb29uIGFzIG5ldyB0ZXN0IHRyZWUgaXMgYnVpbHQgYWRkIHByZXZpb3VzIHJlc3VsdHMsIGJlZm9yZSBjYWxsaW5nIG9uVXBkYXRlXG4gICAgICAgIC8vIHRvIGF2b2lkIGZsYXNoaW5nIGVtcHR5IHJlc3VsdHMgaW4gdGhlIFVJLlxuICAgICAgICBpZiAodGhpcy5fdGVzdFJlc3VsdHNTbmFwc2hvdCkge1xuICAgICAgICAgIGZvciAoY29uc3QgdGVzdCBvZiB0aGlzLnJvb3RTdWl0ZS5hbGxUZXN0cygpKVxuICAgICAgICAgICAgdGVzdC5yZXN1bHRzID0gdGhpcy5fdGVzdFJlc3VsdHNTbmFwc2hvdD8uZ2V0KHRlc3QuaWQpIHx8IHRlc3QucmVzdWx0cztcbiAgICAgICAgICB0aGlzLl90ZXN0UmVzdWx0c1NuYXBzaG90ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJvZ3Jlc3MudG90YWwgPSB0aGlzLl9sYXN0UnVuVGVzdENvdW50O1xuICAgICAgICB0aGlzLnByb2dyZXNzLnBhc3NlZCA9IDA7XG4gICAgICAgIHRoaXMucHJvZ3Jlc3MuZmFpbGVkID0gMDtcbiAgICAgICAgdGhpcy5wcm9ncmVzcy5za2lwcGVkID0gMDtcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5vblVwZGF0ZSh0cnVlKTtcbiAgICAgIH0sXG5cbiAgICAgIG9uRW5kOiAoKSA9PiB7XG4gICAgICAgIHRoaXMuX29wdGlvbnMub25VcGRhdGUodHJ1ZSk7XG4gICAgICB9LFxuXG4gICAgICBvblRlc3RCZWdpbjogKHRlc3Q6IHJlcG9ydGVyVHlwZXMuVGVzdENhc2UsIHRlc3RSZXN1bHQ6IHJlcG9ydGVyVHlwZXMuVGVzdFJlc3VsdCkgPT4ge1xuICAgICAgICAodGVzdFJlc3VsdCBhcyBhbnkpW3N0YXR1c0V4XSA9ICdydW5uaW5nJztcbiAgICAgICAgdGhpcy5fb3B0aW9ucy5vblVwZGF0ZSgpO1xuICAgICAgfSxcblxuICAgICAgb25UZXN0RW5kOiAodGVzdDogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSwgdGVzdFJlc3VsdDogcmVwb3J0ZXJUeXBlcy5UZXN0UmVzdWx0KSA9PiB7XG4gICAgICAgIGlmICh0ZXN0Lm91dGNvbWUoKSA9PT0gJ3NraXBwZWQnKVxuICAgICAgICAgICsrdGhpcy5wcm9ncmVzcy5za2lwcGVkO1xuICAgICAgICBlbHNlIGlmICh0ZXN0Lm91dGNvbWUoKSA9PT0gJ3VuZXhwZWN0ZWQnKVxuICAgICAgICAgICsrdGhpcy5wcm9ncmVzcy5mYWlsZWQ7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICArK3RoaXMucHJvZ3Jlc3MucGFzc2VkO1xuICAgICAgICAodGVzdFJlc3VsdCBhcyBhbnkpW3N0YXR1c0V4XSA9IHRlc3RSZXN1bHQuc3RhdHVzO1xuICAgICAgICB0aGlzLl9vcHRpb25zLm9uVXBkYXRlKCk7XG4gICAgICB9LFxuXG4gICAgICBvbkVycm9yOiAoZXJyb3I6IHJlcG9ydGVyVHlwZXMuVGVzdEVycm9yKSA9PiB0aGlzLl9oYW5kbGVPbkVycm9yKGVycm9yKSxcblxuICAgICAgcHJpbnRzVG9TdGRpbzogKCkgPT4gZmFsc2UsXG4gICAgfTtcbiAgfVxuXG4gIHByb2Nlc3NHbG9iYWxSZXBvcnQocmVwb3J0OiBhbnlbXSkge1xuICAgIGNvbnN0IHJlY2VpdmVyID0gbmV3IFRlbGVSZXBvcnRlclJlY2VpdmVyKHtcbiAgICAgIHZlcnNpb246ICgpID0+ICd2MicsXG4gICAgICBvbkNvbmZpZ3VyZTogKGM6IHJlcG9ydGVyVHlwZXMuRnVsbENvbmZpZykgPT4ge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGM7XG4gICAgICB9LFxuICAgICAgb25FcnJvcjogKGVycm9yOiByZXBvcnRlclR5cGVzLlRlc3RFcnJvcikgPT4gdGhpcy5faGFuZGxlT25FcnJvcihlcnJvcilcbiAgICB9KTtcbiAgICBmb3IgKGNvbnN0IG1lc3NhZ2Ugb2YgcmVwb3J0KVxuICAgICAgdm9pZCByZWNlaXZlci5kaXNwYXRjaChtZXNzYWdlKTtcbiAgfVxuXG4gIHByb2Nlc3NMaXN0UmVwb3J0KHJlcG9ydDogYW55W10pIHtcbiAgICAvLyBTYXZlIHRlc3QgcmVzdWx0cyBhbmQgcmVzZXQgYWxsIHByb2plY3RzLCB0aGUgcmVzdWx0cyB3aWxsIGJlIHJlc3RvcmVkIGFmdGVyXG4gICAgLy8gbmV3IHByb2plY3Qgc3RydWN0dXJlIGlzIGJ1aWx0LlxuICAgIGNvbnN0IHRlc3RzID0gdGhpcy5yb290U3VpdGU/LmFsbFRlc3RzKCkgfHwgW107XG4gICAgdGhpcy5fdGVzdFJlc3VsdHNTbmFwc2hvdCA9IG5ldyBNYXAodGVzdHMubWFwKHRlc3QgPT4gW3Rlc3QuaWQsIHRlc3QucmVzdWx0c10pKTtcbiAgICB0aGlzLl9yZWNlaXZlci5yZXNldCgpO1xuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiByZXBvcnQpXG4gICAgICB2b2lkIHRoaXMuX3JlY2VpdmVyLmRpc3BhdGNoKG1lc3NhZ2UpO1xuICB9XG5cbiAgcHJvY2Vzc1Rlc3RSZXBvcnRFdmVudChtZXNzYWdlOiBhbnkpIHtcbiAgICAvLyBUaGUgb3JkZXIgb2YgcmVjZWl2ZXIgZGlzcGF0Y2hlcyBtYXR0ZXJzIGhlcmUsIHdlIHdhbnQgdG8gYXNzaWduIGBsYXN0UnVuVGVzdENvdW50YFxuICAgIC8vIGJlZm9yZSB3ZSB1c2UgaXQuXG4gICAgdGhpcy5fbGFzdFJ1blJlY2VpdmVyPy5kaXNwYXRjaChtZXNzYWdlKT8uY2F0Y2goKCkgPT4geyB9KTtcbiAgICB0aGlzLl9yZWNlaXZlci5kaXNwYXRjaChtZXNzYWdlKT8uY2F0Y2goKCkgPT4geyB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2hhbmRsZU9uRXJyb3IoZXJyb3I6IHJlcG9ydGVyVHlwZXMuVGVzdEVycm9yKSB7XG4gICAgdGhpcy5sb2FkRXJyb3JzLnB1c2goZXJyb3IpO1xuICAgIHRoaXMuX29wdGlvbnMub25FcnJvcj8uKGVycm9yKTtcbiAgICB0aGlzLl9vcHRpb25zLm9uVXBkYXRlKCk7XG4gIH1cblxuICBhc01vZGVsKCk6IFRlbGVTdWl0ZVVwZGF0ZXJUZXN0TW9kZWwge1xuICAgIHJldHVybiB7XG4gICAgICByb290U3VpdGU6IHRoaXMucm9vdFN1aXRlIHx8IG5ldyBUZWxlU3VpdGUoJycsICdyb290JyksXG4gICAgICBjb25maWc6IHRoaXMuY29uZmlnISxcbiAgICAgIGxvYWRFcnJvcnM6IHRoaXMubG9hZEVycm9ycyxcbiAgICAgIHByb2dyZXNzOiB0aGlzLnByb2dyZXNzLFxuICAgIH07XG4gIH1cbn1cbiIsIi8qXG4gIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuXG4gIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG4gIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCAnLi94dGVybVdyYXBwZXIuY3NzJztcbmltcG9ydCB0eXBlIHsgSVRoZW1lLCBUZXJtaW5hbCB9IGZyb20gJ0B4dGVybS94dGVybSc7XG5pbXBvcnQgdHlwZSB7IEZpdEFkZG9uIH0gZnJvbSAnQHh0ZXJtL2FkZG9uLWZpdCc7XG5pbXBvcnQgdHlwZSB7IFh0ZXJtTW9kdWxlIH0gZnJvbSAnLi94dGVybU1vZHVsZSc7XG5pbXBvcnQgeyBjdXJyZW50VGhlbWUsIGFkZFRoZW1lTGlzdGVuZXIsIHJlbW92ZVRoZW1lTGlzdGVuZXIgfSBmcm9tICcuLi90aGVtZSc7XG5pbXBvcnQgeyB1c2VNZWFzdXJlIH0gZnJvbSAnLi4vdWlVdGlscyc7XG5cbmV4cG9ydCB0eXBlIFh0ZXJtRGF0YVNvdXJjZSA9IHtcbiAgcGVuZGluZzogKHN0cmluZyB8IFVpbnQ4QXJyYXkpW107XG4gIGNsZWFyOiAoKSA9PiB2b2lkLFxuICB3cml0ZTogKGRhdGE6IHN0cmluZyB8IFVpbnQ4QXJyYXkpID0+IHZvaWQ7XG4gIHJlc2l6ZTogKGNvbHM6IG51bWJlciwgcm93czogbnVtYmVyKSA9PiB2b2lkO1xufTtcblxuZXhwb3J0IGNvbnN0IFh0ZXJtV3JhcHBlcjogUmVhY3QuRkM8eyBzb3VyY2U6IFh0ZXJtRGF0YVNvdXJjZSB9PiA9ICh7XG4gIHNvdXJjZSxcbn0pID0+IHtcbiAgY29uc3QgW21lYXN1cmUsIHh0ZXJtRWxlbWVudF0gPSB1c2VNZWFzdXJlPEhUTUxEaXZFbGVtZW50PigpO1xuICBjb25zdCBbdGhlbWUsIHNldFRoZW1lXSA9IFJlYWN0LnVzZVN0YXRlKGN1cnJlbnRUaGVtZSgpKTtcbiAgY29uc3QgW21vZHVsZVByb21pc2VdID0gUmVhY3QudXNlU3RhdGU8UHJvbWlzZTxYdGVybU1vZHVsZT4+KGltcG9ydCgnLi94dGVybU1vZHVsZScpLnRoZW4obSA9PiBtLmRlZmF1bHQpKTtcbiAgY29uc3QgdGVybWluYWwgPSBSZWFjdC51c2VSZWY8eyB0ZXJtaW5hbDogVGVybWluYWwsIGZpdEFkZG9uOiBGaXRBZGRvbiB9IHwgbnVsbD4obnVsbCk7XG5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBhZGRUaGVtZUxpc3RlbmVyKHNldFRoZW1lKTtcbiAgICByZXR1cm4gKCkgPT4gcmVtb3ZlVGhlbWVMaXN0ZW5lcihzZXRUaGVtZSk7XG4gIH0sIFtdKTtcblxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IG9sZFNvdXJjZVdyaXRlID0gc291cmNlLndyaXRlO1xuICAgIGNvbnN0IG9sZFNvdXJjZUNsZWFyID0gc291cmNlLmNsZWFyO1xuXG4gICAgKGFzeW5jICgpID0+IHtcbiAgICAgIC8vIEFsd2F5cyBsb2FkIHRoZSBtb2R1bGUgZmlyc3QuXG4gICAgICBjb25zdCB7IFRlcm1pbmFsLCBGaXRBZGRvbiB9ID0gYXdhaXQgbW9kdWxlUHJvbWlzZTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB4dGVybUVsZW1lbnQuY3VycmVudDtcbiAgICAgIGlmICghZWxlbWVudClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBjb25zdCB0ZXJtaW5hbFRoZW1lID0gdGhlbWUgPT09ICdkYXJrLW1vZGUnID8gZGFya1RoZW1lIDogbGlnaHRUaGVtZTtcbiAgICAgIGlmICh0ZXJtaW5hbC5jdXJyZW50ICYmIHRlcm1pbmFsLmN1cnJlbnQudGVybWluYWwub3B0aW9ucy50aGVtZSA9PT0gdGVybWluYWxUaGVtZSlcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICBpZiAodGVybWluYWwuY3VycmVudClcbiAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9ICcnO1xuXG4gICAgICBjb25zdCBuZXdUZXJtaW5hbCA9IG5ldyBUZXJtaW5hbCh7XG4gICAgICAgIGNvbnZlcnRFb2w6IHRydWUsXG4gICAgICAgIGZvbnRTaXplOiAxMyxcbiAgICAgICAgc2Nyb2xsYmFjazogMTAwMDAsXG4gICAgICAgIGZvbnRGYW1pbHk6ICdtb25vc3BhY2UnLFxuICAgICAgICB0aGVtZTogdGVybWluYWxUaGVtZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXRBZGRvbiA9IG5ldyBGaXRBZGRvbigpO1xuICAgICAgbmV3VGVybWluYWwubG9hZEFkZG9uKGZpdEFkZG9uKTtcbiAgICAgIGZvciAoY29uc3QgcCBvZiBzb3VyY2UucGVuZGluZylcbiAgICAgICAgbmV3VGVybWluYWwud3JpdGUocCk7XG4gICAgICBzb3VyY2Uud3JpdGUgPSAoZGF0YSA9PiB7XG4gICAgICAgIHNvdXJjZS5wZW5kaW5nLnB1c2goZGF0YSk7XG4gICAgICAgIG5ld1Rlcm1pbmFsLndyaXRlKGRhdGEpO1xuICAgICAgfSk7XG4gICAgICBzb3VyY2UuY2xlYXIgPSAoKSA9PiB7XG4gICAgICAgIHNvdXJjZS5wZW5kaW5nID0gW107XG4gICAgICAgIG5ld1Rlcm1pbmFsLmNsZWFyKCk7XG4gICAgICB9O1xuICAgICAgbmV3VGVybWluYWwub3BlbihlbGVtZW50KTtcbiAgICAgIGZpdEFkZG9uLmZpdCgpO1xuICAgICAgdGVybWluYWwuY3VycmVudCA9IHsgdGVybWluYWw6IG5ld1Rlcm1pbmFsLCBmaXRBZGRvbiB9O1xuICAgIH0pKCk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHNvdXJjZS5jbGVhciA9IG9sZFNvdXJjZUNsZWFyO1xuICAgICAgc291cmNlLndyaXRlID0gb2xkU291cmNlV3JpdGU7XG4gICAgfTtcbiAgfSwgW21vZHVsZVByb21pc2UsIHRlcm1pbmFsLCB4dGVybUVsZW1lbnQsIHNvdXJjZSwgdGhlbWVdKTtcblxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIEZpdCByZWFkcyBkYXRhIGZyb20gdGhlIHRlcm1pbmFsIGl0c2VsZiwgd2hpY2ggdXBkYXRlcyBsYXppbHksIHByb2JhYmx5IG9uIHNvbWUgdGltZXJcbiAgICAvLyBvciBtdXRhdGlvbiBvYnNlcnZlci4gV29yayBhcm91bmQgaXQuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAoIXRlcm1pbmFsLmN1cnJlbnQpXG4gICAgICAgIHJldHVybjtcbiAgICAgIHRlcm1pbmFsLmN1cnJlbnQuZml0QWRkb24uZml0KCk7XG4gICAgICBzb3VyY2UucmVzaXplKHRlcm1pbmFsLmN1cnJlbnQudGVybWluYWwuY29scywgdGVybWluYWwuY3VycmVudC50ZXJtaW5hbC5yb3dzKTtcbiAgICB9LCAyNTApO1xuICB9LCBbbWVhc3VyZSwgc291cmNlXSk7XG5cbiAgcmV0dXJuIDxkaXYgZGF0YS10ZXN0aWQ9J291dHB1dCcgY2xhc3NOYW1lPSd4dGVybS13cmFwcGVyJyBzdHlsZT17eyBmbGV4OiAnYXV0bycgfX0gcmVmPXt4dGVybUVsZW1lbnR9PjwvZGl2Pjtcbn07XG5cbmNvbnN0IGxpZ2h0VGhlbWU6IElUaGVtZSA9IHtcbiAgZm9yZWdyb3VuZDogJyMzODNhNDInLFxuICBiYWNrZ3JvdW5kOiAnI2ZhZmFmYScsXG4gIGN1cnNvcjogJyMzODNhNDInLFxuICBibGFjazogJyMwMDAwMDAnLFxuICByZWQ6ICcjZTQ1NjQ5JyxcbiAgZ3JlZW46ICcjNTBhMTRmJyxcbiAgeWVsbG93OiAnI2MxODQwMScsXG4gIGJsdWU6ICcjNDA3OGYyJyxcbiAgbWFnZW50YTogJyNhNjI2YTQnLFxuICBjeWFuOiAnIzAxODRiYycsXG4gIHdoaXRlOiAnI2EwYTBhMCcsXG4gIGJyaWdodEJsYWNrOiAnIzAwMDAwMCcsXG4gIGJyaWdodFJlZDogJyNlMDZjNzUnLFxuICBicmlnaHRHcmVlbjogJyM5OGMzNzknLFxuICBicmlnaHRZZWxsb3c6ICcjZDE5YTY2JyxcbiAgYnJpZ2h0Qmx1ZTogJyM0MDc4ZjInLFxuICBicmlnaHRNYWdlbnRhOiAnI2E2MjZhNCcsXG4gIGJyaWdodEN5YW46ICcjMDE4NGJjJyxcbiAgYnJpZ2h0V2hpdGU6ICcjMzgzYTQyJyxcbiAgc2VsZWN0aW9uQmFja2dyb3VuZDogJyNkN2Q3ZDcnLFxuICBzZWxlY3Rpb25Gb3JlZ3JvdW5kOiAnIzM4M2E0MicsXG59O1xuXG5jb25zdCBkYXJrVGhlbWU6IElUaGVtZSA9IHtcbiAgZm9yZWdyb3VuZDogJyNmOGY4ZjInLFxuICBiYWNrZ3JvdW5kOiAnIzFlMWUxZScsXG4gIGN1cnNvcjogJyNmOGY4ZjAnLFxuICBibGFjazogJyMwMDAwMDAnLFxuICByZWQ6ICcjZmY1NTU1JyxcbiAgZ3JlZW46ICcjNTBmYTdiJyxcbiAgeWVsbG93OiAnI2YxZmE4YycsXG4gIGJsdWU6ICcjYmQ5M2Y5JyxcbiAgbWFnZW50YTogJyNmZjc5YzYnLFxuICBjeWFuOiAnIzhiZTlmZCcsXG4gIHdoaXRlOiAnI2JmYmZiZicsXG4gIGJyaWdodEJsYWNrOiAnIzRkNGQ0ZCcsXG4gIGJyaWdodFJlZDogJyNmZjZlNmUnLFxuICBicmlnaHRHcmVlbjogJyM2OWZmOTQnLFxuICBicmlnaHRZZWxsb3c6ICcjZmZmZmE1JyxcbiAgYnJpZ2h0Qmx1ZTogJyNkNmFjZmYnLFxuICBicmlnaHRNYWdlbnRhOiAnI2ZmOTJkZicsXG4gIGJyaWdodEN5YW46ICcjYTRmZmZmJyxcbiAgYnJpZ2h0V2hpdGU6ICcjZTZlNmU2JyxcbiAgc2VsZWN0aW9uQmFja2dyb3VuZDogJyM0NDQ3NWEnLFxuICBzZWxlY3Rpb25Gb3JlZ3JvdW5kOiAnI2Y4ZjhmMicsXG59O1xuIiwiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0ICdAd2ViL2NvbW1vbi5jc3MnO1xuaW1wb3J0IHsgRXhwYW5kYWJsZSB9IGZyb20gJ0B3ZWIvY29tcG9uZW50cy9leHBhbmRhYmxlJztcbmltcG9ydCAnQHdlYi90aGlyZF9wYXJ0eS92c2NvZGUvY29kaWNvbi5jc3MnO1xuaW1wb3J0IHsgc2V0dGluZ3MgfSBmcm9tICdAd2ViL3VpVXRpbHMnO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCAnLi91aU1vZGVGaWx0ZXJzVmlldy5jc3MnO1xuaW1wb3J0IHR5cGUgeyBUZWxlU3VpdGVVcGRhdGVyVGVzdE1vZGVsIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3RlbGVTdWl0ZVVwZGF0ZXInO1xuXG5leHBvcnQgY29uc3QgRmlsdGVyc1ZpZXc6IFJlYWN0LkZDPHtcbiAgZmlsdGVyVGV4dDogc3RyaW5nO1xuICBzZXRGaWx0ZXJUZXh0OiAodGV4dDogc3RyaW5nKSA9PiB2b2lkO1xuICBzdGF0dXNGaWx0ZXJzOiBNYXA8c3RyaW5nLCBib29sZWFuPjtcbiAgc2V0U3RhdHVzRmlsdGVyczogKGZpbHRlcnM6IE1hcDxzdHJpbmcsIGJvb2xlYW4+KSA9PiB2b2lkO1xuICBwcm9qZWN0RmlsdGVyczogTWFwPHN0cmluZywgYm9vbGVhbj47XG4gIHNldFByb2plY3RGaWx0ZXJzOiAoZmlsdGVyczogTWFwPHN0cmluZywgYm9vbGVhbj4pID0+IHZvaWQ7XG4gIHRlc3RNb2RlbDogVGVsZVN1aXRlVXBkYXRlclRlc3RNb2RlbCB8IHVuZGVmaW5lZCxcbiAgcnVuVGVzdHM6ICgpID0+IHZvaWQ7XG59PiA9ICh7IGZpbHRlclRleHQsIHNldEZpbHRlclRleHQsIHN0YXR1c0ZpbHRlcnMsIHNldFN0YXR1c0ZpbHRlcnMsIHByb2plY3RGaWx0ZXJzLCBzZXRQcm9qZWN0RmlsdGVycywgdGVzdE1vZGVsLCBydW5UZXN0cyB9KSA9PiB7XG4gIGNvbnN0IFtleHBhbmRlZCwgc2V0RXhwYW5kZWRdID0gUmVhY3QudXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBpbnB1dFJlZiA9IFJlYWN0LnVzZVJlZjxIVE1MSW5wdXRFbGVtZW50PihudWxsKTtcbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpbnB1dFJlZi5jdXJyZW50Py5mb2N1cygpO1xuICB9LCBbXSk7XG5cbiAgY29uc3Qgc3RhdHVzTGluZSA9IFsuLi5zdGF0dXNGaWx0ZXJzLmVudHJpZXMoKV0uZmlsdGVyKChbXywgdl0pID0+IHYpLm1hcCgoW3NdKSA9PiBzKS5qb2luKCcgJykgfHwgJ2FsbCc7XG4gIGNvbnN0IHByb2plY3RzTGluZSA9IFsuLi5wcm9qZWN0RmlsdGVycy5lbnRyaWVzKCldLmZpbHRlcigoW18sIHZdKSA9PiB2KS5tYXAoKFtwXSkgPT4gcCkuam9pbignICcpIHx8ICdhbGwnO1xuICByZXR1cm4gPGRpdiBjbGFzc05hbWU9J2ZpbHRlcnMnPlxuICAgIDxFeHBhbmRhYmxlXG4gICAgICBleHBhbmRlZD17ZXhwYW5kZWR9XG4gICAgICBzZXRFeHBhbmRlZD17c2V0RXhwYW5kZWR9XG4gICAgICB0aXRsZT17PGlucHV0IHJlZj17aW5wdXRSZWZ9IHR5cGU9J3NlYXJjaCcgcGxhY2Vob2xkZXI9J0ZpbHRlciAoZS5nLiB0ZXh0LCBAdGFnKScgc3BlbGxDaGVjaz17ZmFsc2V9IHZhbHVlPXtmaWx0ZXJUZXh0fVxuICAgICAgICBvbkNoYW5nZT17ZSA9PiB7XG4gICAgICAgICAgc2V0RmlsdGVyVGV4dChlLnRhcmdldC52YWx1ZSk7XG4gICAgICAgIH19XG4gICAgICAgIG9uS2V5RG93bj17ZSA9PiB7XG4gICAgICAgICAgaWYgKGUua2V5ID09PSAnRW50ZXInKVxuICAgICAgICAgICAgcnVuVGVzdHMoKTtcbiAgICAgICAgfX0gLz59PlxuICAgIDwvRXhwYW5kYWJsZT5cbiAgICA8ZGl2IGNsYXNzTmFtZT0nZmlsdGVyLXN1bW1hcnknIHRpdGxlPXsnU3RhdHVzOiAnICsgc3RhdHVzTGluZSArICdcXG5Qcm9qZWN0czogJyArIHByb2plY3RzTGluZX0gb25DbGljaz17KCkgPT4gc2V0RXhwYW5kZWQoIWV4cGFuZGVkKX0+XG4gICAgICA8c3BhbiBjbGFzc05hbWU9J2ZpbHRlci1sYWJlbCc+U3RhdHVzOjwvc3Bhbj4ge3N0YXR1c0xpbmV9XG4gICAgICA8c3BhbiBjbGFzc05hbWU9J2ZpbHRlci1sYWJlbCc+UHJvamVjdHM6PC9zcGFuPiB7cHJvamVjdHNMaW5lfVxuICAgIDwvZGl2PlxuICAgIHtleHBhbmRlZCAmJiA8ZGl2IGNsYXNzTmFtZT0naGJveCcgc3R5bGU9e3sgbWFyZ2luTGVmdDogMTQsIG1heEhlaWdodDogMjAwLCBvdmVyZmxvd1k6ICdhdXRvJyB9fT5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPSdmaWx0ZXItbGlzdCcgcm9sZT0nbGlzdCcgZGF0YS10ZXN0aWQ9J3N0YXR1cy1maWx0ZXJzJz5cbiAgICAgICAge1suLi5zdGF0dXNGaWx0ZXJzLmVudHJpZXMoKV0ubWFwKChbc3RhdHVzLCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICByZXR1cm4gPGRpdiBjbGFzc05hbWU9J2ZpbHRlci1lbnRyeScga2V5PXtzdGF0dXN9IHJvbGU9J2xpc3RpdGVtJz5cbiAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9J2NoZWNrYm94JyBjaGVja2VkPXt2YWx1ZX0gb25DaGFuZ2U9eygpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb3B5ID0gbmV3IE1hcChzdGF0dXNGaWx0ZXJzKTtcbiAgICAgICAgICAgICAgICBjb3B5LnNldChzdGF0dXMsICFjb3B5LmdldChzdGF0dXMpKTtcbiAgICAgICAgICAgICAgICBzZXRTdGF0dXNGaWx0ZXJzKGNvcHkpO1xuICAgICAgICAgICAgICB9fS8+XG4gICAgICAgICAgICAgIDxkaXY+e3N0YXR1c308L2Rpdj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPC9kaXY+O1xuICAgICAgICB9KX1cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzc05hbWU9J2ZpbHRlci1saXN0JyByb2xlPSdsaXN0JyBkYXRhLXRlc3RpZD0ncHJvamVjdC1maWx0ZXJzJz5cbiAgICAgICAge1suLi5wcm9qZWN0RmlsdGVycy5lbnRyaWVzKCldLm1hcCgoW3Byb2plY3ROYW1lLCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICByZXR1cm4gPGRpdiBjbGFzc05hbWU9J2ZpbHRlci1lbnRyeScga2V5PXtwcm9qZWN0TmFtZX0gIHJvbGU9J2xpc3RpdGVtJz5cbiAgICAgICAgICAgIDxsYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9J2NoZWNrYm94JyBjaGVja2VkPXt2YWx1ZX0gb25DaGFuZ2U9eygpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb3B5ID0gbmV3IE1hcChwcm9qZWN0RmlsdGVycyk7XG4gICAgICAgICAgICAgICAgY29weS5zZXQocHJvamVjdE5hbWUsICFjb3B5LmdldChwcm9qZWN0TmFtZSkpO1xuICAgICAgICAgICAgICAgIHNldFByb2plY3RGaWx0ZXJzKGNvcHkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbmZpZ0ZpbGUgPSB0ZXN0TW9kZWw/LmNvbmZpZz8uY29uZmlnRmlsZTtcbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnRmlsZSlcbiAgICAgICAgICAgICAgICAgIHNldHRpbmdzLnNldE9iamVjdChjb25maWdGaWxlICsgJzpwcm9qZWN0cycsIFsuLi5jb3B5LmVudHJpZXMoKV0uZmlsdGVyKChbXywgdl0pID0+IHYpLm1hcCgoW2tdKSA9PiBrKSk7XG4gICAgICAgICAgICAgIH19Lz5cbiAgICAgICAgICAgICAgPGRpdj57cHJvamVjdE5hbWUgfHwgJ3VudGl0bGVkJ308L2Rpdj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPC9kaXY+O1xuICAgICAgICB9KX1cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2Pn1cbiAgPC9kaXY+O1xufTtcbiIsIi8qKlxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgY2xzeCB9IGZyb20gJ0B3ZWIvdWlVdGlscyc7XG5pbXBvcnQgJy4vdGFnLmNzcyc7XG5cbmV4cG9ydCBjb25zdCBUYWdWaWV3ID0gKHsgdGFnLCBzdHlsZSwgb25DbGljayB9OiB7IHRhZzogc3RyaW5nLCBzdHlsZT86IFJlYWN0LkNTU1Byb3BlcnRpZXMsIG9uQ2xpY2s/OiAoZTogUmVhY3QuTW91c2VFdmVudCkgPT4gdm9pZCB9KSA9PiB7XG4gIHJldHVybiA8c3BhblxuICAgIGNsYXNzTmFtZT17Y2xzeCgndGFnJywgYHRhZy1jb2xvci0ke3RhZ05hbWVUb0NvbG9yKHRhZyl9YCl9XG4gICAgb25DbGljaz17b25DbGlja31cbiAgICBzdHlsZT17eyBtYXJnaW46ICc2cHggMCAwIDZweCcsIC4uLnN0eWxlIH19XG4gICAgdGl0bGU9e2BDbGljayB0byBmaWx0ZXIgYnkgdGFnOiAke3RhZ31gfVxuICA+XG4gICAge3RhZ31cbiAgPC9zcGFuPjtcbn07XG5cbi8vIGhhc2ggc3RyaW5nIHRvIGludGVnZXIgaW4gcmFuZ2UgWzAsIDZdIGZvciBjb2xvciBpbmRleCwgdG8gZ2V0IHNhbWUgY29sb3IgZm9yIHNhbWUgdGFnXG5mdW5jdGlvbiB0YWdOYW1lVG9Db2xvcihzdHI6IHN0cmluZykge1xuICBsZXQgaGFzaCA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKVxuICAgIGhhc2ggPSBzdHIuY2hhckNvZGVBdChpKSArICgoaGFzaCA8PCA4KSAtIGhhc2gpO1xuICByZXR1cm4gTWF0aC5hYnMoaGFzaCAlIDYpO1xufVxuIiwiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBUcmVlSXRlbSB9IGZyb20gJ0B0ZXN0SXNvbW9ycGhpYy90ZXN0VHJlZSc7XG5pbXBvcnQgdHlwZSB7IFRlc3RUcmVlIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3Rlc3RUcmVlJztcbmltcG9ydCAnQHdlYi9jb21tb24uY3NzJztcbmltcG9ydCB7IFRvb2xiYXIgfSBmcm9tICdAd2ViL2NvbXBvbmVudHMvdG9vbGJhcic7XG5pbXBvcnQgeyBUb29sYmFyQnV0dG9uIH0gZnJvbSAnQHdlYi9jb21wb25lbnRzL3Rvb2xiYXJCdXR0b24nO1xuaW1wb3J0IHR5cGUgeyBUcmVlU3RhdGUgfSBmcm9tICdAd2ViL2NvbXBvbmVudHMvdHJlZVZpZXcnO1xuaW1wb3J0IHsgVHJlZVZpZXcgfSBmcm9tICdAd2ViL2NvbXBvbmVudHMvdHJlZVZpZXcnO1xuaW1wb3J0ICdAd2ViL3RoaXJkX3BhcnR5L3ZzY29kZS9jb2RpY29uLmNzcyc7XG5pbXBvcnQgeyBtc1RvU3RyaW5nIH0gZnJvbSAnQHdlYi91aVV0aWxzJztcbmltcG9ydCB0eXBlICogYXMgcmVwb3J0ZXJUeXBlcyBmcm9tICdwbGF5d3JpZ2h0L3R5cGVzL3Rlc3RSZXBvcnRlcic7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBTb3VyY2VMb2NhdGlvbiB9IGZyb20gJy4vbW9kZWxVdGlsJztcbmltcG9ydCB7IHRlc3RTdGF0dXNJY29uIH0gZnJvbSAnLi90ZXN0VXRpbHMnO1xuaW1wb3J0ICcuL3VpTW9kZVRlc3RMaXN0Vmlldy5jc3MnO1xuaW1wb3J0IHR5cGUgeyBUZXN0U2VydmVyQ29ubmVjdGlvbiB9IGZyb20gJ0B0ZXN0SXNvbW9ycGhpYy90ZXN0U2VydmVyQ29ubmVjdGlvbic7XG5pbXBvcnQgeyBUYWdWaWV3IH0gZnJvbSAnLi90YWcnO1xuaW1wb3J0IHR5cGUgeyBUZWxlU3VpdGVVcGRhdGVyVGVzdE1vZGVsIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3RlbGVTdWl0ZVVwZGF0ZXInO1xuXG5jb25zdCBUZXN0VHJlZVZpZXcgPSBUcmVlVmlldzxUcmVlSXRlbT47XG5cbmV4cG9ydCBjb25zdCBUZXN0TGlzdFZpZXc6IFJlYWN0LkZDPHtcbiAgZmlsdGVyVGV4dDogc3RyaW5nLFxuICB0ZXN0VHJlZTogVGVzdFRyZWUsXG4gIHRlc3RTZXJ2ZXJDb25uZWN0aW9uOiBUZXN0U2VydmVyQ29ubmVjdGlvbiB8IHVuZGVmaW5lZCxcbiAgdGVzdE1vZGVsPzogVGVsZVN1aXRlVXBkYXRlclRlc3RNb2RlbCxcbiAgcnVuVGVzdHM6IChtb2RlOiAnYm91bmNlLWlmLWJ1c3knIHwgJ3F1ZXVlLWlmLWJ1c3knLCB0ZXN0SWRzOiBTZXQ8c3RyaW5nPikgPT4gdm9pZCxcbiAgcnVubmluZ1N0YXRlPzogeyB0ZXN0SWRzOiBTZXQ8c3RyaW5nPiwgaXRlbVNlbGVjdGVkQnlVc2VyPzogYm9vbGVhbiwgY29tcGxldGVkPzogYm9vbGVhbiB9LFxuICB3YXRjaEFsbDogYm9vbGVhbixcbiAgd2F0Y2hlZFRyZWVJZHM6IHsgdmFsdWU6IFNldDxzdHJpbmc+IH0sXG4gIHNldFdhdGNoZWRUcmVlSWRzOiAoaWRzOiB7IHZhbHVlOiBTZXQ8c3RyaW5nPiB9KSA9PiB2b2lkLFxuICBpc0xvYWRpbmc/OiBib29sZWFuLFxuICBvbkl0ZW1TZWxlY3RlZDogKGl0ZW06IHsgdHJlZUl0ZW0/OiBUcmVlSXRlbSwgdGVzdENhc2U/OiByZXBvcnRlclR5cGVzLlRlc3RDYXNlLCB0ZXN0RmlsZT86IFNvdXJjZUxvY2F0aW9uIH0pID0+IHZvaWQsXG4gIHJlcXVlc3RlZENvbGxhcHNlQWxsQ291bnQ6IG51bWJlcixcbiAgcmVxdWVzdGVkRXhwYW5kQWxsQ291bnQ6IG51bWJlcixcbiAgc2V0RmlsdGVyVGV4dDogKHRleHQ6IHN0cmluZykgPT4gdm9pZCxcbiAgb25SZXZlYWxTb3VyY2U6ICgpID0+IHZvaWQsXG59PiA9ICh7IGZpbHRlclRleHQsIHRlc3RNb2RlbCwgdGVzdFNlcnZlckNvbm5lY3Rpb24sIHRlc3RUcmVlLCBydW5UZXN0cywgcnVubmluZ1N0YXRlLCB3YXRjaEFsbCwgd2F0Y2hlZFRyZWVJZHMsIHNldFdhdGNoZWRUcmVlSWRzLCBpc0xvYWRpbmcsIG9uSXRlbVNlbGVjdGVkLCByZXF1ZXN0ZWRDb2xsYXBzZUFsbENvdW50LCByZXF1ZXN0ZWRFeHBhbmRBbGxDb3VudCwgc2V0RmlsdGVyVGV4dCwgb25SZXZlYWxTb3VyY2UgfSkgPT4ge1xuICBjb25zdCBbdHJlZVN0YXRlLCBzZXRUcmVlU3RhdGVdID0gUmVhY3QudXNlU3RhdGU8VHJlZVN0YXRlPih7IGV4cGFuZGVkSXRlbXM6IG5ldyBNYXAoKSB9KTtcbiAgY29uc3QgW3NlbGVjdGVkVHJlZUl0ZW1JZCwgc2V0U2VsZWN0ZWRUcmVlSXRlbUlkXSA9IFJlYWN0LnVzZVN0YXRlPHN0cmluZyB8IHVuZGVmaW5lZD4oKTtcbiAgY29uc3QgW2NvbGxhcHNlQWxsQ291bnQsIHNldENvbGxhcHNlQWxsQ291bnRdID0gUmVhY3QudXNlU3RhdGUocmVxdWVzdGVkQ29sbGFwc2VBbGxDb3VudCk7XG4gIGNvbnN0IFtleHBhbmRBbGxDb3VudCwgc2V0RXhwYW5kQWxsQ291bnRdID0gUmVhY3QudXNlU3RhdGUocmVxdWVzdGVkRXhwYW5kQWxsQ291bnQpO1xuXG4gIC8vIExvb2sgZm9yIGEgZmlyc3QgZmFpbHVyZSB3aXRoaW4gdGhlIHJ1biBiYXRjaCB0byBzZWxlY3QgaXQuXG4gIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgLy8gSWYgY29sbGFwc2Ugd2FzIHJlcXVlc3RlZCwgY2xlYXIgdGhlIGV4cGFuZGVkIGl0ZW1zIGFuZCByZXR1cm4gdy9vIHNlbGVjdGVkIGl0ZW0uXG4gICAgaWYgKGNvbGxhcHNlQWxsQ291bnQgIT09IHJlcXVlc3RlZENvbGxhcHNlQWxsQ291bnQpIHtcbiAgICAgIHRyZWVTdGF0ZS5leHBhbmRlZEl0ZW1zLmNsZWFyKCk7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdGVzdFRyZWUuZmxhdFRyZWVJdGVtcygpKVxuICAgICAgICB0cmVlU3RhdGUuZXhwYW5kZWRJdGVtcy5zZXQoaXRlbS5pZCwgZmFsc2UpO1xuICAgICAgc2V0Q29sbGFwc2VBbGxDb3VudChyZXF1ZXN0ZWRDb2xsYXBzZUFsbENvdW50KTtcbiAgICAgIHNldFNlbGVjdGVkVHJlZUl0ZW1JZCh1bmRlZmluZWQpO1xuICAgICAgc2V0VHJlZVN0YXRlKHsgLi4udHJlZVN0YXRlIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChleHBhbmRBbGxDb3VudCAhPT0gcmVxdWVzdGVkRXhwYW5kQWxsQ291bnQpIHtcbiAgICAgIHRyZWVTdGF0ZS5leHBhbmRlZEl0ZW1zLmNsZWFyKCk7XG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgdGVzdFRyZWUuZmxhdFRyZWVJdGVtcygpKVxuICAgICAgICB0cmVlU3RhdGUuZXhwYW5kZWRJdGVtcy5zZXQoaXRlbS5pZCwgdHJ1ZSk7XG4gICAgICBzZXRFeHBhbmRBbGxDb3VudChyZXF1ZXN0ZWRFeHBhbmRBbGxDb3VudCk7XG4gICAgICBzZXRTZWxlY3RlZFRyZWVJdGVtSWQodW5kZWZpbmVkKTtcbiAgICAgIHNldFRyZWVTdGF0ZSh7IC4uLnRyZWVTdGF0ZSB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXJ1bm5pbmdTdGF0ZSB8fCBydW5uaW5nU3RhdGUuaXRlbVNlbGVjdGVkQnlVc2VyKVxuICAgICAgcmV0dXJuO1xuICAgIGxldCBzZWxlY3RlZFRyZWVJdGVtOiBUcmVlSXRlbSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCB2aXNpdCA9ICh0cmVlSXRlbTogVHJlZUl0ZW0pID0+IHtcbiAgICAgIHRyZWVJdGVtLmNoaWxkcmVuLmZvckVhY2godmlzaXQpO1xuICAgICAgaWYgKHNlbGVjdGVkVHJlZUl0ZW0pXG4gICAgICAgIHJldHVybjtcbiAgICAgIGlmICh0cmVlSXRlbS5zdGF0dXMgPT09ICdmYWlsZWQnKSB7XG4gICAgICAgIGlmICh0cmVlSXRlbS5raW5kID09PSAndGVzdCcgJiYgcnVubmluZ1N0YXRlLnRlc3RJZHMuaGFzKHRyZWVJdGVtLnRlc3QuaWQpKVxuICAgICAgICAgIHNlbGVjdGVkVHJlZUl0ZW0gPSB0cmVlSXRlbTtcbiAgICAgICAgZWxzZSBpZiAodHJlZUl0ZW0ua2luZCA9PT0gJ2Nhc2UnICYmIHJ1bm5pbmdTdGF0ZS50ZXN0SWRzLmhhcyh0cmVlSXRlbS50ZXN0c1swXT8uaWQpKVxuICAgICAgICAgIHNlbGVjdGVkVHJlZUl0ZW0gPSB0cmVlSXRlbTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHZpc2l0KHRlc3RUcmVlLnJvb3RJdGVtKTtcblxuICAgIGlmIChzZWxlY3RlZFRyZWVJdGVtKVxuICAgICAgc2V0U2VsZWN0ZWRUcmVlSXRlbUlkKHNlbGVjdGVkVHJlZUl0ZW0uaWQpO1xuICB9LCBbcnVubmluZ1N0YXRlLCBzZXRTZWxlY3RlZFRyZWVJdGVtSWQsIHRlc3RUcmVlLCBjb2xsYXBzZUFsbENvdW50LCBzZXRDb2xsYXBzZUFsbENvdW50LCByZXF1ZXN0ZWRDb2xsYXBzZUFsbENvdW50LCBleHBhbmRBbGxDb3VudCwgc2V0RXhwYW5kQWxsQ291bnQsIHJlcXVlc3RlZEV4cGFuZEFsbENvdW50LCB0cmVlU3RhdGUsIHNldFRyZWVTdGF0ZV0pO1xuXG4gIC8vIENvbXB1dGUgc2VsZWN0ZWQgaXRlbVxuICBjb25zdCBzZWxlY3RlZFRyZWVJdGVtID0gUmVhY3QudXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCFzZWxlY3RlZFRyZWVJdGVtSWQpXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB0ZXN0VHJlZS50cmVlSXRlbUJ5SWQoc2VsZWN0ZWRUcmVlSXRlbUlkKTtcbiAgfSwgW3NlbGVjdGVkVHJlZUl0ZW1JZCwgdGVzdFRyZWVdKTtcblxuICAvLyBIYW5kbGUgc2VsZWN0aW9uIGVmZmVjdHMgc2VwYXJhdGVseVxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghdGVzdE1vZGVsKVxuICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IHRlc3RGaWxlID0gaXRlbUxvY2F0aW9uKHNlbGVjdGVkVHJlZUl0ZW0sIHRlc3RNb2RlbCk7XG4gICAgbGV0IHNlbGVjdGVkVGVzdDogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSB8IHVuZGVmaW5lZDtcbiAgICBpZiAoc2VsZWN0ZWRUcmVlSXRlbT8ua2luZCA9PT0gJ3Rlc3QnKVxuICAgICAgc2VsZWN0ZWRUZXN0ID0gc2VsZWN0ZWRUcmVlSXRlbS50ZXN0O1xuICAgIGVsc2UgaWYgKHNlbGVjdGVkVHJlZUl0ZW0/LmtpbmQgPT09ICdjYXNlJyAmJiBzZWxlY3RlZFRyZWVJdGVtLnRlc3RzLmxlbmd0aCA9PT0gMSlcbiAgICAgIHNlbGVjdGVkVGVzdCA9IHNlbGVjdGVkVHJlZUl0ZW0udGVzdHNbMF07XG4gICAgb25JdGVtU2VsZWN0ZWQoeyB0cmVlSXRlbTogc2VsZWN0ZWRUcmVlSXRlbSwgdGVzdENhc2U6IHNlbGVjdGVkVGVzdCwgdGVzdEZpbGUgfSk7XG4gIH0sIFt0ZXN0TW9kZWwsIHNlbGVjdGVkVHJlZUl0ZW0sIG9uSXRlbVNlbGVjdGVkXSk7XG5cbiAgLy8gVXBkYXRlIHdhdGNoIGFsbC5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaXNMb2FkaW5nKVxuICAgICAgcmV0dXJuO1xuICAgIGlmICh3YXRjaEFsbCkge1xuICAgICAgdGVzdFNlcnZlckNvbm5lY3Rpb24/LndhdGNoTm9SZXBseSh7IGZpbGVOYW1lczogdGVzdFRyZWUuZmlsZU5hbWVzKCkgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGZpbGVOYW1lcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgZm9yIChjb25zdCBpdGVtSWQgb2Ygd2F0Y2hlZFRyZWVJZHMudmFsdWUpIHtcbiAgICAgICAgY29uc3QgdHJlZUl0ZW0gPSB0ZXN0VHJlZS50cmVlSXRlbUJ5SWQoaXRlbUlkKTtcbiAgICAgICAgY29uc3QgZmlsZU5hbWUgPSB0cmVlSXRlbT8ubG9jYXRpb24uZmlsZTtcbiAgICAgICAgaWYgKGZpbGVOYW1lKVxuICAgICAgICAgIGZpbGVOYW1lcy5hZGQoZmlsZU5hbWUpO1xuICAgICAgfVxuICAgICAgdGVzdFNlcnZlckNvbm5lY3Rpb24/LndhdGNoTm9SZXBseSh7IGZpbGVOYW1lczogWy4uLmZpbGVOYW1lc10gfSk7XG4gICAgfVxuICB9LCBbaXNMb2FkaW5nLCB0ZXN0VHJlZSwgd2F0Y2hBbGwsIHdhdGNoZWRUcmVlSWRzLCB0ZXN0U2VydmVyQ29ubmVjdGlvbl0pO1xuXG4gIGNvbnN0IHJ1blRyZWVJdGVtID0gKHRyZWVJdGVtOiBUcmVlSXRlbSkgPT4ge1xuICAgIHNldFNlbGVjdGVkVHJlZUl0ZW1JZCh0cmVlSXRlbS5pZCk7XG4gICAgcnVuVGVzdHMoJ2JvdW5jZS1pZi1idXN5JywgdGVzdFRyZWUuY29sbGVjdFRlc3RJZHModHJlZUl0ZW0pKTtcbiAgfTtcblxuICBjb25zdCBoYW5kbGVUYWdDbGljayA9IChlOiBSZWFjdC5Nb3VzZUV2ZW50LCB0YWc6IHN0cmluZykgPT4ge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIGlmIChlLm1ldGFLZXkgfHwgZS5jdHJsS2V5KSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IGZpbHRlclRleHQuc3BsaXQoJyAnKTtcbiAgICAgIGlmIChwYXJ0cy5pbmNsdWRlcyh0YWcpKVxuICAgICAgICBzZXRGaWx0ZXJUZXh0KHBhcnRzLmZpbHRlcih0ID0+IHQgIT09IHRhZykuam9pbignICcpLnRyaW0oKSk7XG4gICAgICBlbHNlXG4gICAgICAgIHNldEZpbHRlclRleHQoKGZpbHRlclRleHQgKyAnICcgKyB0YWcpLnRyaW0oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlcGxhY2UgYWxsIGV4aXN0aW5nIHRhZ3Mgd2l0aCB0aGlzIHRhZy5cbiAgICAgIHNldEZpbHRlclRleHQoKGZpbHRlclRleHQuc3BsaXQoJyAnKS5maWx0ZXIodCA9PiAhdC5zdGFydHNXaXRoKCdAJykpLmpvaW4oJyAnKSArICcgJyArIHRhZykudHJpbSgpKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIDxUZXN0VHJlZVZpZXdcbiAgICBuYW1lPSd0ZXN0cydcbiAgICB0cmVlU3RhdGU9e3RyZWVTdGF0ZX1cbiAgICBzZXRUcmVlU3RhdGU9e3NldFRyZWVTdGF0ZX1cbiAgICByb290SXRlbT17dGVzdFRyZWUucm9vdEl0ZW19XG4gICAgZGF0YVRlc3RJZD0ndGVzdC10cmVlJ1xuICAgIHJlbmRlcj17dHJlZUl0ZW0gPT4ge1xuICAgICAgY29uc3QgcHJlZml4SWQgPSB0cmVlSXRlbS5pZC5yZXBsYWNlKC9bXlxcd1xcZC1fXS9nLCAnLScpO1xuICAgICAgY29uc3QgbGFiZWxJZCA9IHByZWZpeElkICsgJy1sYWJlbCc7XG4gICAgICBjb25zdCB0aW1lSWQgPSBwcmVmaXhJZCArICctdGltZSc7XG4gICAgICByZXR1cm4gPGRpdiBjbGFzc05hbWU9J2hib3ggdWktbW9kZS10cmVlLWl0ZW0nIGFyaWEtbGFiZWxsZWRieT17YCR7bGFiZWxJZH0gJHt0aW1lSWR9YH0+XG4gICAgICAgIDxkaXYgaWQ9e2xhYmVsSWR9IGNsYXNzTmFtZT0ndWktbW9kZS10cmVlLWl0ZW0tdGl0bGUnPlxuICAgICAgICAgIDxzcGFuPnt0cmVlSXRlbS50aXRsZX08L3NwYW4+XG4gICAgICAgICAge3RyZWVJdGVtLmtpbmQgPT09ICdjYXNlJyA/IHRyZWVJdGVtLnRhZ3MubWFwKHRhZyA9PiA8VGFnVmlldyBrZXk9e3RhZ30gdGFnPXt0YWcuc2xpY2UoMSl9IG9uQ2xpY2s9e2UgPT4gaGFuZGxlVGFnQ2xpY2soZSwgdGFnKX0gLz4pIDogbnVsbH1cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIHshIXRyZWVJdGVtLmR1cmF0aW9uICYmIHRyZWVJdGVtLnN0YXR1cyAhPT0gJ3NraXBwZWQnICYmIDxkaXYgaWQ9e3RpbWVJZH0gY2xhc3NOYW1lPSd1aS1tb2RlLXRyZWUtaXRlbS10aW1lJz57bXNUb1N0cmluZyh0cmVlSXRlbS5kdXJhdGlvbil9PC9kaXY+fVxuICAgICAgICA8VG9vbGJhciBub01pbkhlaWdodD17dHJ1ZX0gbm9TaGFkb3c9e3RydWV9PlxuICAgICAgICAgIDxUb29sYmFyQnV0dG9uIGljb249J3BsYXknIHRpdGxlPSdSdW4nIG9uQ2xpY2s9eygpID0+IHJ1blRyZWVJdGVtKHRyZWVJdGVtKX0gZGlzYWJsZWQ9eyEhcnVubmluZ1N0YXRlICYmICFydW5uaW5nU3RhdGUuY29tcGxldGVkfT48L1Rvb2xiYXJCdXR0b24+XG4gICAgICAgICAgPFRvb2xiYXJCdXR0b24gaWNvbj0nZ28tdG8tZmlsZScgdGl0bGU9J1Nob3cgc291cmNlJyBvbkNsaWNrPXtvblJldmVhbFNvdXJjZX0gc3R5bGU9eyh0cmVlSXRlbS5raW5kID09PSAnZ3JvdXAnICYmIHRyZWVJdGVtLnN1YktpbmQgPT09ICdmb2xkZXInKSA/IHsgdmlzaWJpbGl0eTogJ2hpZGRlbicgfSA6IHt9fT48L1Rvb2xiYXJCdXR0b24+XG4gICAgICAgICAgeyF3YXRjaEFsbCAmJiA8VG9vbGJhckJ1dHRvbiBpY29uPSdleWUnIHRpdGxlPSdXYXRjaCcgb25DbGljaz17KCkgPT4ge1xuICAgICAgICAgICAgaWYgKHdhdGNoZWRUcmVlSWRzLnZhbHVlLmhhcyh0cmVlSXRlbS5pZCkpXG4gICAgICAgICAgICAgIHdhdGNoZWRUcmVlSWRzLnZhbHVlLmRlbGV0ZSh0cmVlSXRlbS5pZCk7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgIHdhdGNoZWRUcmVlSWRzLnZhbHVlLmFkZCh0cmVlSXRlbS5pZCk7XG4gICAgICAgICAgICBzZXRXYXRjaGVkVHJlZUlkcyh7IC4uLndhdGNoZWRUcmVlSWRzIH0pO1xuICAgICAgICAgIH19IHRvZ2dsZWQ9e3dhdGNoZWRUcmVlSWRzLnZhbHVlLmhhcyh0cmVlSXRlbS5pZCl9PjwvVG9vbGJhckJ1dHRvbj59XG4gICAgICAgIDwvVG9vbGJhcj5cbiAgICAgIDwvZGl2PjtcbiAgICB9fVxuICAgIGljb249e3RyZWVJdGVtID0+IHRlc3RTdGF0dXNJY29uKHRyZWVJdGVtLnN0YXR1cyl9XG4gICAgdGl0bGU9e3RyZWVJdGVtID0+IHRyZWVJdGVtLnRpdGxlfVxuICAgIHNlbGVjdGVkSXRlbT17c2VsZWN0ZWRUcmVlSXRlbX1cbiAgICBvbkFjY2VwdGVkPXtydW5UcmVlSXRlbX1cbiAgICBvblNlbGVjdGVkPXt0cmVlSXRlbSA9PiB7XG4gICAgICBpZiAocnVubmluZ1N0YXRlKVxuICAgICAgICBydW5uaW5nU3RhdGUuaXRlbVNlbGVjdGVkQnlVc2VyID0gdHJ1ZTtcbiAgICAgIHNldFNlbGVjdGVkVHJlZUl0ZW1JZCh0cmVlSXRlbS5pZCk7XG4gICAgfX1cbiAgICBpc0Vycm9yPXt0cmVlSXRlbSA9PiB0cmVlSXRlbS5raW5kID09PSAnZ3JvdXAnID8gdHJlZUl0ZW0uaGFzTG9hZEVycm9ycyA6IGZhbHNlfVxuICAgIGF1dG9FeHBhbmREZXB0aD17ZmlsdGVyVGV4dCA/IDUgOiAxfVxuICAgIG5vSXRlbXNNZXNzYWdlPXtpc0xvYWRpbmcgPyAnTG9hZGluZ1xcdTIwMjYnIDogJ05vIHRlc3RzJ30gLz47XG59O1xuXG5mdW5jdGlvbiBpdGVtTG9jYXRpb24oaXRlbTogVHJlZUl0ZW0gfCB1bmRlZmluZWQsIG1vZGVsOiBUZWxlU3VpdGVVcGRhdGVyVGVzdE1vZGVsIHwgdW5kZWZpbmVkKTogU291cmNlTG9jYXRpb24gfCB1bmRlZmluZWQge1xuICBpZiAoIWl0ZW0gfHwgIW1vZGVsKVxuICAgIHJldHVybjtcbiAgcmV0dXJuIHtcbiAgICBmaWxlOiBpdGVtLmxvY2F0aW9uLmZpbGUsXG4gICAgbGluZTogaXRlbS5sb2NhdGlvbi5saW5lLFxuICAgIGNvbHVtbjogaXRlbS5sb2NhdGlvbi5jb2x1bW4sXG4gICAgc291cmNlOiB7XG4gICAgICBlcnJvcnM6IG1vZGVsLmxvYWRFcnJvcnMuZmlsdGVyKGUgPT4gZS5sb2NhdGlvbj8uZmlsZSA9PT0gaXRlbS5sb2NhdGlvbi5maWxlKS5tYXAoZSA9PiAoeyBsaW5lOiBlLmxvY2F0aW9uIS5saW5lLCBtZXNzYWdlOiBlLm1lc3NhZ2UhIH0pKSxcbiAgICAgIGNvbnRlbnQ6IHVuZGVmaW5lZCxcbiAgICB9XG4gIH07XG59XG4iLCIvKipcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXJ0aWZhY3RzRm9sZGVyTmFtZSh3b3JrZXJJbmRleDogbnVtYmVyKSB7XG4gIHJldHVybiBgLnBsYXl3cmlnaHQtYXJ0aWZhY3RzLSR7d29ya2VySW5kZXh9YDtcbn1cbiIsIi8qKlxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7IGFydGlmYWN0c0ZvbGRlck5hbWUgfSBmcm9tICdAdGVzdElzb21vcnBoaWMvZm9sZGVycyc7XG5pbXBvcnQgdHlwZSB7IFRyZWVJdGVtIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3Rlc3RUcmVlJztcbmltcG9ydCAnQHdlYi9jb21tb24uY3NzJztcbmltcG9ydCAnQHdlYi90aGlyZF9wYXJ0eS92c2NvZGUvY29kaWNvbi5jc3MnO1xuaW1wb3J0IHR5cGUgKiBhcyByZXBvcnRlclR5cGVzIGZyb20gJ3BsYXl3cmlnaHQvdHlwZXMvdGVzdFJlcG9ydGVyJztcbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdHlwZSB7IENvbnRleHRFbnRyeSB9IGZyb20gJy4uL3R5cGVzL2VudHJpZXMnO1xuaW1wb3J0IHR5cGUgeyBTb3VyY2VMb2NhdGlvbiB9IGZyb20gJy4vbW9kZWxVdGlsJztcbmltcG9ydCB7IE11bHRpVHJhY2VNb2RlbCB9IGZyb20gJy4vbW9kZWxVdGlsJztcbmltcG9ydCB7IFdvcmtiZW5jaCB9IGZyb20gJy4vd29ya2JlbmNoJztcblxuZXhwb3J0IGNvbnN0IFRyYWNlVmlldzogUmVhY3QuRkM8e1xuICBpdGVtOiB7IHRyZWVJdGVtPzogVHJlZUl0ZW0sIHRlc3RGaWxlPzogU291cmNlTG9jYXRpb24sIHRlc3RDYXNlPzogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSB9LFxuICByb290RGlyPzogc3RyaW5nLFxuICBvbk9wZW5FeHRlcm5hbGx5PzogKGxvY2F0aW9uOiBTb3VyY2VMb2NhdGlvbikgPT4gdm9pZCxcbiAgcmV2ZWFsU291cmNlPzogYm9vbGVhbixcbiAgcGF0aFNlcGFyYXRvcjogc3RyaW5nLFxufT4gPSAoeyBpdGVtLCByb290RGlyLCBvbk9wZW5FeHRlcm5hbGx5LCByZXZlYWxTb3VyY2UsIHBhdGhTZXBhcmF0b3IgfSkgPT4ge1xuICBjb25zdCBbbW9kZWwsIHNldE1vZGVsXSA9IFJlYWN0LnVzZVN0YXRlPHsgbW9kZWw6IE11bHRpVHJhY2VNb2RlbCwgaXNMaXZlOiBib29sZWFuIH0gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGNvbnN0IFtjb3VudGVyLCBzZXRDb3VudGVyXSA9IFJlYWN0LnVzZVN0YXRlKDApO1xuICBjb25zdCBwb2xsVGltZXIgPSBSZWFjdC51c2VSZWY8Tm9kZUpTLlRpbWVvdXQgfCBudWxsPihudWxsKTtcblxuICBjb25zdCB7IG91dHB1dERpciB9ID0gUmVhY3QudXNlTWVtbygoKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0RGlyID0gaXRlbS50ZXN0Q2FzZSA/IG91dHB1dERpckZvclRlc3RDYXNlKGl0ZW0udGVzdENhc2UpIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IG91dHB1dERpciB9O1xuICB9LCBbaXRlbV0pO1xuXG4gIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKHBvbGxUaW1lci5jdXJyZW50KVxuICAgICAgY2xlYXJUaW1lb3V0KHBvbGxUaW1lci5jdXJyZW50KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGl0ZW0udGVzdENhc2U/LnJlc3VsdHNbMF07XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHNldE1vZGVsKHVuZGVmaW5lZCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGVzdCBmaW5pc2hlZC5cbiAgICBjb25zdCBhdHRhY2htZW50ID0gcmVzdWx0ICYmIHJlc3VsdC5kdXJhdGlvbiA+PSAwICYmIHJlc3VsdC5hdHRhY2htZW50cy5maW5kKGEgPT4gYS5uYW1lID09PSAndHJhY2UnKTtcbiAgICBpZiAoYXR0YWNobWVudCAmJiBhdHRhY2htZW50LnBhdGgpIHtcbiAgICAgIGxvYWRTaW5nbGVUcmFjZUZpbGUoYXR0YWNobWVudC5wYXRoKS50aGVuKG1vZGVsID0+IHNldE1vZGVsKHsgbW9kZWwsIGlzTGl2ZTogZmFsc2UgfSkpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghb3V0cHV0RGlyKSB7XG4gICAgICBzZXRNb2RlbCh1bmRlZmluZWQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRyYWNlTG9jYXRpb24gPSBbXG4gICAgICBvdXRwdXREaXIsXG4gICAgICBhcnRpZmFjdHNGb2xkZXJOYW1lKHJlc3VsdCEud29ya2VySW5kZXgpLFxuICAgICAgJ3RyYWNlcycsXG4gICAgICBgJHtpdGVtLnRlc3RDYXNlPy5pZH0uanNvbmBcbiAgICBdLmpvaW4ocGF0aFNlcGFyYXRvcik7XG4gICAgLy8gU3RhcnQgcG9sbGluZyBydW5uaW5nIHRlc3QuXG4gICAgcG9sbFRpbWVyLmN1cnJlbnQgPSBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gYXdhaXQgbG9hZFNpbmdsZVRyYWNlRmlsZSh0cmFjZUxvY2F0aW9uKTtcbiAgICAgICAgc2V0TW9kZWwoeyBtb2RlbCwgaXNMaXZlOiB0cnVlIH0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gbmV3IE11bHRpVHJhY2VNb2RlbCgnJywgW10pO1xuICAgICAgICBtb2RlbC5lcnJvckRlc2NyaXB0b3JzLnB1c2goLi4ucmVzdWx0LmVycm9ycy5mbGF0TWFwKGVycm9yID0+ICEhZXJyb3IubWVzc2FnZSA/IFt7IG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UgfV0gOiBbXSkpO1xuICAgICAgICBzZXRNb2RlbCh7IG1vZGVsLCBpc0xpdmU6IGZhbHNlIH0pO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0Q291bnRlcihjb3VudGVyICsgMSk7XG4gICAgICB9XG4gICAgfSwgNTAwKTtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKHBvbGxUaW1lci5jdXJyZW50KVxuICAgICAgICBjbGVhclRpbWVvdXQocG9sbFRpbWVyLmN1cnJlbnQpO1xuICAgIH07XG4gIH0sIFtvdXRwdXREaXIsIGl0ZW0sIHNldE1vZGVsLCBjb3VudGVyLCBzZXRDb3VudGVyLCBwYXRoU2VwYXJhdG9yXSk7XG5cbiAgcmV0dXJuIDxXb3JrYmVuY2hcbiAgICBtb2RlbD17bW9kZWw/Lm1vZGVsfVxuICAgIGtleT0nd29ya2JlbmNoJ1xuICAgIHNob3dTb3VyY2VzRmlyc3Q9e3RydWV9XG4gICAgcm9vdERpcj17cm9vdERpcn1cbiAgICBmYWxsYmFja0xvY2F0aW9uPXtpdGVtLnRlc3RGaWxlfVxuICAgIGlzTGl2ZT17bW9kZWw/LmlzTGl2ZX1cbiAgICBzdGF0dXM9e2l0ZW0udHJlZUl0ZW0/LnN0YXR1c31cbiAgICBhbm5vdGF0aW9ucz17aXRlbS50ZXN0Q2FzZT8uYW5ub3RhdGlvbnMgPz8gW119XG4gICAgb25PcGVuRXh0ZXJuYWxseT17b25PcGVuRXh0ZXJuYWxseX1cbiAgICByZXZlYWxTb3VyY2U9e3JldmVhbFNvdXJjZX1cbiAgLz47XG59O1xuXG5jb25zdCBvdXRwdXREaXJGb3JUZXN0Q2FzZSA9ICh0ZXN0Q2FzZTogcmVwb3J0ZXJUeXBlcy5UZXN0Q2FzZSk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gIGZvciAobGV0IHN1aXRlOiByZXBvcnRlclR5cGVzLlN1aXRlIHwgdW5kZWZpbmVkID0gdGVzdENhc2UucGFyZW50OyBzdWl0ZTsgc3VpdGUgPSBzdWl0ZS5wYXJlbnQpIHtcbiAgICBpZiAoc3VpdGUucHJvamVjdCgpKVxuICAgICAgcmV0dXJuIHN1aXRlLnByb2plY3QoKT8ub3V0cHV0RGlyO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59O1xuXG5hc3luYyBmdW5jdGlvbiBsb2FkU2luZ2xlVHJhY2VGaWxlKHVybDogc3RyaW5nKTogUHJvbWlzZTxNdWx0aVRyYWNlTW9kZWw+IHtcbiAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcygpO1xuICBwYXJhbXMuc2V0KCd0cmFjZScsIHVybCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYGNvbnRleHRzPyR7cGFyYW1zLnRvU3RyaW5nKCl9YCk7XG4gIGNvbnN0IGNvbnRleHRFbnRyaWVzID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIENvbnRleHRFbnRyeVtdO1xuICByZXR1cm4gbmV3IE11bHRpVHJhY2VNb2RlbCh1cmwsIGNvbnRleHRFbnRyaWVzKTtcbn1cbiIsIi8qKlxuICogQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCAnQHdlYi90aGlyZF9wYXJ0eS92c2NvZGUvY29kaWNvbi5jc3MnO1xuaW1wb3J0ICdAd2ViL2NvbW1vbi5jc3MnO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IFRlbGVTdWl0ZSB9IGZyb20gJ0B0ZXN0SXNvbW9ycGhpYy90ZWxlUmVjZWl2ZXInO1xuaW1wb3J0IHsgVGVsZVN1aXRlVXBkYXRlciwgdHlwZSBUZWxlU3VpdGVVcGRhdGVyUHJvZ3Jlc3MsIHR5cGUgVGVsZVN1aXRlVXBkYXRlclRlc3RNb2RlbCB9IGZyb20gJ0B0ZXN0SXNvbW9ycGhpYy90ZWxlU3VpdGVVcGRhdGVyJztcbmltcG9ydCB0eXBlIHsgVGVsZVRlc3RDYXNlIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3RlbGVSZWNlaXZlcic7XG5pbXBvcnQgdHlwZSAqIGFzIHJlcG9ydGVyVHlwZXMgZnJvbSAncGxheXdyaWdodC90eXBlcy90ZXN0UmVwb3J0ZXInO1xuaW1wb3J0IHsgU3BsaXRWaWV3IH0gZnJvbSAnQHdlYi9jb21wb25lbnRzL3NwbGl0Vmlldyc7XG5pbXBvcnQgdHlwZSB7IFNvdXJjZUxvY2F0aW9uIH0gZnJvbSAnLi9tb2RlbFV0aWwnO1xuaW1wb3J0ICcuL3VpTW9kZVZpZXcuY3NzJztcbmltcG9ydCB7IFRvb2xiYXJCdXR0b24gfSBmcm9tICdAd2ViL2NvbXBvbmVudHMvdG9vbGJhckJ1dHRvbic7XG5pbXBvcnQgeyBUb29sYmFyIH0gZnJvbSAnQHdlYi9jb21wb25lbnRzL3Rvb2xiYXInO1xuaW1wb3J0IHR5cGUgeyBYdGVybURhdGFTb3VyY2UgfSBmcm9tICdAd2ViL2NvbXBvbmVudHMveHRlcm1XcmFwcGVyJztcbmltcG9ydCB7IFh0ZXJtV3JhcHBlciB9IGZyb20gJ0B3ZWIvY29tcG9uZW50cy94dGVybVdyYXBwZXInO1xuaW1wb3J0IHsgY2xzeCwgc2V0dGluZ3MsIHVzZVNldHRpbmcgfSBmcm9tICdAd2ViL3VpVXRpbHMnO1xuaW1wb3J0IHsgc3RhdHVzRXgsIFRlc3RUcmVlIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3Rlc3RUcmVlJztcbmltcG9ydCB0eXBlIHsgVHJlZUl0ZW0gIH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3Rlc3RUcmVlJztcbmltcG9ydCB7IFRlc3RTZXJ2ZXJDb25uZWN0aW9uLCBXZWJTb2NrZXRUZXN0U2VydmVyVHJhbnNwb3J0IH0gZnJvbSAnQHRlc3RJc29tb3JwaGljL3Rlc3RTZXJ2ZXJDb25uZWN0aW9uJztcbmltcG9ydCB7IEZpbHRlcnNWaWV3IH0gZnJvbSAnLi91aU1vZGVGaWx0ZXJzVmlldyc7XG5pbXBvcnQgeyBUZXN0TGlzdFZpZXcgfSBmcm9tICcuL3VpTW9kZVRlc3RMaXN0Vmlldyc7XG5pbXBvcnQgeyBUcmFjZVZpZXcgfSBmcm9tICcuL3VpTW9kZVRyYWNlVmlldyc7XG5pbXBvcnQgeyBTZXR0aW5nc1ZpZXcgfSBmcm9tICcuL3NldHRpbmdzVmlldyc7XG5pbXBvcnQgeyBEZWZhdWx0U2V0dGluZ3NWaWV3IH0gZnJvbSAnLi9kZWZhdWx0U2V0dGluZ3NWaWV3JztcblxubGV0IHh0ZXJtU2l6ZSA9IHsgY29sczogODAsIHJvd3M6IDI0IH07XG5jb25zdCB4dGVybURhdGFTb3VyY2U6IFh0ZXJtRGF0YVNvdXJjZSA9IHtcbiAgcGVuZGluZzogW10sXG4gIGNsZWFyOiAoKSA9PiB7fSxcbiAgd3JpdGU6IGRhdGEgPT4geHRlcm1EYXRhU291cmNlLnBlbmRpbmcucHVzaChkYXRhKSxcbiAgcmVzaXplOiAoKSA9PiB7fSxcbn07XG5cbmNvbnN0IHNlYXJjaFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG5jb25zdCB0ZXN0U2VydmVyQmFzZVVybCA9IG5ldyBVUkwoc2VhcmNoUGFyYW1zLmdldCgnc2VydmVyJykgPz8gJy4uLycsIHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcbmNvbnN0IHdzVVJMID0gbmV3IFVSTChzZWFyY2hQYXJhbXMuZ2V0KCd3cycpISwgdGVzdFNlcnZlckJhc2VVcmwpO1xud3NVUkwucHJvdG9jb2wgPSAod3NVUkwucHJvdG9jb2wgPT09ICdodHRwczonID8gJ3dzczonIDogJ3dzOicpO1xuY29uc3QgcXVlcnlQYXJhbXMgPSB7XG4gIGFyZ3M6IHNlYXJjaFBhcmFtcy5nZXRBbGwoJ2FyZycpLFxuICBncmVwOiBzZWFyY2hQYXJhbXMuZ2V0KCdncmVwJykgfHwgdW5kZWZpbmVkLFxuICBncmVwSW52ZXJ0OiBzZWFyY2hQYXJhbXMuZ2V0KCdncmVwSW52ZXJ0JykgfHwgdW5kZWZpbmVkLFxuICBwcm9qZWN0czogc2VhcmNoUGFyYW1zLmdldEFsbCgncHJvamVjdCcpLFxuICB3b3JrZXJzOiBzZWFyY2hQYXJhbXMuZ2V0KCd3b3JrZXJzJykgfHwgdW5kZWZpbmVkLFxuICBoZWFkZWQ6IHNlYXJjaFBhcmFtcy5oYXMoJ2hlYWRlZCcpLFxuICB1cGRhdGVTbmFwc2hvdHM6IChzZWFyY2hQYXJhbXMuZ2V0KCd1cGRhdGVTbmFwc2hvdHMnKSBhcyByZXBvcnRlclR5cGVzLkZ1bGxDb25maWdbJ3VwZGF0ZVNuYXBzaG90cyddIHwgdW5kZWZpbmVkKSB8fCB1bmRlZmluZWQsXG4gIHJlcG9ydGVyczogc2VhcmNoUGFyYW1zLmhhcygncmVwb3J0ZXInKSA/IHNlYXJjaFBhcmFtcy5nZXRBbGwoJ3JlcG9ydGVyJykgOiB1bmRlZmluZWQsXG4gIHBhdGhTZXBhcmF0b3I6IHNlYXJjaFBhcmFtcy5nZXQoJ3BhdGhTZXBhcmF0b3InKSB8fCAnLycsXG59O1xuaWYgKHF1ZXJ5UGFyYW1zLnVwZGF0ZVNuYXBzaG90cyAmJiAhWydhbGwnLCAnY2hhbmdlZCcsICdub25lJywgJ21pc3NpbmcnXS5pbmNsdWRlcyhxdWVyeVBhcmFtcy51cGRhdGVTbmFwc2hvdHMpKVxuICBxdWVyeVBhcmFtcy51cGRhdGVTbmFwc2hvdHMgPSB1bmRlZmluZWQ7XG5cbmNvbnN0IGlzTWFjID0gbmF2aWdhdG9yLnBsYXRmb3JtID09PSAnTWFjSW50ZWwnO1xuXG5leHBvcnQgY29uc3QgVUlNb2RlVmlldzogUmVhY3QuRkM8e30+ID0gKHtcbn0pID0+IHtcbiAgY29uc3QgW2ZpbHRlclRleHQsIHNldEZpbHRlclRleHRdID0gUmVhY3QudXNlU3RhdGU8c3RyaW5nPignJyk7XG4gIGNvbnN0IFtpc1Nob3dpbmdPdXRwdXQsIHNldElzU2hvd2luZ091dHB1dF0gPSBSZWFjdC51c2VTdGF0ZTxib29sZWFuPihmYWxzZSk7XG4gIGNvbnN0IFtvdXRwdXRDb250YWluc0Vycm9yLCBzZXRPdXRwdXRDb250YWluc0Vycm9yXSA9IFJlYWN0LnVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgW3N0YXR1c0ZpbHRlcnMsIHNldFN0YXR1c0ZpbHRlcnNdID0gUmVhY3QudXNlU3RhdGU8TWFwPHN0cmluZywgYm9vbGVhbj4+KG5ldyBNYXAoW1xuICAgIFsncGFzc2VkJywgZmFsc2VdLFxuICAgIFsnZmFpbGVkJywgZmFsc2VdLFxuICAgIFsnc2tpcHBlZCcsIGZhbHNlXSxcbiAgXSkpO1xuICBjb25zdCBbcHJvamVjdEZpbHRlcnMsIHNldFByb2plY3RGaWx0ZXJzXSA9IFJlYWN0LnVzZVN0YXRlPE1hcDxzdHJpbmcsIGJvb2xlYW4+PihuZXcgTWFwKCkpO1xuICBjb25zdCBbdGVzdE1vZGVsLCBzZXRUZXN0TW9kZWxdID0gUmVhY3QudXNlU3RhdGU8VGVsZVN1aXRlVXBkYXRlclRlc3RNb2RlbD4oKTtcbiAgY29uc3QgW3Byb2dyZXNzLCBzZXRQcm9ncmVzc10gPSBSZWFjdC51c2VTdGF0ZTxUZWxlU3VpdGVVcGRhdGVyUHJvZ3Jlc3MgJiB7IHRvdGFsOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4oKTtcbiAgY29uc3QgW3NlbGVjdGVkSXRlbSwgc2V0U2VsZWN0ZWRJdGVtXSA9IFJlYWN0LnVzZVN0YXRlPHsgdHJlZUl0ZW0/OiBUcmVlSXRlbSwgdGVzdEZpbGU/OiBTb3VyY2VMb2NhdGlvbiwgdGVzdENhc2U/OiByZXBvcnRlclR5cGVzLlRlc3RDYXNlIH0+KHt9KTtcbiAgY29uc3QgW3Zpc2libGVUZXN0SWRzLCBzZXRWaXNpYmxlVGVzdElkc10gPSBSZWFjdC51c2VTdGF0ZTxTZXQ8c3RyaW5nPj4obmV3IFNldCgpKTtcbiAgY29uc3QgW2lzTG9hZGluZywgc2V0SXNMb2FkaW5nXSA9IFJlYWN0LnVzZVN0YXRlPGJvb2xlYW4+KGZhbHNlKTtcbiAgY29uc3QgW3J1bm5pbmdTdGF0ZSwgc2V0UnVubmluZ1N0YXRlXSA9IFJlYWN0LnVzZVN0YXRlPHsgdGVzdElkczogU2V0PHN0cmluZz4sIGl0ZW1TZWxlY3RlZEJ5VXNlcj86IGJvb2xlYW4sIGNvbXBsZXRlZD86IGJvb2xlYW4gfSB8IHVuZGVmaW5lZD4oKTtcbiAgY29uc3QgaXNSdW5uaW5nVGVzdCA9IHJ1bm5pbmdTdGF0ZSAmJiAhcnVubmluZ1N0YXRlLmNvbXBsZXRlZDtcblxuICBjb25zdCBbd2F0Y2hBbGwsIHNldFdhdGNoQWxsXSA9IHVzZVNldHRpbmc8Ym9vbGVhbj4oJ3dhdGNoLWFsbCcsIGZhbHNlKTtcbiAgY29uc3QgW3dhdGNoZWRUcmVlSWRzLCBzZXRXYXRjaGVkVHJlZUlkc10gPSBSZWFjdC51c2VTdGF0ZTx7IHZhbHVlOiBTZXQ8c3RyaW5nPiB9Pih7IHZhbHVlOiBuZXcgU2V0KCkgfSk7XG4gIGNvbnN0IGNvbW1hbmRRdWV1ZSA9IFJlYWN0LnVzZVJlZihQcm9taXNlLnJlc29sdmUoKSk7XG4gIGNvbnN0IHJ1blRlc3RCYWNrbG9nID0gUmVhY3QudXNlUmVmPFNldDxzdHJpbmc+PihuZXcgU2V0KCkpO1xuICBjb25zdCBbY29sbGFwc2VBbGxDb3VudCwgc2V0Q29sbGFwc2VBbGxDb3VudF0gPSBSZWFjdC51c2VTdGF0ZSgwKTtcbiAgY29uc3QgW2V4cGFuZEFsbENvdW50LCBzZXRFeHBhbmRBbGxDb3VudF0gPSBSZWFjdC51c2VTdGF0ZSgwKTtcbiAgY29uc3QgW2lzRGlzY29ubmVjdGVkLCBzZXRJc0Rpc2Nvbm5lY3RlZF0gPSBSZWFjdC51c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtoYXNCcm93c2Vycywgc2V0SGFzQnJvd3NlcnNdID0gUmVhY3QudXNlU3RhdGUodHJ1ZSk7XG4gIGNvbnN0IFt0ZXN0U2VydmVyQ29ubmVjdGlvbiwgc2V0VGVzdFNlcnZlckNvbm5lY3Rpb25dID0gUmVhY3QudXNlU3RhdGU8VGVzdFNlcnZlckNvbm5lY3Rpb24+KCk7XG4gIGNvbnN0IFt0ZWxlU3VpdGVVcGRhdGVyLCBzZXRUZWxlU3VpdGVVcGRhdGVyXSA9IFJlYWN0LnVzZVN0YXRlPFRlbGVTdWl0ZVVwZGF0ZXI+KCk7XG4gIGNvbnN0IFtzZXR0aW5nc1Zpc2libGUsIHNldFNldHRpbmdzVmlzaWJsZV0gPSBSZWFjdC51c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFt0ZXN0aW5nT3B0aW9uc1Zpc2libGUsIHNldFRlc3RpbmdPcHRpb25zVmlzaWJsZV0gPSBSZWFjdC51c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IFtyZXZlYWxTb3VyY2UsIHNldFJldmVhbFNvdXJjZV0gPSBSZWFjdC51c2VTdGF0ZShmYWxzZSk7XG4gIGNvbnN0IG9uUmV2ZWFsU291cmNlID0gUmVhY3QudXNlQ2FsbGJhY2soKCkgPT4gc2V0UmV2ZWFsU291cmNlKHRydWUpLCBbc2V0UmV2ZWFsU291cmNlXSk7XG5cbiAgY29uc3QgW3NpbmdsZVdvcmtlciwgc2V0U2luZ2xlV29ya2VyXSA9IHVzZVNldHRpbmc8Ym9vbGVhbj4oJ3NpbmdsZS13b3JrZXInLCBmYWxzZSk7XG4gIGNvbnN0IFt1cGRhdGVTbmFwc2hvdHMsIHNldFVwZGF0ZVNuYXBzaG90c10gPSB1c2VTZXR0aW5nPHJlcG9ydGVyVHlwZXMuRnVsbENvbmZpZ1sndXBkYXRlU25hcHNob3RzJ10+KCd1cGRhdGVTbmFwc2hvdHMnLCAnbWlzc2luZycpO1xuICBjb25zdCBbbWVyZ2VGaWxlc10gPSB1c2VTZXR0aW5nKCdtZXJnZUZpbGVzJywgZmFsc2UpO1xuXG4gIGNvbnN0IGlucHV0UmVmID0gUmVhY3QudXNlUmVmPEhUTUxJbnB1dEVsZW1lbnQ+KG51bGwpO1xuXG4gIGNvbnN0IHJlbG9hZFRlc3RzID0gUmVhY3QudXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldFRlc3RTZXJ2ZXJDb25uZWN0aW9uKHByZXZDb25uZWN0aW9uID0+IHtcbiAgICAgIHByZXZDb25uZWN0aW9uPy5jbG9zZSgpO1xuICAgICAgcmV0dXJuIG5ldyBUZXN0U2VydmVyQ29ubmVjdGlvbihuZXcgV2ViU29ja2V0VGVzdFNlcnZlclRyYW5zcG9ydCh3c1VSTCkpO1xuICAgIH0pO1xuICB9LCBbXSk7XG5cbiAgLy8gTG9hZCB0ZXN0cyBvbiBzdGFydHVwLlxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlucHV0UmVmLmN1cnJlbnQ/LmZvY3VzKCk7XG4gICAgc2V0SXNMb2FkaW5nKHRydWUpO1xuICAgIHJlbG9hZFRlc3RzKCk7XG4gIH0sIFtyZWxvYWRUZXN0c10pO1xuXG4gIC8vIFdpcmUgc2VydmVyIGNvbm5lY3Rpb24gdG8gdGhlIGF1eGlsaWFyeSBVSSBmZWF0dXJlcy5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIXRlc3RTZXJ2ZXJDb25uZWN0aW9uKVxuICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IGRpc3Bvc2FibGVzID0gW1xuICAgICAgdGVzdFNlcnZlckNvbm5lY3Rpb24ub25TdGRpbyhwYXJhbXMgPT4ge1xuICAgICAgICBpZiAocGFyYW1zLmJ1ZmZlcikge1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSBhdG9iKHBhcmFtcy5idWZmZXIpO1xuICAgICAgICAgIHh0ZXJtRGF0YVNvdXJjZS53cml0ZShkYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB4dGVybURhdGFTb3VyY2Uud3JpdGUocGFyYW1zLnRleHQhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMudHlwZSA9PT0gJ3N0ZGVycicpXG4gICAgICAgICAgc2V0T3V0cHV0Q29udGFpbnNFcnJvcih0cnVlKTtcbiAgICAgIH0pLFxuICAgICAgdGVzdFNlcnZlckNvbm5lY3Rpb24ub25DbG9zZSgoKSA9PiBzZXRJc0Rpc2Nvbm5lY3RlZCh0cnVlKSlcbiAgICBdO1xuICAgIHh0ZXJtRGF0YVNvdXJjZS5yZXNpemUgPSAoY29scywgcm93cykgPT4ge1xuICAgICAgeHRlcm1TaXplID0geyBjb2xzLCByb3dzIH07XG4gICAgICB0ZXN0U2VydmVyQ29ubmVjdGlvbi5yZXNpemVUZXJtaW5hbE5vUmVwbHkoeyBjb2xzLCByb3dzIH0pO1xuICAgIH07XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGZvciAoY29uc3QgZGlzcG9zYWJsZSBvZiBkaXNwb3NhYmxlcylcbiAgICAgICAgZGlzcG9zYWJsZS5kaXNwb3NlKCk7XG4gICAgfTtcbiAgfSwgW3Rlc3RTZXJ2ZXJDb25uZWN0aW9uXSk7XG5cbiAgLy8gVGhpcyBpcyB0aGUgbWFpbiByb3V0aW5lLCBldmVyeSB0aW1lIGNvbm5lY3Rpb24gdXBkYXRlcyBpdCBzdGFydHMgdGhlXG4gIC8vIHdob2xlIHdvcmtmbG93LlxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghdGVzdFNlcnZlckNvbm5lY3Rpb24pXG4gICAgICByZXR1cm47XG5cbiAgICBsZXQgdGhyb3R0bGVUaW1lcjogTm9kZUpTLlRpbWVvdXQgfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgdGVsZVN1aXRlVXBkYXRlciA9IG5ldyBUZWxlU3VpdGVVcGRhdGVyKHtcbiAgICAgIG9uVXBkYXRlOiBpbW1lZGlhdGUgPT4ge1xuICAgICAgICBjbGVhclRpbWVvdXQodGhyb3R0bGVUaW1lcik7XG4gICAgICAgIHRocm90dGxlVGltZXIgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChpbW1lZGlhdGUpIHtcbiAgICAgICAgICBzZXRUZXN0TW9kZWwodGVsZVN1aXRlVXBkYXRlci5hc01vZGVsKCkpO1xuICAgICAgICB9IGVsc2UgaWYgKCF0aHJvdHRsZVRpbWVyKSB7XG4gICAgICAgICAgdGhyb3R0bGVUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgc2V0VGVzdE1vZGVsKHRlbGVTdWl0ZVVwZGF0ZXIuYXNNb2RlbCgpKTtcbiAgICAgICAgICB9LCAyNTApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgb25FcnJvcjogZXJyb3IgPT4ge1xuICAgICAgICB4dGVybURhdGFTb3VyY2Uud3JpdGUoKGVycm9yLnN0YWNrIHx8IGVycm9yLnZhbHVlIHx8ICcnKSArICdcXG4nKTtcbiAgICAgICAgc2V0T3V0cHV0Q29udGFpbnNFcnJvcih0cnVlKTtcbiAgICAgIH0sXG4gICAgICBwYXRoU2VwYXJhdG9yOiBxdWVyeVBhcmFtcy5wYXRoU2VwYXJhdG9yLFxuICAgIH0pO1xuXG4gICAgc2V0VGVsZVN1aXRlVXBkYXRlcih0ZWxlU3VpdGVVcGRhdGVyKTtcblxuICAgIHNldFRlc3RNb2RlbCh1bmRlZmluZWQpO1xuICAgIHNldElzTG9hZGluZyh0cnVlKTtcbiAgICBzZXRXYXRjaGVkVHJlZUlkcyh7IHZhbHVlOiBuZXcgU2V0KCkgfSk7XG4gICAgKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRlc3RTZXJ2ZXJDb25uZWN0aW9uLmluaXRpYWxpemUoe1xuICAgICAgICAgIGludGVyY2VwdFN0ZGlvOiB0cnVlLFxuICAgICAgICAgIHdhdGNoVGVzdERpcnM6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHsgc3RhdHVzLCByZXBvcnQgfSA9IGF3YWl0IHRlc3RTZXJ2ZXJDb25uZWN0aW9uLnJ1bkdsb2JhbFNldHVwKHt9KTtcbiAgICAgICAgdGVsZVN1aXRlVXBkYXRlci5wcm9jZXNzR2xvYmFsUmVwb3J0KHJlcG9ydCk7XG4gICAgICAgIGlmIChzdGF0dXMgIT09ICdwYXNzZWQnKVxuICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZXN0U2VydmVyQ29ubmVjdGlvbi5saXN0VGVzdHMoeyBwcm9qZWN0czogcXVlcnlQYXJhbXMucHJvamVjdHMsIGxvY2F0aW9uczogcXVlcnlQYXJhbXMuYXJncywgZ3JlcDogcXVlcnlQYXJhbXMuZ3JlcCwgZ3JlcEludmVydDogcXVlcnlQYXJhbXMuZ3JlcEludmVydCB9KTtcbiAgICAgICAgdGVsZVN1aXRlVXBkYXRlci5wcm9jZXNzTGlzdFJlcG9ydChyZXN1bHQucmVwb3J0KTtcblxuICAgICAgICB0ZXN0U2VydmVyQ29ubmVjdGlvbi5vblJlcG9ydChwYXJhbXMgPT4ge1xuICAgICAgICAgIHRlbGVTdWl0ZVVwZGF0ZXIucHJvY2Vzc1Rlc3RSZXBvcnRFdmVudChwYXJhbXMpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB7IGhhc0Jyb3dzZXJzIH0gPSBhd2FpdCB0ZXN0U2VydmVyQ29ubmVjdGlvbi5jaGVja0Jyb3dzZXJzKHt9KTtcbiAgICAgICAgc2V0SGFzQnJvd3NlcnMoaGFzQnJvd3NlcnMpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgc2V0SXNMb2FkaW5nKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQodGhyb3R0bGVUaW1lcik7XG4gICAgfTtcbiAgfSwgW3Rlc3RTZXJ2ZXJDb25uZWN0aW9uXSk7XG5cbiAgLy8gVXBkYXRlIHByb2plY3QgZmlsdGVyIGRlZmF1bHQgdmFsdWVzLlxuICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghdGVzdE1vZGVsKVxuICAgICAgcmV0dXJuO1xuXG4gICAgY29uc3QgeyBjb25maWcsIHJvb3RTdWl0ZSB9ID0gdGVzdE1vZGVsO1xuICAgIGNvbnN0IHNlbGVjdGVkUHJvamVjdHMgPSBjb25maWcuY29uZmlnRmlsZSA/IHNldHRpbmdzLmdldE9iamVjdDxzdHJpbmdbXSB8IHVuZGVmaW5lZD4oY29uZmlnLmNvbmZpZ0ZpbGUgKyAnOnByb2plY3RzJywgdW5kZWZpbmVkKSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBuZXdGaWx0ZXIgPSBuZXcgTWFwKHByb2plY3RGaWx0ZXJzKTtcbiAgICBmb3IgKGNvbnN0IHByb2plY3ROYW1lIG9mIG5ld0ZpbHRlci5rZXlzKCkpIHtcbiAgICAgIGlmICghcm9vdFN1aXRlLnN1aXRlcy5maW5kKHMgPT4gcy50aXRsZSA9PT0gcHJvamVjdE5hbWUpKVxuICAgICAgICBuZXdGaWx0ZXIuZGVsZXRlKHByb2plY3ROYW1lKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBwcm9qZWN0U3VpdGUgb2Ygcm9vdFN1aXRlLnN1aXRlcykge1xuICAgICAgaWYgKCFuZXdGaWx0ZXIuaGFzKHByb2plY3RTdWl0ZS50aXRsZSkpXG4gICAgICAgIG5ld0ZpbHRlci5zZXQocHJvamVjdFN1aXRlLnRpdGxlLCAhIXNlbGVjdGVkUHJvamVjdHM/LmluY2x1ZGVzKHByb2plY3RTdWl0ZS50aXRsZSkpO1xuICAgIH1cbiAgICBpZiAoIXNlbGVjdGVkUHJvamVjdHMgJiYgbmV3RmlsdGVyLnNpemUgJiYgIVsuLi5uZXdGaWx0ZXIudmFsdWVzKCldLmluY2x1ZGVzKHRydWUpKVxuICAgICAgbmV3RmlsdGVyLnNldChuZXdGaWx0ZXIuZW50cmllcygpLm5leHQoKS52YWx1ZSFbMF0sIHRydWUpO1xuICAgIGlmIChwcm9qZWN0RmlsdGVycy5zaXplICE9PSBuZXdGaWx0ZXIuc2l6ZSB8fCBbLi4ucHJvamVjdEZpbHRlcnNdLnNvbWUoKFtrLCB2XSkgPT4gbmV3RmlsdGVyLmdldChrKSAhPT0gdikpXG4gICAgICBzZXRQcm9qZWN0RmlsdGVycyhuZXdGaWx0ZXIpO1xuICB9LCBbcHJvamVjdEZpbHRlcnMsIHRlc3RNb2RlbF0pO1xuXG4gIC8vIFVwZGF0ZSBwcm9ncmVzcy5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaXNSdW5uaW5nVGVzdCAmJiB0ZXN0TW9kZWw/LnByb2dyZXNzKVxuICAgICAgc2V0UHJvZ3Jlc3ModGVzdE1vZGVsLnByb2dyZXNzKTtcbiAgICBlbHNlIGlmICghdGVzdE1vZGVsKVxuICAgICAgc2V0UHJvZ3Jlc3ModW5kZWZpbmVkKTtcbiAgfSwgW3Rlc3RNb2RlbCwgaXNSdW5uaW5nVGVzdF0pO1xuXG4gIC8vIFRlc3QgdHJlZSBpcyBidWlsdCBmcm9tIHRoZSBtb2RlbCBhbmQgZmlsdGVycy5cbiAgY29uc3QgeyB0ZXN0VHJlZSB9ID0gUmVhY3QudXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKCF0ZXN0TW9kZWwpXG4gICAgICByZXR1cm4geyB0ZXN0VHJlZTogbmV3IFRlc3RUcmVlKCcnLCBuZXcgVGVsZVN1aXRlKCcnLCAncm9vdCcpLCBbXSwgcHJvamVjdEZpbHRlcnMsIHF1ZXJ5UGFyYW1zLnBhdGhTZXBhcmF0b3IsIG1lcmdlRmlsZXMpIH07XG4gICAgY29uc3QgdGVzdFRyZWUgPSBuZXcgVGVzdFRyZWUoJycsIHRlc3RNb2RlbC5yb290U3VpdGUsIHRlc3RNb2RlbC5sb2FkRXJyb3JzLCBwcm9qZWN0RmlsdGVycywgcXVlcnlQYXJhbXMucGF0aFNlcGFyYXRvciwgbWVyZ2VGaWxlcyk7XG4gICAgdGVzdFRyZWUuZmlsdGVyVHJlZShmaWx0ZXJUZXh0LCBzdGF0dXNGaWx0ZXJzLCBpc1J1bm5pbmdUZXN0ID8gcnVubmluZ1N0YXRlPy50ZXN0SWRzIDogdW5kZWZpbmVkKTtcbiAgICB0ZXN0VHJlZS5zb3J0QW5kUHJvcGFnYXRlU3RhdHVzKCk7XG4gICAgdGVzdFRyZWUuc2hvcnRlblJvb3QoKTtcbiAgICB0ZXN0VHJlZS5mbGF0dGVuRm9yU2luZ2xlUHJvamVjdCgpO1xuICAgIHNldFZpc2libGVUZXN0SWRzKHRlc3RUcmVlLnRlc3RJZHMoKSk7XG4gICAgcmV0dXJuIHsgdGVzdFRyZWUgfTtcbiAgfSwgW2ZpbHRlclRleHQsIHRlc3RNb2RlbCwgc3RhdHVzRmlsdGVycywgcHJvamVjdEZpbHRlcnMsIHNldFZpc2libGVUZXN0SWRzLCBydW5uaW5nU3RhdGUsIGlzUnVubmluZ1Rlc3QsIG1lcmdlRmlsZXNdKTtcblxuICBjb25zdCBydW5UZXN0cyA9IFJlYWN0LnVzZUNhbGxiYWNrKChtb2RlOiAncXVldWUtaWYtYnVzeScgfCAnYm91bmNlLWlmLWJ1c3knLCB0ZXN0SWRzOiBTZXQ8c3RyaW5nPikgPT4ge1xuICAgIGlmICghdGVzdFNlcnZlckNvbm5lY3Rpb24gfHwgIXRlc3RNb2RlbClcbiAgICAgIHJldHVybjtcbiAgICBpZiAobW9kZSA9PT0gJ2JvdW5jZS1pZi1idXN5JyAmJiBpc1J1bm5pbmdUZXN0KVxuICAgICAgcmV0dXJuO1xuXG4gICAgcnVuVGVzdEJhY2tsb2cuY3VycmVudCA9IG5ldyBTZXQoWy4uLnJ1blRlc3RCYWNrbG9nLmN1cnJlbnQsIC4uLnRlc3RJZHNdKTtcbiAgICBjb21tYW5kUXVldWUuY3VycmVudCA9IGNvbW1hbmRRdWV1ZS5jdXJyZW50LnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdElkcyA9IHJ1blRlc3RCYWNrbG9nLmN1cnJlbnQ7XG4gICAgICBydW5UZXN0QmFja2xvZy5jdXJyZW50ID0gbmV3IFNldCgpO1xuICAgICAgaWYgKCF0ZXN0SWRzLnNpemUpXG4gICAgICAgIHJldHVybjtcblxuICAgICAgLy8gQ2xlYXIgdGVzdCByZXN1bHRzLlxuICAgICAge1xuICAgICAgICBmb3IgKGNvbnN0IHRlc3Qgb2YgdGVzdE1vZGVsLnJvb3RTdWl0ZT8uYWxsVGVzdHMoKSB8fCBbXSkge1xuICAgICAgICAgIGlmICh0ZXN0SWRzLmhhcyh0ZXN0LmlkKSkge1xuICAgICAgICAgICAgdGVzdC5yZXN1bHRzID0gW107XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSAodGVzdCBhcyBUZWxlVGVzdENhc2UpLl9jcmVhdGVUZXN0UmVzdWx0KCdwZW5kaW5nJyk7XG4gICAgICAgICAgICAocmVzdWx0IGFzIGFueSlbc3RhdHVzRXhdID0gJ3NjaGVkdWxlZCc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNldFRlc3RNb2RlbCh7IC4uLnRlc3RNb2RlbCB9KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGltZSA9ICcgIFsnICsgbmV3IERhdGUoKS50b0xvY2FsZVRpbWVTdHJpbmcoKSArICddJztcbiAgICAgIHh0ZXJtRGF0YVNvdXJjZS53cml0ZSgnXFx4MUJbMm3igJQnLnJlcGVhdChNYXRoLm1heCgwLCB4dGVybVNpemUuY29scyAtIHRpbWUubGVuZ3RoKSkgKyB0aW1lICsgJ1xceDFCWzIybScpO1xuICAgICAgc2V0UHJvZ3Jlc3MoeyB0b3RhbDogMCwgcGFzc2VkOiAwLCBmYWlsZWQ6IDAsIHNraXBwZWQ6IDAgfSk7XG4gICAgICBzZXRSdW5uaW5nU3RhdGUoeyB0ZXN0SWRzIH0pO1xuXG4gICAgICBhd2FpdCB0ZXN0U2VydmVyQ29ubmVjdGlvbi5ydW5UZXN0cyh7XG4gICAgICAgIGxvY2F0aW9uczogcXVlcnlQYXJhbXMuYXJncyxcbiAgICAgICAgZ3JlcDogcXVlcnlQYXJhbXMuZ3JlcCxcbiAgICAgICAgZ3JlcEludmVydDogcXVlcnlQYXJhbXMuZ3JlcEludmVydCxcbiAgICAgICAgdGVzdElkczogWy4uLnRlc3RJZHNdLFxuICAgICAgICBwcm9qZWN0czogWy4uLnByb2plY3RGaWx0ZXJzXS5maWx0ZXIoKFtfLCB2XSkgPT4gdikubWFwKChbcF0pID0+IHApLFxuICAgICAgICB1cGRhdGVTbmFwc2hvdHMsXG4gICAgICAgIHJlcG9ydGVyczogcXVlcnlQYXJhbXMucmVwb3J0ZXJzLFxuICAgICAgICB3b3JrZXJzOiBzaW5nbGVXb3JrZXIgPyAxIDogdW5kZWZpbmVkLFxuICAgICAgICB0cmFjZTogJ29uJyxcbiAgICAgIH0pO1xuICAgICAgLy8gQ2xlYXIgcGVuZGluZyB0ZXN0cyBpbiBjYXNlIG9mIGludGVycnVwdC5cbiAgICAgIGZvciAoY29uc3QgdGVzdCBvZiB0ZXN0TW9kZWwucm9vdFN1aXRlPy5hbGxUZXN0cygpIHx8IFtdKSB7XG4gICAgICAgIGlmICh0ZXN0LnJlc3VsdHNbMF0/LmR1cmF0aW9uID09PSAtMSlcbiAgICAgICAgICB0ZXN0LnJlc3VsdHMgPSBbXTtcbiAgICAgIH1cbiAgICAgIHNldFRlc3RNb2RlbCh7IC4uLnRlc3RNb2RlbCB9KTtcbiAgICAgIHNldFJ1bm5pbmdTdGF0ZShvbGRTdGF0ZSA9PiBvbGRTdGF0ZSA/ICh7IC4uLm9sZFN0YXRlLCBjb21wbGV0ZWQ6IHRydWUgfSkgOiB1bmRlZmluZWQpO1xuICAgIH0pO1xuICB9LCBbcHJvamVjdEZpbHRlcnMsIGlzUnVubmluZ1Rlc3QsIHRlc3RNb2RlbCwgdGVzdFNlcnZlckNvbm5lY3Rpb24sIHVwZGF0ZVNuYXBzaG90cywgc2luZ2xlV29ya2VyXSk7XG5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIXRlc3RTZXJ2ZXJDb25uZWN0aW9uIHx8ICF0ZWxlU3VpdGVVcGRhdGVyKVxuICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IGRpc3Bvc2FibGUgPSB0ZXN0U2VydmVyQ29ubmVjdGlvbi5vblRlc3RGaWxlc0NoYW5nZWQoYXN5bmMgcGFyYW1zID0+IHtcbiAgICAgIC8vIGZldGNoIHRoZSBuZXcgbGlzdCBvZiB0ZXN0c1xuICAgICAgY29tbWFuZFF1ZXVlLmN1cnJlbnQgPSBjb21tYW5kUXVldWUuY3VycmVudC50aGVuKGFzeW5jICgpID0+IHtcbiAgICAgICAgc2V0SXNMb2FkaW5nKHRydWUpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRlc3RTZXJ2ZXJDb25uZWN0aW9uLmxpc3RUZXN0cyh7IHByb2plY3RzOiBxdWVyeVBhcmFtcy5wcm9qZWN0cywgbG9jYXRpb25zOiBxdWVyeVBhcmFtcy5hcmdzLCBncmVwOiBxdWVyeVBhcmFtcy5ncmVwLCBncmVwSW52ZXJ0OiBxdWVyeVBhcmFtcy5ncmVwSW52ZXJ0IH0pO1xuICAgICAgICAgIHRlbGVTdWl0ZVVwZGF0ZXIucHJvY2Vzc0xpc3RSZXBvcnQocmVzdWx0LnJlcG9ydCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgIGNvbnNvbGUubG9nKGUpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIHNldElzTG9hZGluZyhmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgYXdhaXQgY29tbWFuZFF1ZXVlLmN1cnJlbnQ7XG5cbiAgICAgIGlmIChwYXJhbXMudGVzdEZpbGVzLmxlbmd0aCA9PT0gMClcbiAgICAgICAgcmV0dXJuO1xuXG4gICAgICAvLyBydW4gYWZmZWN0ZWQgd2F0Y2hlZCB0ZXN0c1xuICAgICAgY29uc3QgdGVzdE1vZGVsID0gdGVsZVN1aXRlVXBkYXRlci5hc01vZGVsKCk7XG4gICAgICBjb25zdCB0ZXN0VHJlZSA9IG5ldyBUZXN0VHJlZSgnJywgdGVzdE1vZGVsLnJvb3RTdWl0ZSwgdGVzdE1vZGVsLmxvYWRFcnJvcnMsIHByb2plY3RGaWx0ZXJzLCBxdWVyeVBhcmFtcy5wYXRoU2VwYXJhdG9yLCBtZXJnZUZpbGVzKTtcblxuICAgICAgY29uc3QgdGVzdElkczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGNvbnN0IHNldCA9IG5ldyBTZXQocGFyYW1zLnRlc3RGaWxlcyk7XG4gICAgICBpZiAod2F0Y2hBbGwpIHtcbiAgICAgICAgY29uc3QgdmlzaXQgPSAodHJlZUl0ZW06IFRyZWVJdGVtKSA9PiB7XG4gICAgICAgICAgY29uc3QgZmlsZU5hbWUgPSB0cmVlSXRlbS5sb2NhdGlvbi5maWxlO1xuICAgICAgICAgIGlmIChmaWxlTmFtZSAmJiBzZXQuaGFzKGZpbGVOYW1lKSlcbiAgICAgICAgICAgIHRlc3RJZHMucHVzaCguLi50ZXN0VHJlZS5jb2xsZWN0VGVzdElkcyh0cmVlSXRlbSkpO1xuICAgICAgICAgIGlmICh0cmVlSXRlbS5raW5kID09PSAnZ3JvdXAnICYmIHRyZWVJdGVtLnN1YktpbmQgPT09ICdmb2xkZXInKVxuICAgICAgICAgICAgdHJlZUl0ZW0uY2hpbGRyZW4uZm9yRWFjaCh2aXNpdCk7XG4gICAgICAgIH07XG4gICAgICAgIHZpc2l0KHRlc3RUcmVlLnJvb3RJdGVtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAoY29uc3QgdHJlZUlkIG9mIHdhdGNoZWRUcmVlSWRzLnZhbHVlKSB7XG4gICAgICAgICAgY29uc3QgdHJlZUl0ZW0gPSB0ZXN0VHJlZS50cmVlSXRlbUJ5SWQodHJlZUlkKTtcbiAgICAgICAgICBjb25zdCBmaWxlTmFtZSA9IHRyZWVJdGVtPy5sb2NhdGlvbi5maWxlO1xuICAgICAgICAgIGlmIChmaWxlTmFtZSAmJiBzZXQuaGFzKGZpbGVOYW1lKSlcbiAgICAgICAgICAgIHRlc3RJZHMucHVzaCguLi50ZXN0VHJlZS5jb2xsZWN0VGVzdElkcyh0cmVlSXRlbSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBydW5UZXN0cygncXVldWUtaWYtYnVzeScsIG5ldyBTZXQodGVzdElkcykpO1xuICAgIH0pO1xuICAgIHJldHVybiAoKSA9PiBkaXNwb3NhYmxlLmRpc3Bvc2UoKTtcbiAgfSwgW3J1blRlc3RzLCB0ZXN0U2VydmVyQ29ubmVjdGlvbiwgd2F0Y2hBbGwsIHdhdGNoZWRUcmVlSWRzLCB0ZWxlU3VpdGVVcGRhdGVyLCBwcm9qZWN0RmlsdGVycywgbWVyZ2VGaWxlc10pO1xuXG4gIC8vIFNob3J0Y3V0cy5cbiAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIXRlc3RTZXJ2ZXJDb25uZWN0aW9uKVxuICAgICAgcmV0dXJuO1xuICAgIGNvbnN0IG9uU2hvcnRjdXRFdmVudCA9IChlOiBLZXlib2FyZEV2ZW50KSA9PiB7XG4gICAgICBpZiAoZS5jb2RlID09PSAnQmFja3F1b3RlJyAmJiBlLmN0cmxLZXkpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBzZXRJc1Nob3dpbmdPdXRwdXQoIWlzU2hvd2luZ091dHB1dCk7XG4gICAgICB9IGVsc2UgaWYgKGUuY29kZSA9PT0gJ0Y1JyAmJiBlLnNoaWZ0S2V5KSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGVzdFNlcnZlckNvbm5lY3Rpb24/LnN0b3BUZXN0c05vUmVwbHkoe30pO1xuICAgICAgfSBlbHNlIGlmIChlLmNvZGUgPT09ICdGNScpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBydW5UZXN0cygnYm91bmNlLWlmLWJ1c3knLCB2aXNpYmxlVGVzdElkcyk7XG4gICAgICB9XG4gICAgfTtcbiAgICBhZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgb25TaG9ydGN1dEV2ZW50KTtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIG9uU2hvcnRjdXRFdmVudCk7XG4gICAgfTtcbiAgfSwgW3J1blRlc3RzLCByZWxvYWRUZXN0cywgdGVzdFNlcnZlckNvbm5lY3Rpb24sIHZpc2libGVUZXN0SWRzLCBpc1Nob3dpbmdPdXRwdXRdKTtcblxuICBjb25zdCBkaWFsb2dSZWYgPSBSZWFjdC51c2VSZWY8SFRNTERpYWxvZ0VsZW1lbnQ+KG51bGwpO1xuICBjb25zdCBvcGVuSW5zdGFsbERpYWxvZyA9IFJlYWN0LnVzZUNhbGxiYWNrKChlOiBSZWFjdC5Nb3VzZUV2ZW50KSA9PiB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZGlhbG9nUmVmLmN1cnJlbnQ/LnNob3dNb2RhbCgpO1xuICB9LCBbXSk7XG4gIGNvbnN0IGNsb3NlSW5zdGFsbERpYWxvZyA9IFJlYWN0LnVzZUNhbGxiYWNrKChlOiBSZWFjdC5Nb3VzZUV2ZW50KSA9PiB7XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgZGlhbG9nUmVmLmN1cnJlbnQ/LmNsb3NlKCk7XG4gIH0sIFtdKTtcbiAgY29uc3QgaW5zdGFsbEJyb3dzZXJzID0gUmVhY3QudXNlQ2FsbGJhY2soKGU6IFJlYWN0Lk1vdXNlRXZlbnQpID0+IHtcbiAgICBjbG9zZUluc3RhbGxEaWFsb2coZSk7XG4gICAgc2V0SXNTaG93aW5nT3V0cHV0KHRydWUpO1xuICAgIHRlc3RTZXJ2ZXJDb25uZWN0aW9uPy5pbnN0YWxsQnJvd3NlcnMoe30pLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgc2V0SXNTaG93aW5nT3V0cHV0KGZhbHNlKTtcbiAgICAgIGNvbnN0IHsgaGFzQnJvd3NlcnMgfSA9IGF3YWl0IHRlc3RTZXJ2ZXJDb25uZWN0aW9uPy5jaGVja0Jyb3dzZXJzKHt9KTtcbiAgICAgIHNldEhhc0Jyb3dzZXJzKGhhc0Jyb3dzZXJzKTtcbiAgICB9KTtcbiAgfSwgW2Nsb3NlSW5zdGFsbERpYWxvZywgdGVzdFNlcnZlckNvbm5lY3Rpb25dKTtcblxuICByZXR1cm4gPGRpdiBjbGFzc05hbWU9J3Zib3ggdWktbW9kZSc+XG4gICAgeyFoYXNCcm93c2VycyAmJiA8ZGlhbG9nIHJlZj17ZGlhbG9nUmVmfT5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPSd0aXRsZSc+PHNwYW4gY2xhc3NOYW1lPSdjb2RpY29uIGNvZGljb24tbGlnaHRidWxiJz48L3NwYW4+SW5zdGFsbCBicm93c2VyczwvZGl2PlxuICAgICAgPGRpdiBjbGFzc05hbWU9J2JvZHknPlxuICAgICAgICBQbGF5d3JpZ2h0IGRpZCBub3QgZmluZCBpbnN0YWxsZWQgYnJvd3NlcnMuXG4gICAgICAgIDxicj48L2JyPlxuICAgICAgICBXb3VsZCB5b3UgbGlrZSB0byBydW4gYHBsYXl3cmlnaHQgaW5zdGFsbGA/XG4gICAgICAgIDxicj48L2JyPlxuICAgICAgICA8YnV0dG9uIGNsYXNzTmFtZT0nYnV0dG9uJyBvbkNsaWNrPXtpbnN0YWxsQnJvd3NlcnN9Pkluc3RhbGw8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBjbGFzc05hbWU9J2J1dHRvbiBzZWNvbmRhcnknIG9uQ2xpY2s9e2Nsb3NlSW5zdGFsbERpYWxvZ30+RGlzbWlzczwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaWFsb2c+fVxuICAgIHtpc0Rpc2Nvbm5lY3RlZCAmJiA8ZGl2IGNsYXNzTmFtZT0nZGlzY29ubmVjdGVkJz5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPSd0aXRsZSc+VUkgTW9kZSBkaXNjb25uZWN0ZWQ8L2Rpdj5cbiAgICAgIDxkaXY+PGEgaHJlZj0nIycgb25DbGljaz17KCkgPT4gd2luZG93LmxvY2F0aW9uLmhyZWYgPSAnLyd9PlJlbG9hZCB0aGUgcGFnZTwvYT4gdG8gcmVjb25uZWN0PC9kaXY+XG4gICAgPC9kaXY+fVxuICAgIDxTcGxpdFZpZXdcbiAgICAgIHNpZGViYXJTaXplPXsyNTB9XG4gICAgICBtaW5TaWRlYmFyU2l6ZT17MTUwfVxuICAgICAgb3JpZW50YXRpb249J2hvcml6b250YWwnXG4gICAgICBzaWRlYmFySXNGaXJzdD17dHJ1ZX1cbiAgICAgIHNldHRpbmdOYW1lPSd0ZXN0TGlzdFNpZGViYXInXG4gICAgICBtYWluPXs8ZGl2IGNsYXNzTmFtZT0ndmJveCc+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPXtjbHN4KCd2Ym94JywgIWlzU2hvd2luZ091dHB1dCAmJiAnaGlkZGVuJyl9PlxuICAgICAgICAgIDxUb29sYmFyPlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9J3NlY3Rpb24tdGl0bGUnIHN0eWxlPXt7IGZsZXg6ICdub25lJyB9fT5PdXRwdXQ8L2Rpdj5cbiAgICAgICAgICAgIDxUb29sYmFyQnV0dG9uIGljb249J2NpcmNsZS1zbGFzaCcgdGl0bGU9J0NsZWFyIG91dHB1dCcgb25DbGljaz17KCkgPT4geyB4dGVybURhdGFTb3VyY2UuY2xlYXIoKTsgc2V0T3V0cHV0Q29udGFpbnNFcnJvcihmYWxzZSk7IH19PjwvVG9vbGJhckJ1dHRvbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSdzcGFjZXInPjwvZGl2PlxuICAgICAgICAgICAgPFRvb2xiYXJCdXR0b24gaWNvbj0nY2xvc2UnIHRpdGxlPSdDbG9zZScgb25DbGljaz17KCkgPT4gc2V0SXNTaG93aW5nT3V0cHV0KGZhbHNlKX0+PC9Ub29sYmFyQnV0dG9uPlxuICAgICAgICAgIDwvVG9vbGJhcj5cbiAgICAgICAgICA8WHRlcm1XcmFwcGVyIHNvdXJjZT17eHRlcm1EYXRhU291cmNlfT48L1h0ZXJtV3JhcHBlcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPXtjbHN4KCd2Ym94JywgaXNTaG93aW5nT3V0cHV0ICYmICdoaWRkZW4nKX0+XG4gICAgICAgICAgPFRyYWNlVmlld1xuICAgICAgICAgICAgcGF0aFNlcGFyYXRvcj17cXVlcnlQYXJhbXMucGF0aFNlcGFyYXRvcn1cbiAgICAgICAgICAgIGl0ZW09e3NlbGVjdGVkSXRlbX1cbiAgICAgICAgICAgIHJvb3REaXI9e3Rlc3RNb2RlbD8uY29uZmlnPy5yb290RGlyfVxuICAgICAgICAgICAgcmV2ZWFsU291cmNlPXtyZXZlYWxTb3VyY2V9XG4gICAgICAgICAgICBvbk9wZW5FeHRlcm5hbGx5PXtsb2NhdGlvbiA9PiB0ZXN0U2VydmVyQ29ubmVjdGlvbj8ub3Blbk5vUmVwbHkoeyBsb2NhdGlvbjogeyBmaWxlOiBsb2NhdGlvbi5maWxlLCBsaW5lOiBsb2NhdGlvbi5saW5lLCBjb2x1bW46IGxvY2F0aW9uLmNvbHVtbiB9IH0pfVxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+fVxuICAgICAgc2lkZWJhcj17PGRpdiBjbGFzc05hbWU9J3Zib3ggdWktbW9kZS1zaWRlYmFyJz5cbiAgICAgICAgPFRvb2xiYXIgbm9TaGFkb3c9e3RydWV9IG5vTWluSGVpZ2h0PXt0cnVlfT5cbiAgICAgICAgICA8aW1nIHNyYz0ncGxheXdyaWdodC1sb2dvLnN2ZycgYWx0PSdQbGF5d3JpZ2h0IGxvZ28nIC8+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9J3NlY3Rpb24tdGl0bGUnPlBsYXl3cmlnaHQ8L2Rpdj5cbiAgICAgICAgICA8VG9vbGJhckJ1dHRvbiBpY29uPSdyZWZyZXNoJyB0aXRsZT0nUmVsb2FkJyBvbkNsaWNrPXsoKSA9PiByZWxvYWRUZXN0cygpfSBkaXNhYmxlZD17aXNSdW5uaW5nVGVzdCB8fCBpc0xvYWRpbmd9PjwvVG9vbGJhckJ1dHRvbj5cbiAgICAgICAgICA8ZGl2IHN0eWxlPXt7IHBvc2l0aW9uOiAncmVsYXRpdmUnIH19PlxuICAgICAgICAgICAgPFRvb2xiYXJCdXR0b24gaWNvbj17J3Rlcm1pbmFsJ30gdGl0bGU9eydUb2dnbGUgb3V0cHV0IOKAlCAnICsgKGlzTWFjID8gJ+KMg2AnIDogJ0N0cmwgKyBgJyl9IHRvZ2dsZWQ9e2lzU2hvd2luZ091dHB1dH0gb25DbGljaz17KCkgPT4geyBzZXRJc1Nob3dpbmdPdXRwdXQoIWlzU2hvd2luZ091dHB1dCk7IH19IC8+XG4gICAgICAgICAgICB7b3V0cHV0Q29udGFpbnNFcnJvciAmJiA8ZGl2IHRpdGxlPSdPdXRwdXQgY29udGFpbnMgZXJyb3InIHN0eWxlPXt7IHBvc2l0aW9uOiAnYWJzb2x1dGUnLCB0b3A6IDIsIHJpZ2h0OiAyLCB3aWR0aDogNywgaGVpZ2h0OiA3LCBib3JkZXJSYWRpdXM6ICc1MCUnLCBiYWNrZ3JvdW5kQ29sb3I6ICd2YXIoLS12c2NvZGUtbm90aWZpY2F0aW9uc0Vycm9ySWNvbi1mb3JlZ3JvdW5kKScgfX0gLz59XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgeyFoYXNCcm93c2VycyAmJiA8VG9vbGJhckJ1dHRvbiBpY29uPSdsaWdodGJ1bGItYXV0b2ZpeCcgc3R5bGU9e3sgY29sb3I6ICd2YXIoLS12c2NvZGUtbGlzdC13YXJuaW5nRm9yZWdyb3VuZCknIH19IHRpdGxlPSdQbGF5d3JpZ2h0IGJyb3dzZXJzIGFyZSBtaXNzaW5nJyBvbkNsaWNrPXtvcGVuSW5zdGFsbERpYWxvZ30gLz59XG4gICAgICAgIDwvVG9vbGJhcj5cbiAgICAgICAgPEZpbHRlcnNWaWV3XG4gICAgICAgICAgZmlsdGVyVGV4dD17ZmlsdGVyVGV4dH1cbiAgICAgICAgICBzZXRGaWx0ZXJUZXh0PXtzZXRGaWx0ZXJUZXh0fVxuICAgICAgICAgIHN0YXR1c0ZpbHRlcnM9e3N0YXR1c0ZpbHRlcnN9XG4gICAgICAgICAgc2V0U3RhdHVzRmlsdGVycz17c2V0U3RhdHVzRmlsdGVyc31cbiAgICAgICAgICBwcm9qZWN0RmlsdGVycz17cHJvamVjdEZpbHRlcnN9XG4gICAgICAgICAgc2V0UHJvamVjdEZpbHRlcnM9e3NldFByb2plY3RGaWx0ZXJzfVxuICAgICAgICAgIHRlc3RNb2RlbD17dGVzdE1vZGVsfVxuICAgICAgICAgIHJ1blRlc3RzPXsoKSA9PiBydW5UZXN0cygnYm91bmNlLWlmLWJ1c3knLCB2aXNpYmxlVGVzdElkcyl9IC8+XG4gICAgICAgIDxUb29sYmFyIGNsYXNzTmFtZT0nc2VjdGlvbi10b29sYmFyJyBub01pbkhlaWdodD17dHJ1ZX0+XG4gICAgICAgICAgeyFpc1J1bm5pbmdUZXN0ICYmICFwcm9ncmVzcyAmJiA8ZGl2IGNsYXNzTmFtZT0nc2VjdGlvbi10aXRsZSc+VGVzdHM8L2Rpdj59XG4gICAgICAgICAgeyFpc1J1bm5pbmdUZXN0ICYmIHByb2dyZXNzICYmIDxkaXYgZGF0YS10ZXN0aWQ9J3N0YXR1cy1saW5lJyBjbGFzc05hbWU9J3N0YXR1cy1saW5lJz5cbiAgICAgICAgICAgIDxkaXY+e3Byb2dyZXNzLnBhc3NlZH0ve3Byb2dyZXNzLnRvdGFsfSBwYXNzZWQgKHsocHJvZ3Jlc3MucGFzc2VkIC8gcHJvZ3Jlc3MudG90YWwpICogMTAwIHwgMH0lKTwvZGl2PlxuICAgICAgICAgIDwvZGl2Pn1cbiAgICAgICAgICB7aXNSdW5uaW5nVGVzdCAmJiBwcm9ncmVzcyAmJiA8ZGl2IGRhdGEtdGVzdGlkPSdzdGF0dXMtbGluZScgY2xhc3NOYW1lPSdzdGF0dXMtbGluZSc+XG4gICAgICAgICAgICA8ZGl2PlJ1bm5pbmcge3Byb2dyZXNzLnBhc3NlZH0ve3J1bm5pbmdTdGF0ZS50ZXN0SWRzLnNpemV9IHBhc3NlZCAoeyhwcm9ncmVzcy5wYXNzZWQgLyBydW5uaW5nU3RhdGUudGVzdElkcy5zaXplKSAqIDEwMCB8IDB9JSk8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj59XG4gICAgICAgICAgPFRvb2xiYXJCdXR0b24gaWNvbj0ncGxheScgdGl0bGU9J1J1biBhbGwg4oCUIEY1JyBvbkNsaWNrPXsoKSA9PiBydW5UZXN0cygnYm91bmNlLWlmLWJ1c3knLCB2aXNpYmxlVGVzdElkcyl9IGRpc2FibGVkPXtpc1J1bm5pbmdUZXN0IHx8IGlzTG9hZGluZ30+PC9Ub29sYmFyQnV0dG9uPlxuICAgICAgICAgIDxUb29sYmFyQnV0dG9uIGljb249J2RlYnVnLXN0b3AnIHRpdGxlPXsnU3RvcCDigJQgJyArIChpc01hYyA/ICfih6dGNScgOiAnU2hpZnQgKyBGNScpfSBvbkNsaWNrPXsoKSA9PiB0ZXN0U2VydmVyQ29ubmVjdGlvbj8uc3RvcFRlc3RzKHt9KX0gZGlzYWJsZWQ9eyFpc1J1bm5pbmdUZXN0IHx8IGlzTG9hZGluZ30+PC9Ub29sYmFyQnV0dG9uPlxuICAgICAgICAgIDxUb29sYmFyQnV0dG9uIGljb249J2V5ZScgdGl0bGU9J1dhdGNoIGFsbCcgdG9nZ2xlZD17d2F0Y2hBbGx9IG9uQ2xpY2s9eygpID0+IHtcbiAgICAgICAgICAgIHNldFdhdGNoZWRUcmVlSWRzKHsgdmFsdWU6IG5ldyBTZXQoKSB9KTtcbiAgICAgICAgICAgIHNldFdhdGNoQWxsKCF3YXRjaEFsbCk7XG4gICAgICAgICAgfX0+PC9Ub29sYmFyQnV0dG9uPlxuICAgICAgICAgIDxUb29sYmFyQnV0dG9uIGljb249J2NvbGxhcHNlLWFsbCcgdGl0bGU9J0NvbGxhcHNlIGFsbCcgb25DbGljaz17KCkgPT4ge1xuICAgICAgICAgICAgc2V0Q29sbGFwc2VBbGxDb3VudChjb2xsYXBzZUFsbENvdW50ICsgMSk7XG4gICAgICAgICAgfX0gLz5cbiAgICAgICAgICA8VG9vbGJhckJ1dHRvbiBpY29uPSdleHBhbmQtYWxsJyB0aXRsZT0nRXhwYW5kIGFsbCcgb25DbGljaz17KCkgPT4ge1xuICAgICAgICAgICAgc2V0RXhwYW5kQWxsQ291bnQoZXhwYW5kQWxsQ291bnQgKyAxKTtcbiAgICAgICAgICB9fSAvPlxuICAgICAgICA8L1Rvb2xiYXI+XG4gICAgICAgIDxUZXN0TGlzdFZpZXdcbiAgICAgICAgICBmaWx0ZXJUZXh0PXtmaWx0ZXJUZXh0fVxuICAgICAgICAgIHRlc3RNb2RlbD17dGVzdE1vZGVsfVxuICAgICAgICAgIHRlc3RUcmVlPXt0ZXN0VHJlZX1cbiAgICAgICAgICB0ZXN0U2VydmVyQ29ubmVjdGlvbj17dGVzdFNlcnZlckNvbm5lY3Rpb259XG4gICAgICAgICAgcnVubmluZ1N0YXRlPXtydW5uaW5nU3RhdGV9XG4gICAgICAgICAgcnVuVGVzdHM9e3J1blRlc3RzfVxuICAgICAgICAgIG9uSXRlbVNlbGVjdGVkPXtzZXRTZWxlY3RlZEl0ZW19XG4gICAgICAgICAgd2F0Y2hBbGw9e3dhdGNoQWxsfVxuICAgICAgICAgIHdhdGNoZWRUcmVlSWRzPXt3YXRjaGVkVHJlZUlkc31cbiAgICAgICAgICBzZXRXYXRjaGVkVHJlZUlkcz17c2V0V2F0Y2hlZFRyZWVJZHN9XG4gICAgICAgICAgaXNMb2FkaW5nPXtpc0xvYWRpbmd9XG4gICAgICAgICAgcmVxdWVzdGVkQ29sbGFwc2VBbGxDb3VudD17Y29sbGFwc2VBbGxDb3VudH1cbiAgICAgICAgICByZXF1ZXN0ZWRFeHBhbmRBbGxDb3VudD17ZXhwYW5kQWxsQ291bnR9XG4gICAgICAgICAgc2V0RmlsdGVyVGV4dD17c2V0RmlsdGVyVGV4dH1cbiAgICAgICAgICBvblJldmVhbFNvdXJjZT17b25SZXZlYWxTb3VyY2V9XG4gICAgICAgIC8+XG4gICAgICAgIDxUb29sYmFyIG5vU2hhZG93PXt0cnVlfSBub01pbkhlaWdodD17dHJ1ZX0gY2xhc3NOYW1lPSdzZXR0aW5ncy10b29sYmFyJyBvbkNsaWNrPXsoKSA9PiBzZXRUZXN0aW5nT3B0aW9uc1Zpc2libGUoIXRlc3RpbmdPcHRpb25zVmlzaWJsZSl9PlxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICBjbGFzc05hbWU9e2Bjb2RpY29uIGNvZGljb24tJHt0ZXN0aW5nT3B0aW9uc1Zpc2libGUgPyAnY2hldnJvbi1kb3duJyA6ICdjaGV2cm9uLXJpZ2h0J31gfVxuICAgICAgICAgICAgc3R5bGU9e3sgbWFyZ2luTGVmdDogNSB9fVxuICAgICAgICAgICAgdGl0bGU9e3Rlc3RpbmdPcHRpb25zVmlzaWJsZSA/ICdIaWRlIFRlc3RpbmcgT3B0aW9ucycgOiAnU2hvdyBUZXN0aW5nIE9wdGlvbnMnfVxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9J3NlY3Rpb24tdGl0bGUnPlRlc3RpbmcgT3B0aW9uczwvZGl2PlxuICAgICAgICA8L1Rvb2xiYXI+XG4gICAgICAgIHt0ZXN0aW5nT3B0aW9uc1Zpc2libGUgJiYgPFNldHRpbmdzVmlldyBzZXR0aW5ncz17W1xuICAgICAgICAgIHsgdHlwZTogJ2NoZWNrJywgdmFsdWU6IHNpbmdsZVdvcmtlciwgc2V0OiBzZXRTaW5nbGVXb3JrZXIsIG5hbWU6ICdTaW5nbGUgd29ya2VyJyB9LFxuICAgICAgICAgIHsgdHlwZTogJ3NlbGVjdCcsIG9wdGlvbnM6IFtcbiAgICAgICAgICAgIHsgbGFiZWw6ICdBbGwnLCB2YWx1ZTogJ2FsbCcgfSxcbiAgICAgICAgICAgIHsgbGFiZWw6ICdDaGFuZ2VkJywgdmFsdWU6ICdjaGFuZ2VkJyB9LFxuICAgICAgICAgICAgeyBsYWJlbDogJ01pc3NpbmcnLCB2YWx1ZTogJ21pc3NpbmcnIH0sXG4gICAgICAgICAgICB7IGxhYmVsOiAnTm9uZScsIHZhbHVlOiAnbm9uZScgfSxcbiAgICAgICAgICBdLCB2YWx1ZTogdXBkYXRlU25hcHNob3RzLCBzZXQ6IHNldFVwZGF0ZVNuYXBzaG90cyBhcyAodmFsdWU6IHN0cmluZykgPT4gdm9pZCwgbmFtZTogJ1VwZGF0ZSBzbmFwc2hvdHMnIH0sXG4gICAgICAgIF19IC8+fVxuICAgICAgICA8VG9vbGJhciBub1NoYWRvdz17dHJ1ZX0gbm9NaW5IZWlnaHQ9e3RydWV9IGNsYXNzTmFtZT0nc2V0dGluZ3MtdG9vbGJhcicgb25DbGljaz17KCkgPT4gc2V0U2V0dGluZ3NWaXNpYmxlKCFzZXR0aW5nc1Zpc2libGUpfT5cbiAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgY2xhc3NOYW1lPXtgY29kaWNvbiBjb2RpY29uLSR7c2V0dGluZ3NWaXNpYmxlID8gJ2NoZXZyb24tZG93bicgOiAnY2hldnJvbi1yaWdodCd9YH1cbiAgICAgICAgICAgIHN0eWxlPXt7IG1hcmdpbkxlZnQ6IDUgfX1cbiAgICAgICAgICAgIHRpdGxlPXtzZXR0aW5nc1Zpc2libGUgPyAnSGlkZSBTZXR0aW5ncycgOiAnU2hvdyBTZXR0aW5ncyd9XG4gICAgICAgICAgLz5cbiAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT0nc2VjdGlvbi10aXRsZSc+U2V0dGluZ3M8L2Rpdj5cbiAgICAgICAgPC9Ub29sYmFyPlxuICAgICAgICB7c2V0dGluZ3NWaXNpYmxlICYmIDxEZWZhdWx0U2V0dGluZ3NWaWV3IGxvY2F0aW9uPSd1aS1tb2RlJyAvPn1cbiAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgIC8+XG4gIDwvZGl2Pjtcbn07XG4iLCIvKipcbiAqIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgJ0B3ZWIvY29tbW9uLmNzcyc7XG5pbXBvcnQgeyBhcHBseVRoZW1lIH0gZnJvbSAnQHdlYi90aGVtZSc7XG5pbXBvcnQgJ0B3ZWIvdGhpcmRfcGFydHkvdnNjb2RlL2NvZGljb24uY3NzJztcbmltcG9ydCAqIGFzIFJlYWN0RE9NIGZyb20gJ3JlYWN0LWRvbS9jbGllbnQnO1xuaW1wb3J0IHsgVUlNb2RlVmlldyB9IGZyb20gJy4vdWkvdWlNb2RlVmlldyc7XG5cbihhc3luYyAoKSA9PiB7XG4gIGFwcGx5VGhlbWUoKTtcbiAgaWYgKHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCAhPT0gJ2ZpbGU6Jykge1xuICAgIGlmICh3aW5kb3cubG9jYXRpb24uaHJlZi5pbmNsdWRlcygnaXNVbmRlclRlc3Q9dHJ1ZScpKVxuICAgICAgYXdhaXQgbmV3IFByb21pc2UoZiA9PiBzZXRUaW1lb3V0KGYsIDEwMDApKTtcbiAgICBpZiAoIW5hdmlnYXRvci5zZXJ2aWNlV29ya2VyKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTZXJ2aWNlIHdvcmtlcnMgYXJlIG5vdCBzdXBwb3J0ZWQuXFxuTWFrZSBzdXJlIHRvIHNlcnZlIHRoZSB3ZWJzaXRlICgke3dpbmRvdy5sb2NhdGlvbn0pIHZpYSBIVFRQUyBvciBsb2NhbGhvc3QuYCk7XG4gICAgbmF2aWdhdG9yLnNlcnZpY2VXb3JrZXIucmVnaXN0ZXIoJ3N3LmJ1bmRsZS5qcycpO1xuICAgIGlmICghbmF2aWdhdG9yLnNlcnZpY2VXb3JrZXIuY29udHJvbGxlcikge1xuICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oZiA9PiB7XG4gICAgICAgIG5hdmlnYXRvci5zZXJ2aWNlV29ya2VyLm9uY29udHJvbGxlcmNoYW5nZSA9ICgpID0+IGYoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEtlZXAgU1cgcnVubmluZy5cbiAgICBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHsgZmV0Y2goJ3BpbmcnKTsgfSwgMTAwMDApO1xuICB9XG5cbiAgUmVhY3RET00uY3JlYXRlUm9vdChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcm9vdCcpISkucmVuZGVyKDxVSU1vZGVWaWV3Lz4pO1xufSkoKTtcbiJdLCJmaWxlIjoidWlNb2RlLkNJV0YyM3NpLmpzIn0=