@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.
- package/ThirdPartyNotices.txt +3223 -308
- package/browsers.json +21 -22
- package/lib/cli/program.js +4 -5
- package/lib/client/api.js +3 -0
- package/lib/client/browser.js +3 -5
- package/lib/client/browserContext.js +35 -0
- package/lib/client/browserType.js +4 -3
- package/lib/client/channelOwner.js +4 -3
- package/lib/client/clientInstrumentation.js +10 -0
- package/lib/client/connection.js +4 -0
- package/lib/client/elementHandle.js +3 -0
- package/lib/client/events.js +3 -0
- package/lib/client/fetch.js +3 -4
- package/lib/client/frame.js +1 -0
- package/lib/client/page.js +28 -1
- package/lib/client/pageAgent.js +64 -0
- package/lib/client/platform.js +3 -0
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/mcpBundle.js +84 -0
- package/lib/mcpBundleImpl/index.js +147 -0
- package/lib/protocol/serializers.js +5 -0
- package/lib/protocol/validator.js +92 -3
- package/lib/remote/playwrightServer.js +1 -2
- package/lib/server/agent/actionRunner.js +335 -0
- package/lib/server/agent/actions.js +128 -0
- package/lib/server/agent/codegen.js +111 -0
- package/lib/server/agent/context.js +150 -0
- package/lib/server/agent/expectTools.js +156 -0
- package/lib/server/agent/pageAgent.js +204 -0
- package/lib/server/agent/performTools.js +262 -0
- package/lib/server/agent/tool.js +109 -0
- package/lib/server/artifact.js +1 -1
- package/lib/server/bidi/bidiBrowser.js +56 -12
- package/lib/server/bidi/bidiChromium.js +6 -11
- package/lib/server/bidi/bidiConnection.js +1 -0
- package/lib/server/bidi/bidiDeserializer.js +116 -0
- package/lib/server/bidi/bidiExecutionContext.js +75 -29
- package/lib/server/bidi/bidiFirefox.js +6 -8
- package/lib/server/bidi/bidiNetworkManager.js +1 -1
- package/lib/server/bidi/bidiPage.js +39 -28
- package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
- package/lib/server/browserContext.js +32 -25
- package/lib/server/browserType.js +12 -4
- package/lib/server/chromium/chromium.js +14 -21
- package/lib/server/chromium/chromiumSwitches.js +2 -2
- package/lib/server/chromium/crBrowser.js +22 -12
- package/lib/server/chromium/crConnection.js +0 -5
- package/lib/server/chromium/crDevTools.js +0 -2
- package/lib/server/chromium/crNetworkManager.js +43 -2
- package/lib/server/chromium/crPage.js +19 -87
- package/lib/server/codegen/javascript.js +6 -29
- package/lib/server/deviceDescriptorsSource.json +56 -56
- package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
- package/lib/server/dispatchers/dispatcher.js +6 -13
- package/lib/server/dispatchers/frameDispatcher.js +1 -1
- package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
- package/lib/server/dispatchers/pageDispatcher.js +4 -0
- package/lib/server/dom.js +12 -3
- package/lib/server/electron/electron.js +5 -2
- package/lib/server/firefox/ffBrowser.js +10 -20
- package/lib/server/firefox/ffConnection.js +0 -5
- package/lib/server/firefox/ffNetworkManager.js +2 -2
- package/lib/server/firefox/ffPage.js +15 -18
- package/lib/server/firefox/firefox.js +6 -8
- package/lib/server/frameSelectors.js +9 -3
- package/lib/server/frames.js +49 -33
- package/lib/server/instrumentation.js +3 -0
- package/lib/server/network.js +50 -12
- package/lib/server/page.js +33 -89
- package/lib/server/progress.js +26 -6
- package/lib/server/recorder/recorderApp.js +79 -100
- package/lib/server/recorder.js +55 -0
- package/lib/server/registry/browserFetcher.js +6 -4
- package/lib/server/registry/index.js +172 -149
- package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
- package/lib/server/screencast.js +190 -0
- package/lib/server/screenshotCompositor.js +153 -0
- package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
- package/lib/server/trace/recorder/tracing.js +21 -21
- package/lib/server/trace/viewer/traceParser.js +72 -0
- package/lib/server/trace/viewer/traceViewer.js +17 -13
- package/lib/server/utils/expectUtils.js +87 -2
- package/lib/server/utils/httpServer.js +4 -19
- package/lib/server/utils/network.js +37 -28
- package/lib/server/utils/nodePlatform.js +6 -0
- package/lib/server/videoRecorder.js +124 -0
- package/lib/server/webkit/webkit.js +4 -6
- package/lib/server/webkit/wkBrowser.js +2 -6
- package/lib/server/webkit/wkConnection.js +1 -6
- package/lib/server/webkit/wkInterceptableRequest.js +29 -1
- package/lib/server/webkit/wkPage.js +75 -46
- package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
- package/lib/utils/isomorphic/lruCache.js +51 -0
- package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
- package/lib/utils/isomorphic/stringUtils.js +49 -0
- package/lib/utils/isomorphic/trace/entries.js +16 -0
- package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
- package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
- package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
- package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
- package/lib/utils/isomorphic/trace/traceModel.js +365 -0
- package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
- package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
- package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
- package/lib/utils/isomorphic/yaml.js +84 -0
- package/lib/utils.js +2 -0
- package/lib/utilsBundle.js +2 -5
- package/lib/utilsBundleImpl/index.js +165 -165
- package/lib/vite/htmlReport/index.html +21 -21
- package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
- package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
- package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
- package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
- package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
- package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
- package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
- package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
- package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
- package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
- package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
- package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
- package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
- package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
- package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
- package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
- package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
- package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
- package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
- package/lib/vite/traceViewer/index.html +4 -4
- package/lib/vite/traceViewer/sw.bundle.js +5 -3
- package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
- package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
- package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
- package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
- package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
- package/lib/vite/traceViewer/uiMode.html +3 -3
- package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
- package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
- package/package.json +3 -1
- package/types/protocol.d.ts +738 -159
- package/types/types.d.ts +25 -38
- 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-JtyB0yzL.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+IGYoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEtlZXAgU1cgcnVubmluZy5cbiAgICBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHsgZmV0Y2goJ3BpbmcnKTsgfSwgMTAwMDApO1xuICB9XG5cbiAgUmVhY3RET00uY3JlYXRlUm9vdChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcm9vdCcpISkucmVuZGVyKDxVSU1vZGVWaWV3Lz4pO1xufSkoKTtcbiJdLCJmaWxlIjoidWlNb2RlLldpLUR2SUVZLmpzIn0=
|