1 | ;
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const path_1 = require("path");
|
7 | const debug_1 = __importDefault(require("debug"));
|
8 | const promisify_event_1 = __importDefault(require("promisify-event"));
|
9 | const map_reverse_1 = __importDefault(require("map-reverse"));
|
10 | const events_1 = require("events");
|
11 | const lodash_1 = require("lodash");
|
12 | const bootstrapper_1 = __importDefault(require("./bootstrapper"));
|
13 | const reporter_1 = __importDefault(require("../reporter"));
|
14 | const task_1 = __importDefault(require("./task"));
|
15 | const debug_logger_1 = __importDefault(require("../notifications/debug-logger"));
|
16 | const runtime_1 = require("../errors/runtime");
|
17 | const types_1 = require("../errors/types");
|
18 | const type_assertions_1 = require("../errors/runtime/type-assertions");
|
19 | const utils_1 = require("../errors/test-run/utils");
|
20 | const detect_ffmpeg_1 = __importDefault(require("../utils/detect-ffmpeg"));
|
21 | const check_file_path_1 = __importDefault(require("../utils/check-file-path"));
|
22 | const handle_errors_1 = require("../utils/handle-errors");
|
23 | const option_names_1 = __importDefault(require("../configuration/option-names"));
|
24 | const flag_list_1 = __importDefault(require("../utils/flag-list"));
|
25 | const prepare_reporters_1 = __importDefault(require("../utils/prepare-reporters"));
|
26 | const load_1 = __importDefault(require("../custom-client-scripts/load"));
|
27 | const utils_2 = require("../custom-client-scripts/utils");
|
28 | const string_1 = require("../utils/string");
|
29 | const DEBUG_LOGGER = debug_1.default('testcafe:runner');
|
30 | class Runner extends events_1.EventEmitter {
|
31 | constructor(proxy, browserConnectionGateway, configuration) {
|
32 | super();
|
33 | this.proxy = proxy;
|
34 | this.bootstrapper = this._createBootstrapper(browserConnectionGateway);
|
35 | this.pendingTaskPromises = [];
|
36 | this.configuration = configuration;
|
37 | this.isCli = false;
|
38 | this.apiMethodWasCalled = new flag_list_1.default([
|
39 | option_names_1.default.src,
|
40 | option_names_1.default.browsers,
|
41 | option_names_1.default.reporter,
|
42 | option_names_1.default.clientScripts
|
43 | ]);
|
44 | }
|
45 | _createBootstrapper(browserConnectionGateway) {
|
46 | return new bootstrapper_1.default(browserConnectionGateway);
|
47 | }
|
48 | _disposeBrowserSet(browserSet) {
|
49 | return browserSet.dispose().catch(e => DEBUG_LOGGER(e));
|
50 | }
|
51 | _disposeReporters(reporters) {
|
52 | return Promise.all(reporters.map(reporter => reporter.dispose().catch(e => DEBUG_LOGGER(e))));
|
53 | }
|
54 | _disposeTestedApp(testedApp) {
|
55 | return testedApp ? testedApp.kill().catch(e => DEBUG_LOGGER(e)) : Promise.resolve();
|
56 | }
|
57 | async _disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp) {
|
58 | task.abort();
|
59 | task.unRegisterClientScriptRouting();
|
60 | task.clearListeners();
|
61 | await this._disposeAssets(browserSet, reporters, testedApp);
|
62 | }
|
63 | _disposeAssets(browserSet, reporters, testedApp) {
|
64 | return Promise.all([
|
65 | this._disposeBrowserSet(browserSet),
|
66 | this._disposeReporters(reporters),
|
67 | this._disposeTestedApp(testedApp)
|
68 | ]);
|
69 | }
|
70 | _prepareArrayParameter(array) {
|
71 | array = lodash_1.flattenDeep(array);
|
72 | if (this.isCli)
|
73 | return array.length === 0 ? void 0 : array;
|
74 | return array;
|
75 | }
|
76 | _createCancelablePromise(taskPromise) {
|
77 | const promise = taskPromise.then(({ completionPromise }) => completionPromise);
|
78 | const removeFromPending = () => lodash_1.pull(this.pendingTaskPromises, promise);
|
79 | promise
|
80 | .then(removeFromPending)
|
81 | .catch(removeFromPending);
|
82 | promise.cancel = () => taskPromise
|
83 | .then(({ cancelTask }) => cancelTask())
|
84 | .then(removeFromPending);
|
85 | this.pendingTaskPromises.push(promise);
|
86 | return promise;
|
87 | }
|
88 | // Run task
|
89 | _getFailedTestCount(task, reporter) {
|
90 | let failedTestCount = reporter.testCount - reporter.passed;
|
91 | if (task.opts.stopOnFirstFail && !!failedTestCount)
|
92 | failedTestCount = 1;
|
93 | return failedTestCount;
|
94 | }
|
95 | async _getTaskResult(task, browserSet, reporters, testedApp) {
|
96 | task.on('browser-job-done', job => browserSet.releaseConnection(job.browserConnection));
|
97 | const browserSetErrorPromise = promisify_event_1.default(browserSet, 'error');
|
98 | const taskDonePromise = task.once('done')
|
99 | .then(() => browserSetErrorPromise.cancel())
|
100 | .then(() => {
|
101 | return Promise.all(reporters.map(reporter => reporter.pendingTaskDonePromise));
|
102 | });
|
103 | const promises = [
|
104 | taskDonePromise,
|
105 | browserSetErrorPromise
|
106 | ];
|
107 | if (testedApp)
|
108 | promises.push(testedApp.errorPromise);
|
109 | try {
|
110 | await Promise.race(promises);
|
111 | }
|
112 | catch (err) {
|
113 | await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
114 | throw err;
|
115 | }
|
116 | await this._disposeAssets(browserSet, reporters, testedApp);
|
117 | return this._getFailedTestCount(task, reporters[0]);
|
118 | }
|
119 | _createTask(tests, browserConnectionGroups, proxy, opts) {
|
120 | return new task_1.default(tests, browserConnectionGroups, proxy, opts);
|
121 | }
|
122 | _runTask(reporterPlugins, browserSet, tests, testedApp) {
|
123 | let completed = false;
|
124 | const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, this.configuration.getOptions());
|
125 | const reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, task, reporter.outStream));
|
126 | const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp);
|
127 | task.on('start', handle_errors_1.startHandlingTestErrors);
|
128 | if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
|
129 | task.on('test-run-start', handle_errors_1.addRunningTest);
|
130 | task.on('test-run-done', handle_errors_1.removeRunningTest);
|
131 | }
|
132 | task.on('done', handle_errors_1.stopHandlingTestErrors);
|
133 | const onTaskCompleted = () => {
|
134 | task.unRegisterClientScriptRouting();
|
135 | completed = true;
|
136 | };
|
137 | completionPromise
|
138 | .then(onTaskCompleted)
|
139 | .catch(onTaskCompleted);
|
140 | const cancelTask = async () => {
|
141 | if (!completed)
|
142 | await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
|
143 | };
|
144 | return { completionPromise, cancelTask };
|
145 | }
|
146 | _registerAssets(assets) {
|
147 | assets.forEach(asset => this.proxy.GET(asset.path, asset.info));
|
148 | }
|
149 | _validateDebugLogger() {
|
150 | const debugLogger = this.configuration.getOption(option_names_1.default.debugLogger);
|
151 | const debugLoggerDefinedCorrectly = debugLogger === null || !!debugLogger &&
|
152 | ['showBreakpoint', 'hideBreakpoint'].every(method => method in debugLogger && lodash_1.isFunction(debugLogger[method]));
|
153 | if (!debugLoggerDefinedCorrectly) {
|
154 | this.configuration.mergeOptions({
|
155 | [option_names_1.default.debugLogger]: debug_logger_1.default
|
156 | });
|
157 | }
|
158 | }
|
159 | _validateSpeedOption() {
|
160 | const speed = this.configuration.getOption(option_names_1.default.speed);
|
161 | if (speed === void 0)
|
162 | return;
|
163 | if (typeof speed !== 'number' || isNaN(speed) || speed < 0.01 || speed > 1)
|
164 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSpeedValue);
|
165 | }
|
166 | _validateConcurrencyOption() {
|
167 | const concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
168 | if (concurrency === void 0)
|
169 | return;
|
170 | if (typeof concurrency !== 'number' || isNaN(concurrency) || concurrency < 1)
|
171 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidConcurrencyFactor);
|
172 | }
|
173 | _validateProxyBypassOption() {
|
174 | let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
|
175 | if (proxyBypass === void 0)
|
176 | return;
|
177 | type_assertions_1.assertType([type_assertions_1.is.string, type_assertions_1.is.array], null, '"proxyBypass" argument', proxyBypass);
|
178 | if (typeof proxyBypass === 'string')
|
179 | proxyBypass = [proxyBypass];
|
180 | proxyBypass = proxyBypass.reduce((arr, rules) => {
|
181 | type_assertions_1.assertType(type_assertions_1.is.string, null, '"proxyBypass" argument', rules);
|
182 | return arr.concat(rules.split(','));
|
183 | }, []);
|
184 | this.configuration.mergeOptions({ proxyBypass });
|
185 | }
|
186 | _getScreenshotOptions() {
|
187 | let { path, pathPattern } = this.configuration.getOption(option_names_1.default.screenshots) || {};
|
188 | if (!path)
|
189 | path = this.configuration.getOption(option_names_1.default.screenshotPath);
|
190 | if (!pathPattern)
|
191 | pathPattern = this.configuration.getOption(option_names_1.default.screenshotPathPattern);
|
192 | return { path, pathPattern };
|
193 | }
|
194 | _validateScreenshotOptions() {
|
195 | const { path, pathPattern } = this._getScreenshotOptions();
|
196 | const disableScreenshots = this.configuration.getOption(option_names_1.default.disableScreenshots) || !path;
|
197 | this.configuration.mergeOptions({ [option_names_1.default.disableScreenshots]: disableScreenshots });
|
198 | if (disableScreenshots)
|
199 | return;
|
200 | if (path) {
|
201 | this._validateScreenshotPath(path, 'screenshots base directory path');
|
202 | this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { path: path_1.resolve(path) } });
|
203 | }
|
204 | if (pathPattern) {
|
205 | this._validateScreenshotPath(pathPattern, 'screenshots path pattern');
|
206 | this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPattern } });
|
207 | }
|
208 | }
|
209 | async _validateVideoOptions() {
|
210 | const videoPath = this.configuration.getOption(option_names_1.default.videoPath);
|
211 | const videoEncodingOptions = this.configuration.getOption(option_names_1.default.videoEncodingOptions);
|
212 | let videoOptions = this.configuration.getOption(option_names_1.default.videoOptions);
|
213 | if (!videoPath) {
|
214 | if (videoOptions || videoEncodingOptions)
|
215 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetVideoOptionsWithoutBaseVideoPathSpecified);
|
216 | return;
|
217 | }
|
218 | this.configuration.mergeOptions({ [option_names_1.default.videoPath]: path_1.resolve(videoPath) });
|
219 | if (!videoOptions) {
|
220 | videoOptions = {};
|
221 | this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
|
222 | }
|
223 | if (videoOptions.ffmpegPath)
|
224 | videoOptions.ffmpegPath = path_1.resolve(videoOptions.ffmpegPath);
|
225 | else
|
226 | videoOptions.ffmpegPath = await detect_ffmpeg_1.default();
|
227 | if (!videoOptions.ffmpegPath)
|
228 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
|
229 | }
|
230 | async _validateRunOptions() {
|
231 | this._validateDebugLogger();
|
232 | this._validateScreenshotOptions();
|
233 | await this._validateVideoOptions();
|
234 | this._validateSpeedOption();
|
235 | this._validateConcurrencyOption();
|
236 | this._validateProxyBypassOption();
|
237 | }
|
238 | _validateTestForAllowMultipleWindowsOption(tests) {
|
239 | if (tests.some(test => test.isLegacy))
|
240 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotUseAllowMultipleWindowsOptionForLegacyTests);
|
241 | }
|
242 | _validateBrowsersForAllowMultipleWindowsOption(browserSet) {
|
243 | const browserConnections = browserSet.browserConnectionGroups.map(browserConnectionGroup => browserConnectionGroup[0]);
|
244 | const unsupportedBrowserConnections = browserConnections.filter(browserConnection => !browserConnection.activeWindowId);
|
245 | if (!unsupportedBrowserConnections.length)
|
246 | return;
|
247 | const unsupportedBrowserAliases = unsupportedBrowserConnections.map(browserConnection => browserConnection.browserInfo.alias);
|
248 | const browserAliases = string_1.getConcatenatedValuesString(unsupportedBrowserAliases);
|
249 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotUseAllowMultipleWindowsOptionForSomeBrowsers, browserAliases);
|
250 | }
|
251 | _validateAllowMultipleWindowsOption(tests, browserSet) {
|
252 | const allowMultipleWindows = this.configuration.getOption(option_names_1.default.allowMultipleWindows);
|
253 | if (!allowMultipleWindows)
|
254 | return;
|
255 | this._validateTestForAllowMultipleWindowsOption(tests);
|
256 | this._validateBrowsersForAllowMultipleWindowsOption(browserSet);
|
257 | }
|
258 | _createRunnableConfiguration() {
|
259 | return this.bootstrapper
|
260 | .createRunnableConfiguration()
|
261 | .then(runnableConfiguration => {
|
262 | this.emit('done-bootstrapping');
|
263 | return runnableConfiguration;
|
264 | });
|
265 | }
|
266 | _validateScreenshotPath(screenshotPath, pathType) {
|
267 | const forbiddenCharsList = check_file_path_1.default(screenshotPath);
|
268 | if (forbiddenCharsList.length)
|
269 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, utils_1.renderForbiddenCharsList(forbiddenCharsList));
|
270 | }
|
271 | _setBootstrapperOptions() {
|
272 | this.configuration.prepare();
|
273 | this.configuration.notifyAboutOverriddenOptions();
|
274 | this.bootstrapper.sources = this.configuration.getOption(option_names_1.default.src) || this.bootstrapper.sources;
|
275 | this.bootstrapper.browsers = this.configuration.getOption(option_names_1.default.browsers) || this.bootstrapper.browsers;
|
276 | this.bootstrapper.concurrency = this.configuration.getOption(option_names_1.default.concurrency);
|
277 | this.bootstrapper.appCommand = this.configuration.getOption(option_names_1.default.appCommand) || this.bootstrapper.appCommand;
|
278 | this.bootstrapper.appInitDelay = this.configuration.getOption(option_names_1.default.appInitDelay);
|
279 | this.bootstrapper.filter = this.configuration.getOption(option_names_1.default.filter) || this.bootstrapper.filter;
|
280 | this.bootstrapper.reporters = this.configuration.getOption(option_names_1.default.reporter) || this.bootstrapper.reporters;
|
281 | this.bootstrapper.tsConfigPath = this.configuration.getOption(option_names_1.default.tsConfigPath);
|
282 | this.bootstrapper.clientScripts = this.configuration.getOption(option_names_1.default.clientScripts) || this.bootstrapper.clientScripts;
|
283 | this.bootstrapper.allowMultipleWindows = this.configuration.getOption(option_names_1.default.allowMultipleWindows) || this.bootstrapper.allowMultipleWindows;
|
284 | }
|
285 | // API
|
286 | embeddingOptions(opts) {
|
287 | const { assets, TestRunCtor } = opts;
|
288 | this._registerAssets(assets);
|
289 | this.configuration.mergeOptions({ TestRunCtor });
|
290 | return this;
|
291 | }
|
292 | src(...sources) {
|
293 | if (this.apiMethodWasCalled.src)
|
294 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
|
295 | sources = this._prepareArrayParameter(sources);
|
296 | this.configuration.mergeOptions({ [option_names_1.default.src]: sources });
|
297 | this.apiMethodWasCalled.src = true;
|
298 | return this;
|
299 | }
|
300 | browsers(...browsers) {
|
301 | if (this.apiMethodWasCalled.browsers)
|
302 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.browsers);
|
303 | browsers = this._prepareArrayParameter(browsers);
|
304 | this.configuration.mergeOptions({ browsers });
|
305 | this.apiMethodWasCalled.browsers = true;
|
306 | return this;
|
307 | }
|
308 | concurrency(concurrency) {
|
309 | this.configuration.mergeOptions({ concurrency });
|
310 | return this;
|
311 | }
|
312 | reporter(name, output) {
|
313 | if (this.apiMethodWasCalled.reporter)
|
314 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.reporter);
|
315 | let reporters = prepare_reporters_1.default(name, output);
|
316 | reporters = this._prepareArrayParameter(reporters);
|
317 | this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporters });
|
318 | this.apiMethodWasCalled.reporter = true;
|
319 | return this;
|
320 | }
|
321 | filter(filter) {
|
322 | this.configuration.mergeOptions({ filter });
|
323 | return this;
|
324 | }
|
325 | useProxy(proxy, proxyBypass) {
|
326 | this.configuration.mergeOptions({ proxy, proxyBypass });
|
327 | return this;
|
328 | }
|
329 | screenshots(...options) {
|
330 | let fullPage;
|
331 | let [path, takeOnFails, pathPattern] = options;
|
332 | if (options.length === 1 && options[0] && typeof options[0] === 'object')
|
333 | ({ path, takeOnFails, pathPattern, fullPage } = options[0]);
|
334 | this.configuration.mergeOptions({ screenshots: { path, takeOnFails, pathPattern, fullPage } });
|
335 | return this;
|
336 | }
|
337 | video(path, options, encodingOptions) {
|
338 | this.configuration.mergeOptions({
|
339 | [option_names_1.default.videoPath]: path,
|
340 | [option_names_1.default.videoOptions]: options,
|
341 | [option_names_1.default.videoEncodingOptions]: encodingOptions
|
342 | });
|
343 | return this;
|
344 | }
|
345 | startApp(command, initDelay) {
|
346 | this.configuration.mergeOptions({
|
347 | [option_names_1.default.appCommand]: command,
|
348 | [option_names_1.default.appInitDelay]: initDelay
|
349 | });
|
350 | return this;
|
351 | }
|
352 | tsConfigPath(path) {
|
353 | this.configuration.mergeOptions({
|
354 | [option_names_1.default.tsConfigPath]: path
|
355 | });
|
356 | return this;
|
357 | }
|
358 | clientScripts(...scripts) {
|
359 | if (this.apiMethodWasCalled.clientScripts)
|
360 | throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.clientScripts);
|
361 | scripts = this._prepareArrayParameter(scripts);
|
362 | this.configuration.mergeOptions({ [option_names_1.default.clientScripts]: scripts });
|
363 | this.apiMethodWasCalled.clientScripts = true;
|
364 | return this;
|
365 | }
|
366 | async _prepareClientScripts(tests, clientScripts) {
|
367 | return Promise.all(tests.map(async (test) => {
|
368 | if (test.isLegacy)
|
369 | return;
|
370 | let loadedTestClientScripts = await load_1.default(test.clientScripts, path_1.dirname(test.testFile.filename));
|
371 | loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
|
372 | test.clientScripts = utils_2.setUniqueUrls(loadedTestClientScripts);
|
373 | }));
|
374 | }
|
375 | run(options = {}) {
|
376 | this.apiMethodWasCalled.reset();
|
377 | this.configuration.mergeOptions(options);
|
378 | this._setBootstrapperOptions();
|
379 | const runTaskPromise = Promise.resolve()
|
380 | .then(() => this._validateRunOptions())
|
381 | .then(() => this._createRunnableConfiguration())
|
382 | .then(async ({ reporterPlugins, browserSet, tests, testedApp, commonClientScripts }) => {
|
383 | await this._prepareClientScripts(tests, commonClientScripts);
|
384 | this._validateAllowMultipleWindowsOption(tests, browserSet);
|
385 | return this._runTask(reporterPlugins, browserSet, tests, testedApp);
|
386 | });
|
387 | return this._createCancelablePromise(runTaskPromise);
|
388 | }
|
389 | async stop() {
|
390 | // NOTE: When taskPromise is cancelled, it is removed from
|
391 | // the pendingTaskPromises array, which leads to shifting indexes
|
392 | // towards the beginning. So, we must copy the array in order to iterate it,
|
393 | // or we can perform iteration from the end to the beginning.
|
394 | const cancellationPromises = map_reverse_1.default(this.pendingTaskPromises, taskPromise => taskPromise.cancel());
|
395 | await Promise.all(cancellationPromises);
|
396 | }
|
397 | }
|
398 | exports.default = Runner;
|
399 | module.exports = exports.default;
|
400 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVEO0FBQ3ZELGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsOERBQXFDO0FBQ3JDLG1DQUFzQztBQUN0QyxtQ0FBNEU7QUFDNUUsa0VBQTBDO0FBQzFDLDJEQUFtQztBQUNuQyxrREFBMEI7QUFDMUIsaUZBQStEO0FBQy9ELCtDQUFpRDtBQUNqRCwyQ0FBaUQ7QUFDakQsdUVBQW1FO0FBQ25FLG9EQUFvRTtBQUNwRSwyRUFBa0Q7QUFDbEQsK0VBQXFEO0FBQ3JELDBEQUE0SDtBQUM1SCxpRkFBeUQ7QUFDekQsbUVBQTBDO0FBQzFDLG1GQUEwRDtBQUMxRCx5RUFBOEQ7QUFDOUQsMERBQStEO0FBQy9ELDRDQUE4RDtBQUU5RCxNQUFNLFlBQVksR0FBRyxlQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUU5QyxNQUFxQixNQUFPLFNBQVEscUJBQVk7SUFDNUMsWUFBYSxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsYUFBYTtRQUN2RCxLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxLQUFLLEdBQWlCLEtBQUssQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFVLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzlFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLGFBQWEsR0FBUyxhQUFhLENBQUM7UUFDekMsSUFBSSxDQUFDLEtBQUssR0FBaUIsS0FBSyxDQUFDO1FBRWpDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLG1CQUFRLENBQUM7WUFDbkMsc0JBQVksQ0FBQyxHQUFHO1lBQ2hCLHNCQUFZLENBQUMsUUFBUTtZQUNyQixzQkFBWSxDQUFDLFFBQVE7WUFDckIsc0JBQVksQ0FBQyxhQUFhO1NBQzdCLENB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LENBQUM7YUFDdEMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyw0QkFBNEIsRUFBRSxDQUFDO2FBQy9DLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFO1lBQ25GLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1lBRTdELElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFFNUQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3hFLENBQUMsQ0FBQyxDQUFDO1FBRVAsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ04sMERBQTBEO1FBQzFELGlFQUFpRTtRQUNqRSw0RUFBNEU7UUFDNUUsNkRBQTZEO1FBQzdELE1BQU0sb0JBQW9CLEdBQUcscUJBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUV2RyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM1QyxDQUFDO0NBQ0o7QUE3ZkQseUJBNmZDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVzb2x2ZSBhcyByZXNvbHZlUGF0aCwgZGlybmFtZSB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IG1hcFJldmVyc2UgZnJvbSAnbWFwLXJldmVyc2UnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IGZsYXR0ZW5EZWVwIGFzIGZsYXR0ZW4sIHB1bGwgYXMgcmVtb3ZlLCBpc0Z1bmN0aW9uIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCb290c3RyYXBwZXIgZnJvbSAnLi9ib290c3RyYXBwZXInO1xuaW1wb3J0IFJlcG9ydGVyIGZyb20gJy4uL3JlcG9ydGVyJztcbmltcG9ydCBUYXNrIGZyb20gJy4vdGFzayc7XG5pbXBvcnQgZGVmYXVsdERlYnVnTG9nZ2VyIGZyb20gJy4uL25vdGlmaWNhdGlvbnMvZGVidWctbG9nZ2VyJztcbmltcG9ydCB7IEdlbmVyYWxFcnJvciB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IFJVTlRJTUVfRVJST1JTIH0gZnJvbSAnLi4vZXJyb3JzL3R5cGVzJztcbmltcG9ydCB7IGFzc2VydFR5cGUsIGlzIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUvdHlwZS1hc3NlcnRpb25zJztcbmltcG9ydCB7IHJlbmRlckZvcmJpZGRlbkNoYXJzTGlzdCB9IGZyb20gJy4uL2Vycm9ycy90ZXN0LXJ1bi91dGlscyc7XG5pbXBvcnQgZGV0ZWN0RkZNUEVHIGZyb20gJy4uL3V0aWxzL2RldGVjdC1mZm1wZWcnO1xuaW1wb3J0IGNoZWNrRmlsZVBhdGggZnJvbSAnLi4vdXRpbHMvY2hlY2stZmlsZS1wYXRoJztcbmltcG9ydCB7IGFkZFJ1bm5pbmdUZXN0LCByZW1vdmVSdW5uaW5nVGVzdCwgc3RhcnRIYW5kbGluZ1Rlc3RFcnJvcnMsIHN0b3BIYW5kbGluZ1Rlc3RFcnJvcnMgfSBmcm9tICcuLi91dGlscy9oYW5kbGUtZXJyb3JzJztcbmltcG9ydCBPUFRJT05fTkFNRVMgZnJvbSAnLi4vY29uZmlndXJhdGlvbi9vcHRpb24tbmFtZXMnO1xuaW1wb3J0IEZsYWdMaXN0IGZyb20gJy4uL3V0aWxzL2ZsYWctbGlzdCc7XG5pbXBvcnQgcHJlcGFyZVJlcG9ydGVycyBmcm9tICcuLi91dGlscy9wcmVwYXJlLXJlcG9ydGVycyc7XG5pbXBvcnQgbG9hZENsaWVudFNjcmlwdHMgZnJvbSAnLi4vY3VzdG9tLWNsaWVudC1zY3JpcHRzL2xvYWQnO1xuaW1wb3J0IHsgc2V0VW5pcXVlVXJscyB9IGZyb20gJy4uL2N1c3RvbS1jbGllbnQtc2NyaXB0cy91dGlscyc7XG5pbXBvcnQgeyBnZXRDb25jYXRlbmF0ZWRWYWx1ZXNTdHJpbmcgfSBmcm9tICcuLi91dGlscy9zdHJpbmcnO1xuXG5jb25zdCBERUJVR19MT0dHRVIgPSBkZWJ1ZygndGVzdGNhZmU6cnVubmVyJyk7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJ1bm5lciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gICAgY29uc3RydWN0b3IgKHByb3h5LCBicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbmZpZ3VyYXRpb24pIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLnByb3h5ICAgICAgICAgICAgICAgPSBwcm94eTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIgICAgICAgID0gdGhpcy5fY3JlYXRlQm9vdHN0cmFwcGVyKGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSk7XG4gICAgICAgIHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcyA9IFtdO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24gICAgICAgPSBjb25maWd1cmF0aW9uO1xuICAgICAgICB0aGlzLmlzQ2xpICAgICAgICAgICAgICAgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZCA9IG5ldyBGbGFnTGlzdChbXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuc3JjLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLmJyb3dzZXJzLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLnJlcG9ydGVyLFxuICAgICAgICAgICAgT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHNcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUJvb3RzdHJhcHBlciAoYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5KSB7XG4gICAgICAgIHJldHVybiBuZXcgQm9vdHN0cmFwcGVyKGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VCcm93c2VyU2V0IChicm93c2VyU2V0KSB7XG4gICAgICAgIHJldHVybiBicm93c2VyU2V0LmRpc3Bvc2UoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VSZXBvcnRlcnMgKHJlcG9ydGVycykge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5kaXNwb3NlKCkuY2F0Y2goZSA9PiBERUJVR19MT0dHRVIoZSkpKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VUZXN0ZWRBcHAgKHRlc3RlZEFwcCkge1xuICAgICAgICByZXR1cm4gdGVzdGVkQXBwID8gdGVzdGVkQXBwLmtpbGwoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSkgOiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZGlzcG9zZVRhc2tBbmRSZWxhdGVkQXNzZXRzICh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCkge1xuICAgICAgICB0YXNrLmFib3J0KCk7XG4gICAgICAgIHRhc2sudW5SZWdpc3RlckNsaWVudFNjcmlwdFJvdXRpbmcoKTtcbiAgICAgICAgdGFzay5jbGVhckxpc3RlbmVycygpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX2Rpc3Bvc2VBc3NldHMoYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuICAgIH1cblxuICAgIF9kaXNwb3NlQXNzZXRzIChicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZUJyb3dzZXJTZXQoYnJvd3NlclNldCksXG4gICAgICAgICAgICB0aGlzLl9kaXNwb3NlUmVwb3J0ZXJzKHJlcG9ydGVycyksXG4gICAgICAgICAgICB0aGlzLl9kaXNwb3NlVGVzdGVkQXBwKHRlc3RlZEFwcClcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgX3ByZXBhcmVBcnJheVBhcmFtZXRlciAoYXJyYXkpIHtcbiAgICAgICAgYXJyYXkgPSBmbGF0dGVuKGFycmF5KTtcblxuICAgICAgICBpZiAodGhpcy5pc0NsaSlcbiAgICAgICAgICAgIHJldHVybiBhcnJheS5sZW5ndGggPT09IDAgPyB2b2lkIDAgOiBhcnJheTtcblxuICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUNhbmNlbGFibGVQcm9taXNlICh0YXNrUHJvbWlzZSkge1xuICAgICAgICBjb25zdCBwcm9taXNlICAgICAgICAgICA9IHRhc2tQcm9taXNlLnRoZW4oKHsgY29tcGxldGlvblByb21pc2UgfSkgPT4gY29tcGxldGlvblByb21pc2UpO1xuICAgICAgICBjb25zdCByZW1vdmVGcm9tUGVuZGluZyA9ICgpID0+IHJlbW92ZSh0aGlzLnBlbmRpbmdUYXNrUHJvbWlzZXMsIHByb21pc2UpO1xuXG4gICAgICAgIHByb21pc2VcbiAgICAgICAgICAgIC50aGVuKHJlbW92ZUZyb21QZW5kaW5nKVxuICAgICAgICAgICAgLmNhdGNoKHJlbW92ZUZyb21QZW5kaW5nKTtcblxuICAgICAgICBwcm9taXNlLmNhbmNlbCA9ICgpID0+IHRhc2tQcm9taXNlXG4gICAgICAgICAgICAudGhlbigoeyBjYW5jZWxUYXNrIH0pID0+IGNhbmNlbFRhc2soKSlcbiAgICAgICAgICAgIC50aGVuKHJlbW92ZUZyb21QZW5kaW5nKTtcblxuICAgICAgICB0aGlzLnBlbmRpbmdUYXNrUHJvbWlzZXMucHVzaChwcm9taXNlKTtcblxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvLyBSdW4gdGFza1xuICAgIF9nZXRGYWlsZWRUZXN0Q291bnQgKHRhc2ssIHJlcG9ydGVyKSB7XG4gICAgICAgIGxldCBmYWlsZWRUZXN0Q291bnQgPSByZXBvcnRlci50ZXN0Q291bnQgLSByZXBvcnRlci5wYXNzZWQ7XG5cbiAgICAgICAgaWYgKHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWwgJiYgISFmYWlsZWRUZXN0Q291bnQpXG4gICAgICAgICAgICBmYWlsZWRUZXN0Q291bnQgPSAxO1xuXG4gICAgICAgIHJldHVybiBmYWlsZWRUZXN0Q291bnQ7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFRhc2tSZXN1bHQgKHRhc2ssIGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKSB7XG4gICAgICAgIHRhc2sub24oJ2Jyb3dzZXItam9iLWRvbmUnLCBqb2IgPT4gYnJvd3NlclNldC5yZWxlYXNlQ29ubmVjdGlvbihqb2IuYnJvd3NlckNvbm5lY3Rpb24pKTtcblxuICAgICAgICBjb25zdCBicm93c2VyU2V0RXJyb3JQcm9taXNlID0gcHJvbWlzaWZ5RXZlbnQoYnJvd3NlclNldCwgJ2Vycm9yJyk7XG5cbiAgICAgICAgY29uc3QgdGFza0RvbmVQcm9taXNlID0gdGFzay5vbmNlKCdkb25lJylcbiAgICAgICAgICAgIC50aGVuKCgpID0+IGJyb3dzZXJTZXRFcnJvclByb21pc2UuY2FuY2VsKCkpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHJlcG9ydGVycy5tYXAocmVwb3J0ZXIgPT4gcmVwb3J0ZXIucGVuZGluZ1Rhc2tEb25lUHJvbWlzZSkpO1xuICAgICAgICAgICAgfSk7XG5cblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtcbiAgICAgICAgICAgIHRhc2tEb25lUHJvbWlzZSxcbiAgICAgICAgICAgIGJyb3dzZXJTZXRFcnJvclByb21pc2VcbiAgICAgICAgXTtcblxuICAgICAgICBpZiAodGVzdGVkQXBwKVxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0ZXN0ZWRBcHAuZXJyb3JQcm9taXNlKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKHByb21pc2VzKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlVGFza0FuZFJlbGF0ZWRBc3NldHModGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlQXNzZXRzKGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0RmFpbGVkVGVzdENvdW50KHRhc2ssIHJlcG9ydGVyc1swXSk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVRhc2sgKHRlc3RzLCBicm93c2VyQ29ubmVjdGlvbkdyb3VwcywgcHJveHksIG9wdHMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUYXNrKHRlc3RzLCBicm93c2VyQ29ubmVjdGlvbkdyb3VwcywgcHJveHksIG9wdHMpO1xuICAgIH1cblxuICAgIF9ydW5UYXNrIChyZXBvcnRlclBsdWdpbnMsIGJyb3dzZXJTZXQsIHRlc3RzLCB0ZXN0ZWRBcHApIHtcbiAgICAgICAgbGV0IGNvbXBsZXRlZCAgICAgICAgICAgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgdGFzayAgICAgICAgICAgICAgPSB0aGlzLl9jcmVhdGVUYXNrKHRlc3RzLCBicm93c2VyU2V0LmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzLCB0aGlzLnByb3h5LCB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9ucygpKTtcbiAgICAgICAgY29uc3QgcmVwb3J0ZXJzICAgICAgICAgPSByZXBvcnRlclBsdWdpbnMubWFwKHJlcG9ydGVyID0+IG5ldyBSZXBvcnRlcihyZXBvcnRlci5wbHVnaW4sIHRhc2ssIHJlcG9ydGVyLm91dFN0cmVhbSkpO1xuICAgICAgICBjb25zdCBjb21wbGV0aW9uUHJvbWlzZSA9IHRoaXMuX2dldFRhc2tSZXN1bHQodGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuXG4gICAgICAgIHRhc2sub24oJ3N0YXJ0Jywgc3RhcnRIYW5kbGluZ1Rlc3RFcnJvcnMpO1xuXG4gICAgICAgIGlmICghdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2tpcFVuY2F1Z2h0RXJyb3JzKSkge1xuICAgICAgICAgICAgdGFzay5vbigndGVzdC1ydW4tc3RhcnQnLCBhZGRSdW5uaW5nVGVzdCk7XG4gICAgICAgICAgICB0YXNrLm9uKCd0ZXN0LXJ1bi1kb25lJywgcmVtb3ZlUnVubmluZ1Rlc3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFzay5vbignZG9uZScsIHN0b3BIYW5kbGluZ1Rlc3RFcnJvcnMpO1xuXG4gICAgICAgIGNvbnN0IG9uVGFza0NvbXBsZXRlZCA9ICgpID0+IHtcbiAgICAgICAgICAgIHRhc2sudW5SZWdpc3RlckNsaWVudFNjcmlwdFJvdXRpbmcoKTtcblxuICAgICAgICAgICAgY29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBjb21wbGV0aW9uUHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4ob25UYXNrQ29tcGxldGVkKVxuICAgICAgICAgICAgLmNhdGNoKG9uVGFza0NvbXBsZXRlZCk7XG5cbiAgICAgICAgY29uc3QgY2FuY2VsVGFzayA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmICghY29tcGxldGVkKVxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Rpc3Bvc2VUYXNrQW5kUmVsYXRlZEFzc2V0cyh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHsgY29tcGxldGlvblByb21pc2UsIGNhbmNlbFRhc2sgfTtcbiAgICB9XG5cbiAgICBfcmVnaXN0ZXJBc3NldHMgKGFzc2V0cykge1xuICAgICAgICBhc3NldHMuZm9yRWFjaChhc3NldCA9PiB0aGlzLnByb3h5LkdFVChhc3NldC5wYXRoLCBhc3NldC5pbmZvKSk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlRGVidWdMb2dnZXIgKCkge1xuICAgICAgICBjb25zdCBkZWJ1Z0xvZ2dlciA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmRlYnVnTG9nZ2VyKTtcblxuICAgICAgICBjb25zdCBkZWJ1Z0xvZ2dlckRlZmluZWRDb3JyZWN0bHkgPSBkZWJ1Z0xvZ2dlciA9PT0gbnVsbCB8fCAhIWRlYnVnTG9nZ2VyICYmXG4gICAgICAgICAgICBbJ3Nob3dCcmVha3BvaW50JywgJ2hpZGVCcmVha3BvaW50J10uZXZlcnkobWV0aG9kID0+IG1ldGhvZCBpbiBkZWJ1Z0xvZ2dlciAmJiBpc0Z1bmN0aW9uKGRlYnVnTG9nZ2VyW21ldGhvZF0pKTtcblxuICAgICAgICBpZiAoIWRlYnVnTG9nZ2VyRGVmaW5lZENvcnJlY3RseSkge1xuICAgICAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7XG4gICAgICAgICAgICAgICAgW09QVElPTl9OQU1FUy5kZWJ1Z0xvZ2dlcl06IGRlZmF1bHREZWJ1Z0xvZ2dlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfdmFsaWRhdGVTcGVlZE9wdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHNwZWVkID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc3BlZWQpO1xuXG4gICAgICAgIGlmIChzcGVlZCA9PT0gdm9pZCAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmICh0eXBlb2Ygc3BlZWQgIT09ICdudW1iZXInIHx8IGlzTmFOKHNwZWVkKSB8fCBzcGVlZCA8IDAuMDEgfHwgc3BlZWQgPiAxKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkU3BlZWRWYWx1ZSk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlQ29uY3VycmVuY3lPcHRpb24gKCkge1xuICAgICAgICBjb25zdCBjb25jdXJyZW5jeSA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmNvbmN1cnJlbmN5KTtcblxuICAgICAgICBpZiAoY29uY3VycmVuY3kgPT09IHZvaWQgMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmN1cnJlbmN5ICE9PSAnbnVtYmVyJyB8fCBpc05hTihjb25jdXJyZW5jeSkgfHwgY29uY3VycmVuY3kgPCAxKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEdlbmVyYWxFcnJvcihSVU5USU1FX0VSUk9SUy5pbnZhbGlkQ29uY3VycmVuY3lGYWN0b3IpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVByb3h5QnlwYXNzT3B0aW9uICgpIHtcbiAgICAgICAgbGV0IHByb3h5QnlwYXNzID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMucHJveHlCeXBhc3MpO1xuXG4gICAgICAgIGlmIChwcm94eUJ5cGFzcyA9PT0gdm9pZCAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGFzc2VydFR5cGUoWyBpcy5zdHJpbmcsIGlzLmFycmF5IF0sIG51bGwsICdcInByb3h5QnlwYXNzXCIgYXJndW1lbnQnLCBwcm94eUJ5cGFzcyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwcm94eUJ5cGFzcyA9PT0gJ3N0cmluZycpXG4gICAgICAgICAgICBwcm94eUJ5cGFzcyA9IFtwcm94eUJ5cGFzc107XG5cbiAgICAgICAgcHJveHlCeXBhc3MgPSBwcm94eUJ5cGFzcy5yZWR1Y2UoKGFyciwgcnVsZXMpID0+IHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMuc3RyaW5nLCBudWxsLCAnXCJwcm94eUJ5cGFzc1wiIGFyZ3VtZW50JywgcnVsZXMpO1xuXG4gICAgICAgICAgICByZXR1cm4gYXJyLmNvbmNhdChydWxlcy5zcGxpdCgnLCcpKTtcbiAgICAgICAgfSwgW10pO1xuXG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBwcm94eUJ5cGFzcyB9KTtcbiAgICB9XG5cbiAgICBfZ2V0U2NyZWVuc2hvdE9wdGlvbnMgKCkge1xuICAgICAgICBsZXQgeyBwYXRoLCBwYXRoUGF0dGVybiB9ID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2NyZWVuc2hvdHMpIHx8IHt9O1xuXG4gICAgICAgIGlmICghcGF0aClcbiAgICAgICAgICAgIHBhdGggPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5zY3JlZW5zaG90UGF0aCk7XG5cbiAgICAgICAgaWYgKCFwYXRoUGF0dGVybilcbiAgICAgICAgICAgIHBhdGhQYXR0ZXJuID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc2NyZWVuc2hvdFBhdGhQYXR0ZXJuKTtcblxuICAgICAgICByZXR1cm4geyBwYXRoLCBwYXRoUGF0dGVybiB9O1xuICAgIH1cblxuICAgIF92YWxpZGF0ZVNjcmVlbnNob3RPcHRpb25zICgpIHtcbiAgICAgICAgY29uc3QgeyBwYXRoLCBwYXRoUGF0dGVybiB9ID0gdGhpcy5fZ2V0U2NyZWVuc2hvdE9wdGlvbnMoKTtcblxuICAgICAgICBjb25zdCBkaXNhYmxlU2NyZWVuc2hvdHMgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5kaXNhYmxlU2NyZWVuc2hvdHMpIHx8ICFwYXRoO1xuXG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLmRpc2FibGVTY3JlZW5zaG90c106IGRpc2FibGVTY3JlZW5zaG90cyB9KTtcblxuICAgICAgICBpZiAoZGlzYWJsZVNjcmVlbnNob3RzKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGlmIChwYXRoKSB7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZVNjcmVlbnNob3RQYXRoKHBhdGgsICdzY3JlZW5zaG90cyBiYXNlIGRpcmVjdG9yeSBwYXRoJyk7XG5cbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLnNjcmVlbnNob3RzXTogeyBwYXRoOiByZXNvbHZlUGF0aChwYXRoKSB9IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhdGhQYXR0ZXJuKSB7XG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZVNjcmVlbnNob3RQYXRoKHBhdGhQYXR0ZXJuLCAnc2NyZWVuc2hvdHMgcGF0aCBwYXR0ZXJuJyk7XG5cbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLnNjcmVlbnNob3RzXTogeyBwYXRoUGF0dGVybiB9IH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgX3ZhbGlkYXRlVmlkZW9PcHRpb25zICgpIHtcbiAgICAgICAgY29uc3QgdmlkZW9QYXRoICAgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy52aWRlb1BhdGgpO1xuICAgICAgICBjb25zdCB2aWRlb0VuY29kaW5nT3B0aW9ucyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnZpZGVvRW5jb2RpbmdPcHRpb25zKTtcblxuICAgICAgICBsZXQgdmlkZW9PcHRpb25zID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMudmlkZW9PcHRpb25zKTtcblxuICAgICAgICBpZiAoIXZpZGVvUGF0aCkge1xuICAgICAgICAgICAgaWYgKHZpZGVvT3B0aW9ucyB8fCB2aWRlb0VuY29kaW5nT3B0aW9ucylcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdFNldFZpZGVvT3B0aW9uc1dpdGhvdXRCYXNlVmlkZW9QYXRoU3BlY2lmaWVkKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMudmlkZW9QYXRoXTogcmVzb2x2ZVBhdGgodmlkZW9QYXRoKSB9KTtcblxuICAgICAgICBpZiAoIXZpZGVvT3B0aW9ucykge1xuICAgICAgICAgICAgdmlkZW9PcHRpb25zID0ge307XG5cbiAgICAgICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBbT1BUSU9OX05BTUVTLnZpZGVvT3B0aW9uc106IHZpZGVvT3B0aW9ucyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2aWRlb09wdGlvbnMuZmZtcGVnUGF0aClcbiAgICAgICAgICAgIHZpZGVvT3B0aW9ucy5mZm1wZWdQYXRoID0gcmVzb2x2ZVBhdGgodmlkZW9PcHRpb25zLmZmbXBlZ1BhdGgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB2aWRlb09wdGlvbnMuZmZtcGVnUGF0aCA9IGF3YWl0IGRldGVjdEZGTVBFRygpO1xuXG4gICAgICAgIGlmICghdmlkZW9PcHRpb25zLmZmbXBlZ1BhdGgpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdEZpbmRGRk1QRUcpO1xuICAgIH1cblxuICAgIGFzeW5jIF92YWxpZGF0ZVJ1bk9wdGlvbnMgKCkge1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlYnVnTG9nZ2VyKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlU2NyZWVuc2hvdE9wdGlvbnMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5fdmFsaWRhdGVWaWRlb09wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVTcGVlZE9wdGlvbigpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUNvbmN1cnJlbmN5T3B0aW9uKCk7XG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlUHJveHlCeXBhc3NPcHRpb24oKTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVUZXN0Rm9yQWxsb3dNdWx0aXBsZVdpbmRvd3NPcHRpb24gKHRlc3RzKSB7XG4gICAgICAgIGlmICh0ZXN0cy5zb21lKHRlc3QgPT4gdGVzdC5pc0xlZ2FjeSkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdFVzZUFsbG93TXVsdGlwbGVXaW5kb3dzT3B0aW9uRm9yTGVnYWN5VGVzdHMpO1xuICAgIH1cblxuICAgIF92YWxpZGF0ZUJyb3dzZXJzRm9yQWxsb3dNdWx0aXBsZVdpbmRvd3NPcHRpb24gKGJyb3dzZXJTZXQpIHtcbiAgICAgICAgY29uc3QgYnJvd3NlckNvbm5lY3Rpb25zICAgICAgICAgICAgPSBicm93c2VyU2V0LmJyb3dzZXJDb25uZWN0aW9uR3JvdXBzLm1hcChicm93c2VyQ29ubmVjdGlvbkdyb3VwID0+IGJyb3dzZXJDb25uZWN0aW9uR3JvdXBbMF0pO1xuICAgICAgICBjb25zdCB1bnN1cHBvcnRlZEJyb3dzZXJDb25uZWN0aW9ucyA9IGJyb3dzZXJDb25uZWN0aW9ucy5maWx0ZXIoYnJvd3NlckNvbm5lY3Rpb24gPT4gIWJyb3dzZXJDb25uZWN0aW9uLmFjdGl2ZVdpbmRvd0lkKTtcblxuICAgICAgICBpZiAoIXVuc3VwcG9ydGVkQnJvd3NlckNvbm5lY3Rpb25zLmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCB1bnN1cHBvcnRlZEJyb3dzZXJBbGlhc2VzID0gdW5zdXBwb3J0ZWRCcm93c2VyQ29ubmVjdGlvbnMubWFwKGJyb3dzZXJDb25uZWN0aW9uID0+IGJyb3dzZXJDb25uZWN0aW9uLmJyb3dzZXJJbmZvLmFsaWFzKTtcbiAgICAgICAgY29uc3QgYnJvd3NlckFsaWFzZXMgICAgICAgICAgICA9IGdldENvbmNhdGVuYXRlZFZhbHVlc1N0cmluZyh1bnN1cHBvcnRlZEJyb3dzZXJBbGlhc2VzKTtcblxuICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLmNhbm5vdFVzZUFsbG93TXVsdGlwbGVXaW5kb3dzT3B0aW9uRm9yU29tZUJyb3dzZXJzLCBicm93c2VyQWxpYXNlcyk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlQWxsb3dNdWx0aXBsZVdpbmRvd3NPcHRpb24gKHRlc3RzLCBicm93c2VyU2V0KSB7XG4gICAgICAgIGNvbnN0IGFsbG93TXVsdGlwbGVXaW5kb3dzID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYWxsb3dNdWx0aXBsZVdpbmRvd3MpO1xuXG4gICAgICAgIGlmICghYWxsb3dNdWx0aXBsZVdpbmRvd3MpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGhpcy5fdmFsaWRhdGVUZXN0Rm9yQWxsb3dNdWx0aXBsZVdpbmRvd3NPcHRpb24odGVzdHMpO1xuICAgICAgICB0aGlzLl92YWxpZGF0ZUJyb3dzZXJzRm9yQWxsb3dNdWx0aXBsZVdpbmRvd3NPcHRpb24oYnJvd3NlclNldCk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVJ1bm5hYmxlQ29uZmlndXJhdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmJvb3RzdHJhcHBlclxuICAgICAgICAgICAgLmNyZWF0ZVJ1bm5hYmxlQ29uZmlndXJhdGlvbigpXG4gICAgICAgICAgICAudGhlbihydW5uYWJsZUNvbmZpZ3VyYXRpb24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZW1pdCgnZG9uZS1ib290c3RyYXBwaW5nJyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcnVubmFibGVDb25maWd1cmF0aW9uO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX3ZhbGlkYXRlU2NyZWVuc2hvdFBhdGggKHNjcmVlbnNob3RQYXRoLCBwYXRoVHlwZSkge1xuICAgICAgICBjb25zdCBmb3JiaWRkZW5DaGFyc0xpc3QgPSBjaGVja0ZpbGVQYXRoKHNjcmVlbnNob3RQYXRoKTtcblxuICAgICAgICBpZiAoZm9yYmlkZGVuQ2hhcnNMaXN0Lmxlbmd0aClcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMuZm9yYmlkZGVuQ2hhcmF0ZXJzSW5TY3JlZW5zaG90UGF0aCwgc2NyZWVuc2hvdFBhdGgsIHBhdGhUeXBlLCByZW5kZXJGb3JiaWRkZW5DaGFyc0xpc3QoZm9yYmlkZGVuQ2hhcnNMaXN0KSk7XG4gICAgfVxuXG4gICAgX3NldEJvb3RzdHJhcHBlck9wdGlvbnMgKCkge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ucHJlcGFyZSgpO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubm90aWZ5QWJvdXRPdmVycmlkZGVuT3B0aW9ucygpO1xuXG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLnNvdXJjZXMgICAgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuc3JjKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5zb3VyY2VzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5icm93c2VycyAgICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmJyb3dzZXJzKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5icm93c2VycztcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuY29uY3VycmVuY3kgICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jb25jdXJyZW5jeSk7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLmFwcENvbW1hbmQgICAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMuYXBwQ29tbWFuZCkgfHwgdGhpcy5ib290c3RyYXBwZXIuYXBwQ29tbWFuZDtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuYXBwSW5pdERlbGF5ICAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5hcHBJbml0RGVsYXkpO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5maWx0ZXIgICAgICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmZpbHRlcikgfHwgdGhpcy5ib290c3RyYXBwZXIuZmlsdGVyO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5yZXBvcnRlcnMgICAgICAgICAgICA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLnJlcG9ydGVyKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5yZXBvcnRlcnM7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwcGVyLnRzQ29uZmlnUGF0aCAgICAgICAgID0gdGhpcy5jb25maWd1cmF0aW9uLmdldE9wdGlvbihPUFRJT05fTkFNRVMudHNDb25maWdQYXRoKTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIuY2xpZW50U2NyaXB0cyAgICAgICAgPSB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0T3B0aW9uKE9QVElPTl9OQU1FUy5jbGllbnRTY3JpcHRzKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5jbGllbnRTY3JpcHRzO1xuICAgICAgICB0aGlzLmJvb3RzdHJhcHBlci5hbGxvd011bHRpcGxlV2luZG93cyA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRPcHRpb24oT1BUSU9OX05BTUVTLmFsbG93TXVsdGlwbGVXaW5kb3dzKSB8fCB0aGlzLmJvb3RzdHJhcHBlci5hbGxvd011bHRpcGxlV2luZG93cztcbiAgICB9XG5cbiAgICAvLyBBUElcbiAgICBlbWJlZGRpbmdPcHRpb25zIChvcHRzKSB7XG4gICAgICAgIGNvbnN0IHsgYXNzZXRzLCBUZXN0UnVuQ3RvciB9ID0gb3B0cztcblxuICAgICAgICB0aGlzLl9yZWdpc3RlckFzc2V0cyhhc3NldHMpO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgVGVzdFJ1bkN0b3IgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgc3JjICguLi5zb3VyY2VzKSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5zcmMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLnNyYyk7XG5cbiAgICAgICAgc291cmNlcyA9IHRoaXMuX3ByZXBhcmVBcnJheVBhcmFtZXRlcihzb3VyY2VzKTtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMuc3JjXTogc291cmNlcyB9KTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5zcmMgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGJyb3dzZXJzICguLi5icm93c2Vycykge1xuICAgICAgICBpZiAodGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuYnJvd3NlcnMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLmJyb3dzZXJzKTtcblxuICAgICAgICBicm93c2VycyA9IHRoaXMuX3ByZXBhcmVBcnJheVBhcmFtZXRlcihicm93c2Vycyk7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBicm93c2VycyB9KTtcblxuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5icm93c2VycyA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgY29uY3VycmVuY3kgKGNvbmN1cnJlbmN5KSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBjb25jdXJyZW5jeSB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICByZXBvcnRlciAobmFtZSwgb3V0cHV0KSB7XG4gICAgICAgIGlmICh0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5yZXBvcnRlcilcbiAgICAgICAgICAgIHRocm93IG5ldyBHZW5lcmFsRXJyb3IoUlVOVElNRV9FUlJPUlMubXVsdGlwbGVBUElNZXRob2RDYWxsRm9yYmlkZGVuLCBPUFRJT05fTkFNRVMucmVwb3J0ZXIpO1xuXG4gICAgICAgIGxldCByZXBvcnRlcnMgPSBwcmVwYXJlUmVwb3J0ZXJzKG5hbWUsIG91dHB1dCk7XG5cbiAgICAgICAgcmVwb3J0ZXJzID0gdGhpcy5fcHJlcGFyZUFycmF5UGFyYW1ldGVyKHJlcG9ydGVycyk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMucmVwb3J0ZXJdOiByZXBvcnRlcnMgfSk7XG5cbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQucmVwb3J0ZXIgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZpbHRlciAoZmlsdGVyKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoeyBmaWx0ZXIgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdXNlUHJveHkgKHByb3h5LCBwcm94eUJ5cGFzcykge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgcHJveHksIHByb3h5QnlwYXNzIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHNjcmVlbnNob3RzICguLi5vcHRpb25zKSB7XG4gICAgICAgIGxldCBmdWxsUGFnZTtcbiAgICAgICAgbGV0IFtwYXRoLCB0YWtlT25GYWlscywgcGF0aFBhdHRlcm5dID0gb3B0aW9ucztcblxuICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPT09IDEgJiYgb3B0aW9uc1swXSAmJiB0eXBlb2Ygb3B0aW9uc1swXSA9PT0gJ29iamVjdCcpXG4gICAgICAgICAgICAoeyBwYXRoLCB0YWtlT25GYWlscywgcGF0aFBhdHRlcm4sIGZ1bGxQYWdlIH0gPSBvcHRpb25zWzBdKTtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKHsgc2NyZWVuc2hvdHM6IHsgcGF0aCwgdGFrZU9uRmFpbHMsIHBhdGhQYXR0ZXJuLCBmdWxsUGFnZSB9IH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZpZGVvIChwYXRoLCBvcHRpb25zLCBlbmNvZGluZ09wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7XG4gICAgICAgICAgICBbT1BUSU9OX05BTUVTLnZpZGVvUGF0aF06ICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgIFtPUFRJT05fTkFNRVMudmlkZW9PcHRpb25zXTogICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgW09QVElPTl9OQU1FUy52aWRlb0VuY29kaW5nT3B0aW9uc106IGVuY29kaW5nT3B0aW9uc1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBzdGFydEFwcCAoY29tbWFuZCwgaW5pdERlbGF5KSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgW09QVElPTl9OQU1FUy5hcHBDb21tYW5kXTogICBjb21tYW5kLFxuICAgICAgICAgICAgW09QVElPTl9OQU1FUy5hcHBJbml0RGVsYXldOiBpbml0RGVsYXlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdHNDb25maWdQYXRoIChwYXRoKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5tZXJnZU9wdGlvbnMoe1xuICAgICAgICAgICAgW09QVElPTl9OQU1FUy50c0NvbmZpZ1BhdGhdOiBwYXRoXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNsaWVudFNjcmlwdHMgKC4uLnNjcmlwdHMpIHtcbiAgICAgICAgaWYgKHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkLmNsaWVudFNjcmlwdHMpXG4gICAgICAgICAgICB0aHJvdyBuZXcgR2VuZXJhbEVycm9yKFJVTlRJTUVfRVJST1JTLm11bHRpcGxlQVBJTWV0aG9kQ2FsbEZvcmJpZGRlbiwgT1BUSU9OX05BTUVTLmNsaWVudFNjcmlwdHMpO1xuXG4gICAgICAgIHNjcmlwdHMgPSB0aGlzLl9wcmVwYXJlQXJyYXlQYXJhbWV0ZXIoc2NyaXB0cyk7XG5cbiAgICAgICAgdGhpcy5jb25maWd1cmF0aW9uLm1lcmdlT3B0aW9ucyh7IFtPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0c106IHNjcmlwdHMgfSk7XG5cbiAgICAgICAgdGhpcy5hcGlNZXRob2RXYXNDYWxsZWQuY2xpZW50U2NyaXB0cyA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgYXN5bmMgX3ByZXBhcmVDbGllbnRTY3JpcHRzICh0ZXN0cywgY2xpZW50U2NyaXB0cykge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwodGVzdHMubWFwKGFzeW5jIHRlc3QgPT4ge1xuICAgICAgICAgICAgaWYgKHRlc3QuaXNMZWdhY3kpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICBsZXQgbG9hZGVkVGVzdENsaWVudFNjcmlwdHMgPSBhd2FpdCBsb2FkQ2xpZW50U2NyaXB0cyh0ZXN0LmNsaWVudFNjcmlwdHMsIGRpcm5hbWUodGVzdC50ZXN0RmlsZS5maWxlbmFtZSkpO1xuXG4gICAgICAgICAgICBsb2FkZWRUZXN0Q2xpZW50U2NyaXB0cyA9IGNsaWVudFNjcmlwdHMuY29uY2F0KGxvYWRlZFRlc3RDbGllbnRTY3JpcHRzKTtcblxuICAgICAgICAgICAgdGVzdC5jbGllbnRTY3JpcHRzID0gc2V0VW5pcXVlVXJscyhsb2FkZWRUZXN0Q2xpZW50U2NyaXB0cyk7XG4gICAgICAgIH0pKTtcbiAgICB9XG5cbiAgICBydW4gKG9wdGlvbnMgPSB7fSkge1xuICAgICAgICB0aGlzLmFwaU1ldGhvZFdhc0NhbGxlZC5yZXNldCgpO1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ubWVyZ2VPcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICB0aGlzLl9zZXRCb290c3RyYXBwZXJPcHRpb25zKCk7XG5cbiAgICAgICAgY29uc3QgcnVuVGFza1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5fdmFsaWRhdGVSdW5PcHRpb25zKCkpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLl9jcmVhdGVSdW5uYWJsZUNvbmZpZ3VyYXRpb24oKSlcbiAgICAgICAgICAgIC50aGVuKGFzeW5jICh7IHJlcG9ydGVyUGx1Z2lucywgYnJvd3NlclNldCwgdGVzdHMsIHRlc3RlZEFwcCwgY29tbW9uQ2xpZW50U2NyaXB0cyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fcHJlcGFyZUNsaWVudFNjcmlwdHModGVzdHMsIGNvbW1vbkNsaWVudFNjcmlwdHMpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5fdmFsaWRhdGVBbGxvd011bHRpcGxlV2luZG93c09wdGlvbih0ZXN0cywgYnJvd3NlclNldCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcnVuVGFzayhyZXBvcnRlclBsdWdpbnMsIGJyb3dzZXJTZXQsIHRlc3RzLCB0ZXN0ZWRBcHApO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWF0ZUNhbmNlbGFibGVQcm9taXNlKHJ1blRhc2tQcm9taXNlKTtcbiAgICB9XG5cbiAgICBhc3luYyBzdG9wICgpIHtcbiAgICAgICAgLy8gTk9URTogV2hlbiB0YXNrUHJvbWlzZSBpcyBjYW5jZWxsZWQsIGl0IGlzIHJlbW92ZWQgZnJvbVxuICAgICAgICAvLyB0aGUgcGVuZGluZ1Rhc2tQcm9taXNlcyBhcnJheSwgd2hpY2ggbGVhZHMgdG8gc2hpZnRpbmcgaW5kZXhlc1xuICAgICAgICAvLyB0b3dhcmRzIHRoZSBiZWdpbm5pbmcuIFNvLCB3ZSBtdXN0IGNvcHkgdGhlIGFycmF5IGluIG9yZGVyIHRvIGl0ZXJhdGUgaXQsXG4gICAgICAgIC8vIG9yIHdlIGNhbiBwZXJmb3JtIGl0ZXJhdGlvbiBmcm9tIHRoZSBlbmQgdG8gdGhlIGJlZ2lubmluZy5cbiAgICAgICAgY29uc3QgY2FuY2VsbGF0aW9uUHJvbWlzZXMgPSBtYXBSZXZlcnNlKHRoaXMucGVuZGluZ1Rhc2tQcm9taXNlcywgdGFza1Byb21pc2UgPT4gdGFza1Byb21pc2UuY2FuY2VsKCkpO1xuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGNhbmNlbGxhdGlvblByb21pc2VzKTtcbiAgICB9XG59XG4iXX0= |
\ | No newline at end of file |