oxygen-cli 1.22.0 → 1.99.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -50
- package/build/core/OxygenCore.js +56 -145
- package/build/errors/OxygenError.js +5 -15
- package/build/errors/helper.js +45 -49
- package/build/index.js +14 -6
- package/build/lib/cli-util.js +19 -19
- package/build/lib/cli.js +4 -2
- package/build/lib/parallel-launcher.js +333 -0
- package/build/lib/param-manager.js +66 -47
- package/build/lib/util.js +38 -9
- package/build/ox_modules/index.js +1 -97
- package/build/ox_modules/module-assert.js +19 -9
- package/build/ox_modules/module-dns.js +220 -0
- package/build/ox_modules/module-http.js +39 -51
- package/build/ox_modules/module-shell.js +19 -75
- package/build/ox_modules/module-utils.js +1 -108
- package/build/ox_modules/utils.js +1 -357
- package/build/reporter/FileReporterBase.js +5 -5
- package/build/reporter/ReportAggregator.js +127 -4
- package/build/runners/WorkerProcess.js +15 -28
- package/build/runners/index.js +2 -6
- package/build/runners/oxygen/OxygenWorker.js +8 -8
- package/build/runners/oxygen/index.js +17 -18
- package/build/runners/oxygen/worker.js +10 -8
- package/package.json +12 -46
- package/build/lib/img-merge.js +0 -163
- package/build/ox_modules/module-db.js +0 -146
- package/build/ox_modules/module-email.js +0 -212
- package/build/ox_modules/module-eyes.js +0 -189
- package/build/ox_modules/module-mailinator.js +0 -207
- package/build/ox_modules/module-mob/commands/alertAccept.js +0 -35
- package/build/ox_modules/module-mob/commands/alertDismiss.js +0 -35
- package/build/ox_modules/module-mob/commands/assertAlert.js +0 -56
- package/build/ox_modules/module-mob/commands/assertText.js +0 -45
- package/build/ox_modules/module-mob/commands/assertTitle.js +0 -43
- package/build/ox_modules/module-mob/commands/assertValue.js +0 -66
- package/build/ox_modules/module-mob/commands/back.js +0 -27
- package/build/ox_modules/module-mob/commands/clear.js +0 -40
- package/build/ox_modules/module-mob/commands/click.js +0 -35
- package/build/ox_modules/module-mob/commands/clickHidden.js +0 -52
- package/build/ox_modules/module-mob/commands/clickLong.js +0 -34
- package/build/ox_modules/module-mob/commands/clickMultipleTimes.js +0 -37
- package/build/ox_modules/module-mob/commands/closeApp.js +0 -27
- package/build/ox_modules/module-mob/commands/debug.js +0 -26
- package/build/ox_modules/module-mob/commands/dragAndDrop.js +0 -38
- package/build/ox_modules/module-mob/commands/enableNetwork.js +0 -75
- package/build/ox_modules/module-mob/commands/execute.js +0 -32
- package/build/ox_modules/module-mob/commands/findElement.js +0 -36
- package/build/ox_modules/module-mob/commands/findElements.js +0 -39
- package/build/ox_modules/module-mob/commands/getAlertText.js +0 -31
- package/build/ox_modules/module-mob/commands/getAppiumLogs.js +0 -26
- package/build/ox_modules/module-mob/commands/getBrowserLogs.js +0 -66
- package/build/ox_modules/module-mob/commands/getCurrentActivity.js +0 -26
- package/build/ox_modules/module-mob/commands/getCurrentPackage.js +0 -26
- package/build/ox_modules/module-mob/commands/getDeviceLogs.js +0 -57
- package/build/ox_modules/module-mob/commands/getDeviceTime.js +0 -27
- package/build/ox_modules/module-mob/commands/getLocation.js +0 -32
- package/build/ox_modules/module-mob/commands/getSource.js +0 -26
- package/build/ox_modules/module-mob/commands/getText.js +0 -36
- package/build/ox_modules/module-mob/commands/getTitle.js +0 -24
- package/build/ox_modules/module-mob/commands/getUrl.js +0 -28
- package/build/ox_modules/module-mob/commands/getValue.js +0 -50
- package/build/ox_modules/module-mob/commands/getWindowHandles.js +0 -27
- package/build/ox_modules/module-mob/commands/hideKeyboard.js +0 -33
- package/build/ox_modules/module-mob/commands/index.js +0 -594
- package/build/ox_modules/module-mob/commands/installApp.js +0 -28
- package/build/ox_modules/module-mob/commands/isAppInstalled.js +0 -28
- package/build/ox_modules/module-mob/commands/isCheckable.js +0 -31
- package/build/ox_modules/module-mob/commands/isChecked.js +0 -31
- package/build/ox_modules/module-mob/commands/isClickable.js +0 -31
- package/build/ox_modules/module-mob/commands/isExist.js +0 -36
- package/build/ox_modules/module-mob/commands/isSelected.js +0 -36
- package/build/ox_modules/module-mob/commands/isVisible.js +0 -36
- package/build/ox_modules/module-mob/commands/isWebViewContext.js +0 -27
- package/build/ox_modules/module-mob/commands/launchApp.js +0 -26
- package/build/ox_modules/module-mob/commands/longPressKeyCode.js +0 -30
- package/build/ox_modules/module-mob/commands/open.js +0 -43
- package/build/ox_modules/module-mob/commands/pause.js +0 -27
- package/build/ox_modules/module-mob/commands/removeApp.js +0 -28
- package/build/ox_modules/module-mob/commands/resetApp.js +0 -26
- package/build/ox_modules/module-mob/commands/scrollIntoElement.js +0 -86
- package/build/ox_modules/module-mob/commands/scrollIntoView.js +0 -40
- package/build/ox_modules/module-mob/commands/select.js +0 -54
- package/build/ox_modules/module-mob/commands/selectFrame.js +0 -53
- package/build/ox_modules/module-mob/commands/selectWindow.js +0 -149
- package/build/ox_modules/module-mob/commands/sendKeys.js +0 -84
- package/build/ox_modules/module-mob/commands/setContext.js +0 -28
- package/build/ox_modules/module-mob/commands/setNativeContext.js +0 -26
- package/build/ox_modules/module-mob/commands/setTimeout.js +0 -33
- package/build/ox_modules/module-mob/commands/setWebViewContext.js +0 -39
- package/build/ox_modules/module-mob/commands/shake.js +0 -27
- package/build/ox_modules/module-mob/commands/smsClickLink.js +0 -32
- package/build/ox_modules/module-mob/commands/smsGetText.js +0 -45
- package/build/ox_modules/module-mob/commands/swipe.js +0 -58
- package/build/ox_modules/module-mob/commands/swipeElement.js +0 -58
- package/build/ox_modules/module-mob/commands/swipeScreen.js +0 -56
- package/build/ox_modules/module-mob/commands/takeScreenshot.js +0 -27
- package/build/ox_modules/module-mob/commands/tap.js +0 -34
- package/build/ox_modules/module-mob/commands/type.js +0 -67
- package/build/ox_modules/module-mob/commands/unlockPattern.js +0 -92
- package/build/ox_modules/module-mob/commands/waitForExist.js +0 -29
- package/build/ox_modules/module-mob/commands/waitForInteractable.js +0 -42
- package/build/ox_modules/module-mob/commands/waitForVisible.js +0 -28
- package/build/ox_modules/module-mob.js +0 -699
- package/build/ox_modules/module-pdf.js +0 -328
- package/build/ox_modules/module-proxy.js +0 -324
- package/build/ox_modules/module-serial.js +0 -187
- package/build/ox_modules/module-soap.js +0 -260
- package/build/ox_modules/module-twilio.js +0 -192
- package/build/ox_modules/module-web/commands/alertAccept.js +0 -35
- package/build/ox_modules/module-web/commands/alertDismiss.js +0 -35
- package/build/ox_modules/module-web/commands/assertAlert.js +0 -55
- package/build/ox_modules/module-web/commands/assertExist.js +0 -28
- package/build/ox_modules/module-web/commands/assertSelectedLabel.js +0 -51
- package/build/ox_modules/module-web/commands/assertSelectedValue.js +0 -45
- package/build/ox_modules/module-web/commands/assertText.js +0 -45
- package/build/ox_modules/module-web/commands/assertTextNotPresent.js +0 -56
- package/build/ox_modules/module-web/commands/assertTextPresent.js +0 -52
- package/build/ox_modules/module-web/commands/assertTitle.js +0 -42
- package/build/ox_modules/module-web/commands/assertValue.js +0 -44
- package/build/ox_modules/module-web/commands/back.js +0 -27
- package/build/ox_modules/module-web/commands/clear.js +0 -41
- package/build/ox_modules/module-web/commands/click.js +0 -112
- package/build/ox_modules/module-web/commands/clickHidden.js +0 -79
- package/build/ox_modules/module-web/commands/closeWindow.js +0 -25
- package/build/ox_modules/module-web/commands/debug.js +0 -25
- package/build/ox_modules/module-web/commands/deleteCookies.js +0 -22
- package/build/ox_modules/module-web/commands/deselect.js +0 -34
- package/build/ox_modules/module-web/commands/doubleClick.js +0 -65
- package/build/ox_modules/module-web/commands/dragAndDrop.js +0 -36
- package/build/ox_modules/module-web/commands/execute.js +0 -36
- package/build/ox_modules/module-web/commands/fileBrowse.js +0 -72
- package/build/ox_modules/module-web/commands/findElement.js +0 -35
- package/build/ox_modules/module-web/commands/findElements.js +0 -38
- package/build/ox_modules/module-web/commands/fullscreenWindow.js +0 -24
- package/build/ox_modules/module-web/commands/getAlertText.js +0 -30
- package/build/ox_modules/module-web/commands/getAttribute.js +0 -38
- package/build/ox_modules/module-web/commands/getBrowserLogs.js +0 -34
- package/build/ox_modules/module-web/commands/getCookies.js +0 -23
- package/build/ox_modules/module-web/commands/getCssValue.js +0 -38
- package/build/ox_modules/module-web/commands/getElementCount.js +0 -29
- package/build/ox_modules/module-web/commands/getHTML.js +0 -30
- package/build/ox_modules/module-web/commands/getSource.js +0 -26
- package/build/ox_modules/module-web/commands/getText.js +0 -36
- package/build/ox_modules/module-web/commands/getTitle.js +0 -22
- package/build/ox_modules/module-web/commands/getUrl.js +0 -26
- package/build/ox_modules/module-web/commands/getValue.js +0 -43
- package/build/ox_modules/module-web/commands/getWindowHandles.js +0 -26
- package/build/ox_modules/module-web/commands/getWindowSize.js +0 -26
- package/build/ox_modules/module-web/commands/getXMLPageSource.js +0 -51
- package/build/ox_modules/module-web/commands/index.js +0 -634
- package/build/ox_modules/module-web/commands/isAlertPresent.js +0 -31
- package/build/ox_modules/module-web/commands/isChecked.js +0 -30
- package/build/ox_modules/module-web/commands/isExist.js +0 -36
- package/build/ox_modules/module-web/commands/isSelected.js +0 -35
- package/build/ox_modules/module-web/commands/isVisible.js +0 -36
- package/build/ox_modules/module-web/commands/makeVisible.js +0 -74
- package/build/ox_modules/module-web/commands/maximizeWindow.js +0 -24
- package/build/ox_modules/module-web/commands/minimizeWindow.js +0 -24
- package/build/ox_modules/module-web/commands/newWindow.js +0 -27
- package/build/ox_modules/module-web/commands/open.js +0 -42
- package/build/ox_modules/module-web/commands/pause.js +0 -26
- package/build/ox_modules/module-web/commands/point.js +0 -37
- package/build/ox_modules/module-web/commands/pointJS.js +0 -56
- package/build/ox_modules/module-web/commands/refresh.js +0 -26
- package/build/ox_modules/module-web/commands/rightClick.js +0 -61
- package/build/ox_modules/module-web/commands/rightClickActions.js +0 -57
- package/build/ox_modules/module-web/commands/scrollToElement.js +0 -33
- package/build/ox_modules/module-web/commands/select.js +0 -55
- package/build/ox_modules/module-web/commands/selectFrame.js +0 -52
- package/build/ox_modules/module-web/commands/selectWindow.js +0 -148
- package/build/ox_modules/module-web/commands/sendKeys.js +0 -56
- package/build/ox_modules/module-web/commands/setAutoWaitForAngular.js +0 -33
- package/build/ox_modules/module-web/commands/setTimeout.js +0 -33
- package/build/ox_modules/module-web/commands/setWindowSize.js +0 -29
- package/build/ox_modules/module-web/commands/takeScreenshot.js +0 -37
- package/build/ox_modules/module-web/commands/type.js +0 -52
- package/build/ox_modules/module-web/commands/waitForAngular.js +0 -83
- package/build/ox_modules/module-web/commands/waitForExist.js +0 -28
- package/build/ox_modules/module-web/commands/waitForInteractable.js +0 -31
- package/build/ox_modules/module-web/commands/waitForNotExist.js +0 -57
- package/build/ox_modules/module-web/commands/waitForNotText.js +0 -45
- package/build/ox_modules/module-web/commands/waitForNotValue.js +0 -45
- package/build/ox_modules/module-web/commands/waitForText.js +0 -45
- package/build/ox_modules/module-web/commands/waitForValue.js +0 -45
- package/build/ox_modules/module-web/commands/waitForVisible.js +0 -28
- package/build/ox_modules/module-web/commands/waitForWindow.js +0 -118
- package/build/ox_modules/module-web.js +0 -909
- package/build/ox_modules/module-win/commands/assertText.js +0 -41
- package/build/ox_modules/module-win/commands/assertTitle.js +0 -38
- package/build/ox_modules/module-win/commands/assertValue.js +0 -62
- package/build/ox_modules/module-win/commands/back.js +0 -21
- package/build/ox_modules/module-win/commands/clear.js +0 -34
- package/build/ox_modules/module-win/commands/click.js +0 -25
- package/build/ox_modules/module-win/commands/clickLong.js +0 -30
- package/build/ox_modules/module-win/commands/clickMultipleTimes.js +0 -33
- package/build/ox_modules/module-win/commands/findElement.js +0 -31
- package/build/ox_modules/module-win/commands/findElements.js +0 -31
- package/build/ox_modules/module-win/commands/getAppiumLogs.js +0 -22
- package/build/ox_modules/module-win/commands/getCurrentWindowHandle.js +0 -25
- package/build/ox_modules/module-win/commands/getLocation.js +0 -26
- package/build/ox_modules/module-win/commands/getSource.js +0 -22
- package/build/ox_modules/module-win/commands/getText.js +0 -32
- package/build/ox_modules/module-win/commands/getValue.js +0 -46
- package/build/ox_modules/module-win/commands/getWindowHandles.js +0 -25
- package/build/ox_modules/module-win/commands/index.js +0 -298
- package/build/ox_modules/module-win/commands/isCheckable.js +0 -26
- package/build/ox_modules/module-win/commands/isChecked.js +0 -26
- package/build/ox_modules/module-win/commands/isClickable.js +0 -26
- package/build/ox_modules/module-win/commands/isExist.js +0 -32
- package/build/ox_modules/module-win/commands/isSelected.js +0 -26
- package/build/ox_modules/module-win/commands/isVisible.js +0 -32
- package/build/ox_modules/module-win/commands/open.js +0 -24
- package/build/ox_modules/module-win/commands/pause.js +0 -23
- package/build/ox_modules/module-win/commands/rightClick.js +0 -30
- package/build/ox_modules/module-win/commands/selectWindow.js +0 -97
- package/build/ox_modules/module-win/commands/sendKeys.js +0 -50
- package/build/ox_modules/module-win/commands/setTimeout.js +0 -29
- package/build/ox_modules/module-win/commands/takeScreenshot.js +0 -26
- package/build/ox_modules/module-win/commands/tap.js +0 -29
- package/build/ox_modules/module-win/commands/type.js +0 -38
- package/build/ox_modules/module-win/commands/waitForExist.js +0 -25
- package/build/ox_modules/module-win/commands/waitForInteractable.js +0 -43
- package/build/ox_modules/module-win/commands/waitForVisible.js +0 -24
- package/build/ox_modules/module-win.js +0 -367
- package/build/ox_services/service-devtools/submodule-network.js +0 -338
- package/build/ox_services/service-devtools.js +0 -83
- package/build/runners/cucumber/CucumberEventListener.js +0 -181
- package/build/runners/cucumber/CucumberReporter.js +0 -277
- package/build/runners/cucumber/CucumberWorker.js +0 -337
- package/build/runners/cucumber/index.js +0 -159
- package/build/runners/cucumber/worker.js +0 -184
|
@@ -1,909 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-unused-vars */
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Copyright (C) 2015-present CloudBeat Limited
|
|
5
|
-
*
|
|
6
|
-
* This program is free software: you can redistribute it and/or modify
|
|
7
|
-
* it under the terms of the GNU General Public License as published by
|
|
8
|
-
* the Free Software Foundation, either version 3 of the License, or
|
|
9
|
-
* (at your option) any later version.
|
|
10
|
-
*/
|
|
11
|
-
'use strict';
|
|
12
|
-
/**
|
|
13
|
-
* @name web
|
|
14
|
-
* @description Provides methods for browser automation.
|
|
15
|
-
* @sample **Notes:**
|
|
16
|
-
*
|
|
17
|
-
* Commands which operate on elements such as click, assert, waitFor, type, select, and others will automatically wait for a period of time for the element to appear in DOM and become visible. By default this period equals to 60 seconds, but can be changed using the `setTimeout`command.
|
|
18
|
-
*
|
|
19
|
-
* **String matching patterns:**
|
|
20
|
-
*
|
|
21
|
-
* Commands which expect a string matching pattern in their arguments, support following patterns unless specified otherwise:
|
|
22
|
-
*
|
|
23
|
-
* * `regex:PATTERN` - Match using regular expression.
|
|
24
|
-
* * `regexi:PATTERN` - Match using case-insensitive regular expression.
|
|
25
|
-
* * `exact:STRING` - Match the string verbatim.
|
|
26
|
-
* * `glob:PATTERN` - Match using case-insensitive glob pattern. `?` will match any single character except new line \(\n\). `*` will match any sequence \(0 or more\) of characters except new line. Empty PATTERN will match only other empty strings.
|
|
27
|
-
* * `PATTERN` - Same as glob matching.
|
|
28
|
-
*
|
|
29
|
-
* **Locators:**
|
|
30
|
-
*
|
|
31
|
-
* Commands which expect an element locator in their arguments, support following locator types unless specified otherwise:
|
|
32
|
-
*
|
|
33
|
-
* * `id=ID` - Locates element by its ID attribute.
|
|
34
|
-
* * `css=CSS_SELECTOR` - Locates element using a CSS selector.
|
|
35
|
-
* * `link=TEXT` - Locates link element whose visible text matches the given string.
|
|
36
|
-
* * `link-contains=TEXT` - Locates link element whose visible text contains the given string.
|
|
37
|
-
* * `name=NAME` - Locates element by its NAME attribute.
|
|
38
|
-
* * `tag=NAME` - Locates element by its tag name.
|
|
39
|
-
* * `/XPATH` - Locates element using an XPath 1.0 expression.
|
|
40
|
-
* * `(XPATH)[]` - Locates element using an XPath 1.0 expression.
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
/* eslint-disable quotes */
|
|
44
|
-
|
|
45
|
-
Object.defineProperty(exports, "__esModule", {
|
|
46
|
-
value: true
|
|
47
|
-
});
|
|
48
|
-
exports.default = void 0;
|
|
49
|
-
|
|
50
|
-
require("source-map-support/register");
|
|
51
|
-
|
|
52
|
-
var _chromeHar = require("chrome-har");
|
|
53
|
-
|
|
54
|
-
var _url = _interopRequireDefault(require("url"));
|
|
55
|
-
|
|
56
|
-
var wdio = _interopRequireWildcard(require("webdriverio"));
|
|
57
|
-
|
|
58
|
-
var _WebDriverModule = _interopRequireDefault(require("../core/WebDriverModule"));
|
|
59
|
-
|
|
60
|
-
var _when = require("when");
|
|
61
|
-
|
|
62
|
-
var _utils = _interopRequireDefault(require("./utils"));
|
|
63
|
-
|
|
64
|
-
var _helper = _interopRequireDefault(require("../errors/helper"));
|
|
65
|
-
|
|
66
|
-
var _OxygenError = _interopRequireDefault(require("../errors/OxygenError"));
|
|
67
|
-
|
|
68
|
-
var _util = _interopRequireDefault(require("util"));
|
|
69
|
-
|
|
70
|
-
var _saucelabs = _interopRequireDefault(require("saucelabs"));
|
|
71
|
-
|
|
72
|
-
var _nodeRestClient = _interopRequireDefault(require("@lambdatest/node-rest-client"));
|
|
73
|
-
|
|
74
|
-
var _testingbotApi = _interopRequireDefault(require("testingbot-api"));
|
|
75
|
-
|
|
76
|
-
var _child_process = require("child_process");
|
|
77
|
-
|
|
78
|
-
var _perfectoReporting = _interopRequireDefault(require("perfecto-reporting"));
|
|
79
|
-
|
|
80
|
-
var _request = _interopRequireDefault(require("request"));
|
|
81
|
-
|
|
82
|
-
var _imgMerge = _interopRequireDefault(require("../lib/img-merge"));
|
|
83
|
-
|
|
84
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
85
|
-
|
|
86
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
87
|
-
|
|
88
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
89
|
-
|
|
90
|
-
const MODULE_NAME = 'web';
|
|
91
|
-
const DEFAULT_SELENIUM_URL = 'http://localhost:4444/wd/hub';
|
|
92
|
-
const DEFAULT_BROWSER_NAME = 'chrome';
|
|
93
|
-
const DEFAULT_MOBILE_BROWSER = 'default';
|
|
94
|
-
const NO_SCREENSHOT_COMMANDS = ['init', 'assertAlert'];
|
|
95
|
-
const ACTION_COMMANDS = ['open', 'click'];
|
|
96
|
-
const DEFAULT_WAIT_TIMEOUT = 60 * 1000; // default 60s wait timeout
|
|
97
|
-
|
|
98
|
-
class WebModule extends _WebDriverModule.default {
|
|
99
|
-
constructor(options, context, rs, logger, modules, services) {
|
|
100
|
-
super(options, context, rs, logger, modules, services);
|
|
101
|
-
this.transactions = {}; // transaction->har dictionary
|
|
102
|
-
|
|
103
|
-
this.lastNavigationStartTime = null;
|
|
104
|
-
this.helpers = {};
|
|
105
|
-
|
|
106
|
-
this._loadHelperFunctions(); // support backward compatibility (some module commands might refer to this.OxError and this.errHelper)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.OxError = _OxygenError.default;
|
|
110
|
-
this.errHelper = _helper.default; // holds element operation timeout value
|
|
111
|
-
|
|
112
|
-
this.waitForTimeout = DEFAULT_WAIT_TIMEOUT;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
get name() {
|
|
116
|
-
return MODULE_NAME;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* @function getDriver
|
|
120
|
-
* @summary Returns the underlying WDIO driver.
|
|
121
|
-
* @return {Object} WDIO driver.
|
|
122
|
-
*/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
getDriver() {
|
|
126
|
-
return super.getDriver();
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* @function getCapabilities
|
|
130
|
-
* @summary Returns currently defined capabilities.
|
|
131
|
-
* @return {Object} Current capabilities object.
|
|
132
|
-
*/
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
getCapabilities() {
|
|
136
|
-
return this.caps || super.getCapabilities();
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* @function init
|
|
140
|
-
* @summary Initializes new Selenium session.
|
|
141
|
-
* @param {String=} caps - Desired capabilities. If not specified capabilities will be taken from suite definition.
|
|
142
|
-
* @param {String=} seleniumUrl - Remote server URL (default: http://localhost:4444/wd/hub).
|
|
143
|
-
*/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
async init(caps, seleniumUrl) {
|
|
147
|
-
if (this.isInitialized) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (!seleniumUrl) {
|
|
152
|
-
seleniumUrl = this.options.seleniumUrl || DEFAULT_SELENIUM_URL;
|
|
153
|
-
} // take capabilities either from init method argument or from context parameters passed in the constructor
|
|
154
|
-
// merge capabilities from context and from init function argument, give preference to context-passed capabilities
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.caps = {};
|
|
158
|
-
|
|
159
|
-
if (this.ctx.caps) {
|
|
160
|
-
this.caps = { ...this.ctx.caps
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (caps) {
|
|
165
|
-
this.caps = { ...this.caps,
|
|
166
|
-
...caps
|
|
167
|
-
};
|
|
168
|
-
} // populate browserName caps from options. FIXME: why is this even needed?
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
let defaultBrowser = false;
|
|
172
|
-
|
|
173
|
-
if (!this.caps.browserName) {
|
|
174
|
-
this.caps.browserName = this.options.browserName || DEFAULT_BROWSER_NAME;
|
|
175
|
-
defaultBrowser = true;
|
|
176
|
-
} // FIXME: shall we throw an exception if browserName is not specified, neither in caps nor in options?!
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (!this.caps.browserName) {
|
|
180
|
-
throw new _OxygenError.default(_helper.default.errorCode.INVALID_CAPABILITIES, 'Failed to initialize `web` module - browserName must be specified.');
|
|
181
|
-
} // adjust browserName-s
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (this.caps.browserName.toLowerCase() === 'ie') {
|
|
185
|
-
// IE is specified as 'ie' through the command line and possibly suites
|
|
186
|
-
// but selenium standalone server expects 'internet explorer'
|
|
187
|
-
this.caps.browserName = 'internet explorer';
|
|
188
|
-
} else if (this.caps['lambda:options']) {// lambdatest expects original case names
|
|
189
|
-
} else if (this.caps['perfectoMobile:options']) {// perfectoMobile expects original case names
|
|
190
|
-
} else if (this.caps.browserName !== 'MicrosoftEdge') {
|
|
191
|
-
// selenium standalone server expects all browserNames to be lowercase
|
|
192
|
-
// except "MicrosoftEdge"
|
|
193
|
-
this.caps.browserName = this.caps.browserName.toLowerCase();
|
|
194
|
-
} // adjust capabilities to enable collecting browser and performance stats in Chrome
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (this.options.recordHAR && this.caps.browserName === 'chrome') {
|
|
198
|
-
this.caps['goog:loggingPrefs'] = {
|
|
199
|
-
// for ChromeDriver >= 75
|
|
200
|
-
browser: 'ALL',
|
|
201
|
-
performance: 'ALL'
|
|
202
|
-
};
|
|
203
|
-
/*
|
|
204
|
-
// specifying this leads Chrome 77+ to refuse loading
|
|
205
|
-
this.caps.loggingPrefs = { // for ChromeDriver < 75
|
|
206
|
-
browser: 'ALL',
|
|
207
|
-
performance: 'ALL'
|
|
208
|
-
};
|
|
209
|
-
this.caps.chromeOptions = {
|
|
210
|
-
perfLoggingPrefs: {
|
|
211
|
-
enableNetwork: true,
|
|
212
|
-
enablePage: false
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
*/
|
|
216
|
-
} // populate WDIO options
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const url = _url.default.parse(seleniumUrl || DEFAULT_SELENIUM_URL);
|
|
220
|
-
|
|
221
|
-
const protocol = url.protocol.replace(/:$/, '');
|
|
222
|
-
const host = url.hostname;
|
|
223
|
-
const port = parseInt(url.port || (protocol === 'https' ? 443 : 80));
|
|
224
|
-
const path = url.pathname; // auth is needed mostly for cloud providers such as LambdaTest
|
|
225
|
-
|
|
226
|
-
if (url.auth) {
|
|
227
|
-
const auth = url.auth.split(':');
|
|
228
|
-
this.options.wdioOpts = {
|
|
229
|
-
user: auth[0],
|
|
230
|
-
key: auth[1]
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const wdioOpts = { ...(this.options.wdioOpts || {}),
|
|
235
|
-
protocol: protocol,
|
|
236
|
-
hostname: host,
|
|
237
|
-
port: port,
|
|
238
|
-
path: path,
|
|
239
|
-
capabilities: this.caps,
|
|
240
|
-
logLevel: 'silent',
|
|
241
|
-
runner: 'repl',
|
|
242
|
-
waitforTimeout: 5000,
|
|
243
|
-
// increase the default 3000
|
|
244
|
-
connectionRetryTimeout: 310 * 1000,
|
|
245
|
-
connectionRetryCount: 1
|
|
246
|
-
};
|
|
247
|
-
let initError = null;
|
|
248
|
-
|
|
249
|
-
const _this = this;
|
|
250
|
-
|
|
251
|
-
const provider = _utils.default.determineProvider(wdioOpts);
|
|
252
|
-
|
|
253
|
-
if (provider === _utils.default.provider.PERFECTO) {
|
|
254
|
-
wdioOpts.path = '/nexperience/perfectomobile/wd/hub';
|
|
255
|
-
wdioOpts.port = 80;
|
|
256
|
-
wdioOpts.protocol = 'http';
|
|
257
|
-
wdioOpts.openDeviceTimeout = 15;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
let name = 'name';
|
|
261
|
-
|
|
262
|
-
if (wdioOpts.capabilities['perfectoMobile:options'] && wdioOpts.capabilities['perfectoMobile:options']['name']) {
|
|
263
|
-
name = wdioOpts.capabilities['perfectoMobile:options']['name'];
|
|
264
|
-
delete wdioOpts.capabilities['perfectoMobile:options'];
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (wdioOpts.capabilities['lambda:options'] && wdioOpts.capabilities['lambda:options']['name']) {
|
|
268
|
-
name = wdioOpts.capabilities['lambda:options']['name'];
|
|
269
|
-
delete wdioOpts.capabilities['lambda:options'];
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (wdioOpts.capabilities['testingBot:options'] && wdioOpts.capabilities['testingBot:options']['name']) {
|
|
273
|
-
name = wdioOpts.capabilities['testingBot:options']['name'];
|
|
274
|
-
delete wdioOpts.capabilities['testingBot:options'];
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (wdioOpts.capabilities['bstack:options'] && wdioOpts.capabilities['bstack:options']['name']) {
|
|
278
|
-
name = wdioOpts.capabilities['bstack:options']['name'];
|
|
279
|
-
delete wdioOpts.capabilities['bstack:options'];
|
|
280
|
-
} // set default browser for mobile web tests, if executed against remote devices of a cloud provider
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (defaultBrowser && provider) {
|
|
284
|
-
this.caps.browserName = wdioOpts.capabilities.browserName = DEFAULT_MOBILE_BROWSER;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
this.wdioOpts = wdioOpts;
|
|
288
|
-
|
|
289
|
-
try {
|
|
290
|
-
this.driver = await wdio.remote(wdioOpts);
|
|
291
|
-
this.driver.provider = provider;
|
|
292
|
-
|
|
293
|
-
if (this.options.seleniumBrowserTimeout) {
|
|
294
|
-
this.driver.seleniumBrowserTimeout = this.options.seleniumBrowserTimeout;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (this.options.seleniumTimeout) {
|
|
298
|
-
this.driver.seleniumTimeout = this.options.seleniumTimeout;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (provider === _utils.default.provider.PERFECTO) {
|
|
302
|
-
const perfectoExecutionContext = await new _perfectoReporting.default.Perfecto.PerfectoExecutionContext({
|
|
303
|
-
webdriver: {
|
|
304
|
-
executeScript: async (command, params) => {
|
|
305
|
-
return await this.driver.execute(command, params);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
this.reportingClient = new _perfectoReporting.default.Perfecto.PerfectoReportingClient(perfectoExecutionContext);
|
|
310
|
-
await this.reportingClient.testStart(name);
|
|
311
|
-
}
|
|
312
|
-
} catch (e) {
|
|
313
|
-
throw _helper.default.getSeleniumInitError(e);
|
|
314
|
-
} // reset browser logs if auto collect logs option is enabled
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (this.options.collectBrowserLogs && this.caps.browserName === 'chrome') {
|
|
318
|
-
try {
|
|
319
|
-
// simply call this to clear the previous logs and start the test with the clean logs
|
|
320
|
-
await this.getBrowserLogs();
|
|
321
|
-
} catch (e) {
|
|
322
|
-
this.logger.error('Cannot retrieve browser logs.', e);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
if ([_utils.default.provider.LAMBDATEST, _utils.default.provider.BROWSERSTACK, _utils.default.provider.PERFECTO].includes(this.driver.provider) //['MicrosoftEdge', 'msedge', 'Edge', 'Internet Explorer'].includes(this.driver.capabilities.browserName)
|
|
328
|
-
) {// do not maximize window if the test is executed against external cloud provider infrastructure
|
|
329
|
-
// as most of cloud providers do not support this functionality
|
|
330
|
-
} else {
|
|
331
|
-
// maximize browser window
|
|
332
|
-
await this.driver.maximizeWindow(); // set initial Timeout
|
|
333
|
-
|
|
334
|
-
await this.driver.setTimeout({
|
|
335
|
-
'implicit': this.waitForTimeout,
|
|
336
|
-
'pageLoad': this.waitForTimeout
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
} catch (err) {
|
|
340
|
-
throw new _OxygenError.default(_helper.default.errorCode.UNKNOWN_ERROR, err.message, _util.default.inspect(err));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
super.init(this.driver);
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* @function dispose
|
|
347
|
-
* @summary Ends the current session.
|
|
348
|
-
* @param {String=} status - Test status, either `passed` or `failed`.
|
|
349
|
-
*/
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
async dispose(status) {
|
|
353
|
-
this.transactions = {};
|
|
354
|
-
this._whenWebModuleDispose = (0, _when.defer)();
|
|
355
|
-
|
|
356
|
-
if (!status) {
|
|
357
|
-
status = 'passed';
|
|
358
|
-
|
|
359
|
-
if (this.rs.steps && Array.isArray(this.rs.steps) && this.rs.steps.length > 0) {
|
|
360
|
-
const failedFinded = this.rs.steps.find(item => item.status === 'failed');
|
|
361
|
-
|
|
362
|
-
if (failedFinded) {
|
|
363
|
-
status = 'failed';
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
if (this.driver && this.isInitialized) {
|
|
369
|
-
try {
|
|
370
|
-
status = status.toUpperCase();
|
|
371
|
-
|
|
372
|
-
if (this.driver.provider === _utils.default.provider.SAUCELABS) {
|
|
373
|
-
const username = this.wdioOpts.capabilities['sauce:options']['username'];
|
|
374
|
-
const accessKey = this.wdioOpts.capabilities['sauce:options']['accessKey'];
|
|
375
|
-
const passed = status === 'PASSED';
|
|
376
|
-
const id = this.driver.sessionId;
|
|
377
|
-
const body = "{\"passed\":" + passed + "}";
|
|
378
|
-
const myAccount = new _saucelabs.default({
|
|
379
|
-
user: username,
|
|
380
|
-
key: accessKey
|
|
381
|
-
});
|
|
382
|
-
await myAccount.updateJob(username, id, body);
|
|
383
|
-
await myAccount.stopJob(username, id);
|
|
384
|
-
} else if (this.driver.provider === _utils.default.provider.LAMBDATEST) {
|
|
385
|
-
await this._sendResultStatusToLambdaTest(status);
|
|
386
|
-
await this.deleteSession();
|
|
387
|
-
} else if (this.driver.provider === _utils.default.provider.TESTINGBOT) {
|
|
388
|
-
await this._sendResultStatusToTestingBot(status);
|
|
389
|
-
await this.deleteSession();
|
|
390
|
-
} else if (this.driver.provider === _utils.default.provider.PERFECTO) {
|
|
391
|
-
await this.reportingClient.testStop({
|
|
392
|
-
status: status === 'PASSED' ? _perfectoReporting.default.Constants.results.passed : _perfectoReporting.default.Constants.results.failed
|
|
393
|
-
});
|
|
394
|
-
} else if (this.driver.provider === _utils.default.provider.BROWSERSTACK) {
|
|
395
|
-
await this._sendResultStatusToBrowserstack(status);
|
|
396
|
-
await this.deleteSession();
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
if (this.driver.provider === null && ['PASSED', 'FAILED'].includes(status)) {
|
|
400
|
-
await this.closeBrowserWindows(status);
|
|
401
|
-
} else {
|
|
402
|
-
// canceled or other status
|
|
403
|
-
this.disposeContinue();
|
|
404
|
-
}
|
|
405
|
-
} catch (e) {
|
|
406
|
-
this.logger.warn('Error disposing driver: ', e); // ignore any errors at disposal stage
|
|
407
|
-
}
|
|
408
|
-
} else {
|
|
409
|
-
this.disposeContinue();
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
return this._whenWebModuleDispose.promise;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
async deleteSession() {
|
|
416
|
-
try {
|
|
417
|
-
if (this.driver && this.driver.deleteSession) {
|
|
418
|
-
if (this.seleniumSessionTimeout) {// ignore
|
|
419
|
-
// deleteSession will take 5 min to call
|
|
420
|
-
} else {
|
|
421
|
-
await this.driver.deleteSession();
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
} catch (e) {
|
|
425
|
-
this.logger.error('deleteSession error', e);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
async closeBrowserWindows(status) {
|
|
430
|
-
if (status && 'FAILED' === status.toUpperCase() && this.options && this.options.seleniumPid) {
|
|
431
|
-
this.disposeContinue(status);
|
|
432
|
-
} else {
|
|
433
|
-
try {
|
|
434
|
-
await this.deleteSession();
|
|
435
|
-
} catch (e) {
|
|
436
|
-
this.logger.warn('Failed to close browser windows:', e);
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
this.disposeContinue();
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
disposeContinue(status) {
|
|
444
|
-
this.driver = null;
|
|
445
|
-
this.lastNavigationStartTime = null;
|
|
446
|
-
super.dispose(); // cleanup chromedriver's only when running from within the IDE and test did not fail
|
|
447
|
-
|
|
448
|
-
if (this.options && this.options.seleniumPid && (!status || 'FAILED' !== status.toUpperCase())) {
|
|
449
|
-
try {
|
|
450
|
-
if (process.platform === 'win32') {
|
|
451
|
-
(0, _child_process.execSync)('taskkill /IM chromedriver.exe /F', {
|
|
452
|
-
stdio: ['ignore', 'ignore', 'ignore']
|
|
453
|
-
});
|
|
454
|
-
} else {
|
|
455
|
-
let pgrepResult = (0, _child_process.execSync)("pgrep -d' ' chromedriver");
|
|
456
|
-
|
|
457
|
-
if (pgrepResult && pgrepResult.toString) {
|
|
458
|
-
pgrepResult = pgrepResult.toString();
|
|
459
|
-
|
|
460
|
-
if (pgrepResult) {
|
|
461
|
-
(0, _child_process.execSync)('kill -9 ' + pgrepResult, {
|
|
462
|
-
stdio: ['ignore', 'ignore', 'ignore']
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
} catch (e) {// ignore errors
|
|
468
|
-
}
|
|
469
|
-
} // cleanup edgedriver's only when running from within the IDE and test did not fail
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
if (this.options && this.options.seleniumPid && (!status || 'FAILED' !== status.toUpperCase())) {
|
|
473
|
-
try {
|
|
474
|
-
if (process.platform === 'win32') {// ignore for now
|
|
475
|
-
} else {
|
|
476
|
-
let pgrepResult = (0, _child_process.execSync)("pgrep -d' ' msedgedriver");
|
|
477
|
-
|
|
478
|
-
if (pgrepResult && pgrepResult.toString) {
|
|
479
|
-
pgrepResult = pgrepResult.toString();
|
|
480
|
-
|
|
481
|
-
if (pgrepResult) {
|
|
482
|
-
(0, _child_process.execSync)('kill -9 ' + pgrepResult, {
|
|
483
|
-
stdio: ['ignore', 'ignore', 'ignore']
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
} catch (e) {// ignore errors
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
this._whenWebModuleDispose.resolve(null);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
_iterationStart() {
|
|
496
|
-
// clear transaction name saved in previous iteration if any
|
|
497
|
-
global._lastTransactionName = null;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
async _iterationEnd(error) {
|
|
501
|
-
if (error && error.type === _helper.default.errorCode.SELENIUM_SESSION_TIMEOUT) {
|
|
502
|
-
this.seleniumSessionTimeout = true;
|
|
503
|
-
return;
|
|
504
|
-
} else {
|
|
505
|
-
this.seleniumSessionTimeout = false;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (!this.isInitialized) {
|
|
509
|
-
return;
|
|
510
|
-
} // collect browser logs for this session
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (this.options.collectBrowserLogs === true && this.caps.browserName === 'chrome') {
|
|
514
|
-
try {
|
|
515
|
-
const logs = await this.getBrowserLogs();
|
|
516
|
-
|
|
517
|
-
if (logs && Array.isArray(logs)) {
|
|
518
|
-
for (var log of logs) {
|
|
519
|
-
this.rs.logs.push(this._adjustBrowserLog(log));
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
} catch (e) {
|
|
523
|
-
// ignore errors
|
|
524
|
-
this.logger.error('Cannot retrieve browser logs.', e);
|
|
525
|
-
}
|
|
526
|
-
} // TODO: should clear transactions to avoid duplicate names across iterations
|
|
527
|
-
// also should throw on duplicate names.
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
if (this.options.recordHAR && this.caps.browserName === 'chrome') {
|
|
531
|
-
// there might be no transactions set if test fails before web.transaction command
|
|
532
|
-
if (global._lastTransactionName) {
|
|
533
|
-
this.transactions[global._lastTransactionName] = await this._getHAR();
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
this.rs.har = this.transactions;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
_isAction(name) {
|
|
541
|
-
return ACTION_COMMANDS.includes(name);
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
_takeScreenshotSilent(name) {
|
|
545
|
-
if (!NO_SCREENSHOT_COMMANDS.includes(name)) {
|
|
546
|
-
let error;
|
|
547
|
-
|
|
548
|
-
try {
|
|
549
|
-
if (this.driver && this.driver.takeScreenshot) {
|
|
550
|
-
let retval;
|
|
551
|
-
this.driver.call(() => {
|
|
552
|
-
return new Promise((resolve, reject) => {
|
|
553
|
-
const waitUntilRetVal = this.driver.waitUntil(async () => {
|
|
554
|
-
try {
|
|
555
|
-
let images = []; // collect all (screenshot and title) images
|
|
556
|
-
|
|
557
|
-
const handles = await this.driver.getWindowHandles();
|
|
558
|
-
|
|
559
|
-
if (handles && Array.isArray(handles) && handles.length > 0) {
|
|
560
|
-
for (const handle of handles) {
|
|
561
|
-
await this.driver.switchToWindow(handle);
|
|
562
|
-
const image = await this.driver.takeScreenshot();
|
|
563
|
-
const title = await this.driver.getTitle();
|
|
564
|
-
|
|
565
|
-
if (title) {
|
|
566
|
-
const textToImage = require('text-to-image');
|
|
567
|
-
|
|
568
|
-
let titleImage = await textToImage.generate(title, {
|
|
569
|
-
debug: false,
|
|
570
|
-
fontFamily: 'Arial'
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
if (titleImage && typeof titleImage === 'string') {
|
|
574
|
-
titleImage = titleImage.replace('data:image/png;base64,', '');
|
|
575
|
-
images.push(titleImage);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
images.push(image);
|
|
580
|
-
}
|
|
581
|
-
} // merge all images into one
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const mergedImage = await (0, _imgMerge.default)(images, {
|
|
585
|
-
direction: true
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
if (mergedImage && typeof mergedImage === 'string') {
|
|
589
|
-
retval = mergedImage.replace('data:image/jpeg;base64,', '');
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
return true;
|
|
593
|
-
} catch (e) {
|
|
594
|
-
error = e;
|
|
595
|
-
return false;
|
|
596
|
-
}
|
|
597
|
-
}, {
|
|
598
|
-
timeout: 30 * 1000
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
if (waitUntilRetVal && waitUntilRetVal.then) {
|
|
602
|
-
waitUntilRetVal.then(() => {
|
|
603
|
-
resolve();
|
|
604
|
-
}).catch(err => {
|
|
605
|
-
reject(err);
|
|
606
|
-
});
|
|
607
|
-
} else {
|
|
608
|
-
resolve();
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
});
|
|
612
|
-
|
|
613
|
-
if (error) {
|
|
614
|
-
this.logger.error('Cannot get screenshot', error);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
return retval;
|
|
618
|
-
}
|
|
619
|
-
} catch (e) {
|
|
620
|
-
this.logger.error('Cannot get screenshot', e);
|
|
621
|
-
|
|
622
|
-
if (error) {
|
|
623
|
-
this.logger.error('Cannot get screenshot inner error', error);
|
|
624
|
-
} // ignore
|
|
625
|
-
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
_adjustBrowserLog(log) {
|
|
631
|
-
if (!log || typeof log !== 'object') {
|
|
632
|
-
return null;
|
|
633
|
-
} // TODO: convert log.timestamp from the browser time zone to the local one (so we can later correlate between steps and logs)
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
return {
|
|
637
|
-
time: log.timestamp,
|
|
638
|
-
msg: log.message,
|
|
639
|
-
// convert SEVERE log level to ERROR
|
|
640
|
-
level: log.level === 'SEVERE' ? 'ERROR' : log.level,
|
|
641
|
-
src: 'browser'
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
/*
|
|
645
|
-
* FIXME: There is a bug with IE. See the comment within function body.
|
|
646
|
-
*
|
|
647
|
-
* domContentLoaded (aka First Visual Time)- Represents the difference between domContentLoadedEventStart and navigationStart.
|
|
648
|
-
* load (aka Full Load Time) - Represents the difference between loadEventStart and navigationStart.
|
|
649
|
-
*
|
|
650
|
-
* The processing model:
|
|
651
|
-
*
|
|
652
|
-
* 1. navigationStart - The browser has requested the document.
|
|
653
|
-
* 2. ... - Not relevant to us. See http://www.w3.org/TR/navigation-timing/#process for more information.
|
|
654
|
-
* 3. domLoading - The browser starts parsing the document.
|
|
655
|
-
* 4. domInteractive - The browser has finished parsing the document and the user can interact with the page.
|
|
656
|
-
* 5. domContentLoadedEventStart - The document has been completely loaded and parsed and deferred scripts, if any, have executed.
|
|
657
|
-
* Async scripts, if any, might or might not have executed.
|
|
658
|
-
* Stylesheets[1], images, and subframes might or might not have finished loading.
|
|
659
|
-
* [1] - Stylesheets /usually/ defer this event! - http://molily.de/weblog/domcontentloaded
|
|
660
|
-
* 6. domContentLoadedEventEnd - The DOMContentLoaded event callback, if any, finished executing. E.g.
|
|
661
|
-
* document.addEventListener("DOMContentLoaded", function(event) {
|
|
662
|
-
* console.log("DOM fully loaded and parsed");
|
|
663
|
-
* });
|
|
664
|
-
* 7. domComplete - The DOM tree is completely built. Async scripts, if any, have executed.
|
|
665
|
-
* 8. loadEventStart - The browser have finished loading all the resources like images, swf, etc.
|
|
666
|
-
* 9. loadEventEnd - The load event callback, if any, finished executing.
|
|
667
|
-
*/
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
_getStats(commandName) {
|
|
671
|
-
if (this.options.fetchStats && this.isInitialized && this._isAction(commandName)) {
|
|
672
|
-
var navigationStart;
|
|
673
|
-
var domContentLoaded = 0;
|
|
674
|
-
var load = 0;
|
|
675
|
-
var samePage = false; // TODO: handle following situation:
|
|
676
|
-
// if navigateStart equals to the one we got from previous attempt (we need to save it)
|
|
677
|
-
// it means we are still on the same page and don't need to record load/domContentLoaded times
|
|
678
|
-
|
|
679
|
-
try {
|
|
680
|
-
this.driver.call(() => {
|
|
681
|
-
return new Promise((resolve, reject) => {
|
|
682
|
-
let lastError = false;
|
|
683
|
-
const waitUntilRetVal = this.driver.waitUntil(async () => {
|
|
684
|
-
try {
|
|
685
|
-
/*global window*/
|
|
686
|
-
var timings = await this.driver.execute(function () {
|
|
687
|
-
return {
|
|
688
|
-
navigationStart: window.performance.timing.navigationStart,
|
|
689
|
-
domContentLoadedEventStart: window.performance.timing.domContentLoadedEventStart,
|
|
690
|
-
loadEventStart: window.performance.timing.loadEventStart
|
|
691
|
-
};
|
|
692
|
-
});
|
|
693
|
-
lastError = false;
|
|
694
|
-
|
|
695
|
-
if (timings.domContentLoadedEventStart > 0 && timings.loadEventStart > 0) {
|
|
696
|
-
samePage = this.lastNavigationStartTime && this.lastNavigationStartTime == timings.navigationStart;
|
|
697
|
-
navigationStart = this.lastNavigationStartTime = timings.navigationStart;
|
|
698
|
-
var domContentLoadedEventStart = timings.domContentLoadedEventStart;
|
|
699
|
-
var loadEventStart = timings.loadEventStart;
|
|
700
|
-
domContentLoaded = domContentLoadedEventStart - navigationStart;
|
|
701
|
-
load = loadEventStart - navigationStart;
|
|
702
|
-
return domContentLoadedEventStart > 0 && loadEventStart > 0;
|
|
703
|
-
} else {
|
|
704
|
-
return false;
|
|
705
|
-
}
|
|
706
|
-
} catch (executeError) {
|
|
707
|
-
// collect error inside driver.execute or driver.waitUntil
|
|
708
|
-
lastError = executeError;
|
|
709
|
-
}
|
|
710
|
-
}, {
|
|
711
|
-
timeout: 30 * 1000
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
if (waitUntilRetVal && waitUntilRetVal.then) {
|
|
715
|
-
waitUntilRetVal.then(() => {
|
|
716
|
-
if (lastError) {
|
|
717
|
-
// print error from driver.execute or driver.waitUntil
|
|
718
|
-
console.log(lastError);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
resolve();
|
|
722
|
-
}).catch(err => {
|
|
723
|
-
if (lastError) {
|
|
724
|
-
// print error from driver.execute or driver.waitUntil
|
|
725
|
-
console.log(lastError);
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
reject(err);
|
|
729
|
-
});
|
|
730
|
-
} else {
|
|
731
|
-
resolve();
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
});
|
|
735
|
-
} catch (e) {
|
|
736
|
-
return {}; // couldn't get timings.
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
this.lastNavigationStartTime = navigationStart;
|
|
740
|
-
return samePage ? {} : {
|
|
741
|
-
DomContentLoadedEvent: domContentLoaded,
|
|
742
|
-
LoadEvent: load
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
return {};
|
|
747
|
-
}
|
|
748
|
-
/**
|
|
749
|
-
* @summary Opens new transaction.
|
|
750
|
-
* @description The transaction will persist till a new one is opened. Transaction names must be
|
|
751
|
-
* unique.
|
|
752
|
-
* @function transaction
|
|
753
|
-
* @param {String} name - The transaction name.
|
|
754
|
-
*/
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
async transaction(name) {
|
|
758
|
-
if (global._lastTransactionName) {
|
|
759
|
-
this.transactions[global._lastTransactionName] = null;
|
|
760
|
-
|
|
761
|
-
if (this.options.recordHAR && this.isInitialized && this.caps.browserName === 'chrome') {
|
|
762
|
-
this.transactions[global._lastTransactionName] = await this._getHAR();
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
if (typeof this.transactions[name] !== 'undefined') {
|
|
767
|
-
const counter = Object.keys(this.transactions).filter(item => item.startsWith(name)).length + 1;
|
|
768
|
-
global._lastTransactionName = name + ' (#' + counter + ')';
|
|
769
|
-
} else {
|
|
770
|
-
global._lastTransactionName = name;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
_loadHelperFunctions() {
|
|
775
|
-
this.helpers.getWdioLocator = _utils.default.getWdioLocator;
|
|
776
|
-
this.helpers.matchPattern = _utils.default.matchPattern;
|
|
777
|
-
this.helpers.getElement = _utils.default.getElement;
|
|
778
|
-
this.helpers.getElements = _utils.default.getElements;
|
|
779
|
-
this.helpers.getChildElement = _utils.default.getChildElement;
|
|
780
|
-
this.helpers.getChildElements = _utils.default.getChildElements;
|
|
781
|
-
this.helpers.setTimeoutImplicit = _utils.default.setTimeoutImplicit;
|
|
782
|
-
this.helpers.restoreTimeoutImplicit = _utils.default.restoreTimeoutImplicit;
|
|
783
|
-
this.helpers.assertArgument = _utils.default.assertArgument;
|
|
784
|
-
this.helpers.assertArgumentNonEmptyString = _utils.default.assertArgumentNonEmptyString;
|
|
785
|
-
this.helpers.assertArgumentNumber = _utils.default.assertArgumentNumber;
|
|
786
|
-
this.helpers.assertArgumentNumberNonNegative = _utils.default.assertArgumentNumberNonNegative;
|
|
787
|
-
this.helpers.assertArgumentBool = _utils.default.assertArgumentBool;
|
|
788
|
-
this.helpers.assertArgumentBoolOptional = _utils.default.assertArgumentBoolOptional;
|
|
789
|
-
this.helpers.assertArgumentTimeout = _utils.default.assertArgumentTimeout;
|
|
790
|
-
this.helpers.assertArgumentString = _utils.default.assertArgumentString;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
async _getHAR() {
|
|
794
|
-
try {
|
|
795
|
-
const types = await this.driver.getLogTypes();
|
|
796
|
-
|
|
797
|
-
if (types.includes('performance')) {
|
|
798
|
-
const logs = await this.driver.getLogs('performance'); // in one instance, logs was not iterable for some reason - hence the following check:
|
|
799
|
-
|
|
800
|
-
if (!logs || typeof logs[Symbol.iterator] !== 'function') {
|
|
801
|
-
this.logger.error('getHAR: logs not iterable: ' + JSON.stringify(logs));
|
|
802
|
-
return null;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
const events = [];
|
|
806
|
-
|
|
807
|
-
for (let log of logs) {
|
|
808
|
-
const msgObj = JSON.parse(log.message); // returned as string
|
|
809
|
-
|
|
810
|
-
events.push(msgObj.message);
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
const har = (0, _chromeHar.harFromMessages)(events);
|
|
814
|
-
return JSON.stringify(har);
|
|
815
|
-
} else {
|
|
816
|
-
return null;
|
|
817
|
-
}
|
|
818
|
-
} catch (e) {
|
|
819
|
-
this.logger.error('Unable to fetch HAR: ' + e.toString());
|
|
820
|
-
return null;
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
async checkWaitForAngular() {
|
|
825
|
-
if (this.autoWaitForAngular) {
|
|
826
|
-
await this.waitForAngular(this.autoWaitForAngularRootSelector, this.autoWaitForAngularTimeout);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
async _sendResultStatusToLambdaTest(status) {
|
|
831
|
-
return new Promise((resolve, reject) => {
|
|
832
|
-
const lambdaCredentials = {
|
|
833
|
-
username: this.wdioOpts.user,
|
|
834
|
-
accessKey: this.wdioOpts.key
|
|
835
|
-
};
|
|
836
|
-
const sessionId = this.driver.sessionId;
|
|
837
|
-
|
|
838
|
-
const lambdaAutomationClient = _nodeRestClient.default.AutomationClient(lambdaCredentials);
|
|
839
|
-
|
|
840
|
-
const requestBody = {
|
|
841
|
-
status_ind: status === 'PASSED' ? 'passed' : 'failed'
|
|
842
|
-
};
|
|
843
|
-
|
|
844
|
-
try {
|
|
845
|
-
lambdaAutomationClient.updateSessionById(sessionId, requestBody, error => {
|
|
846
|
-
resolve();
|
|
847
|
-
});
|
|
848
|
-
} catch (e) {
|
|
849
|
-
this.logger.error('Unable to send result status to LambdaTest: ' + e.toString());
|
|
850
|
-
resolve();
|
|
851
|
-
}
|
|
852
|
-
});
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
async _sendResultStatusToTestingBot(status) {
|
|
856
|
-
return new Promise((resolve, reject) => {
|
|
857
|
-
const sessionId = this.driver.sessionId;
|
|
858
|
-
const tb = new _testingbotApi.default({
|
|
859
|
-
api_key: this.wdioOpts.user,
|
|
860
|
-
api_secret: this.wdioOpts.key
|
|
861
|
-
});
|
|
862
|
-
const testData = {
|
|
863
|
-
"test[success]": status === 'PASSED' ? "1" : "0"
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
try {
|
|
867
|
-
tb.updateTest(testData, sessionId, function (error, testDetails) {
|
|
868
|
-
resolve();
|
|
869
|
-
});
|
|
870
|
-
} catch (e) {
|
|
871
|
-
this.logger.error('Unable to send result status to TestingBot: ' + e.toString());
|
|
872
|
-
resolve();
|
|
873
|
-
}
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
async _sendResultStatusToBrowserstack(status) {
|
|
878
|
-
return new Promise((resolve, reject) => {
|
|
879
|
-
const requestBody = {
|
|
880
|
-
status: status === 'PASSED' ? 'passed' : 'failed'
|
|
881
|
-
};
|
|
882
|
-
const options = {
|
|
883
|
-
url: `https://api.browserstack.com/automate/sessions/${this.driver.sessionId}.json`,
|
|
884
|
-
method: 'PUT',
|
|
885
|
-
json: true,
|
|
886
|
-
rejectUnauthorized: false,
|
|
887
|
-
body: requestBody,
|
|
888
|
-
'auth': {
|
|
889
|
-
'user': this.wdioOpts.user,
|
|
890
|
-
'pass': this.wdioOpts.key,
|
|
891
|
-
'sendImmediately': false
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
|
|
895
|
-
try {
|
|
896
|
-
(0, _request.default)(options, (err, res, body) => {
|
|
897
|
-
resolve();
|
|
898
|
-
});
|
|
899
|
-
} catch (e) {
|
|
900
|
-
this.logger.error('Unable to send result status to Browserstack: ' + e.toString());
|
|
901
|
-
resolve();
|
|
902
|
-
}
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
exports.default = WebModule;
|
|
909
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9veF9tb2R1bGVzL21vZHVsZS13ZWIuanMiXSwibmFtZXMiOlsiTU9EVUxFX05BTUUiLCJERUZBVUxUX1NFTEVOSVVNX1VSTCIsIkRFRkFVTFRfQlJPV1NFUl9OQU1FIiwiREVGQVVMVF9NT0JJTEVfQlJPV1NFUiIsIk5PX1NDUkVFTlNIT1RfQ09NTUFORFMiLCJBQ1RJT05fQ09NTUFORFMiLCJERUZBVUxUX1dBSVRfVElNRU9VVCIsIldlYk1vZHVsZSIsIldlYkRyaXZlck1vZHVsZSIsImNvbnN0cnVjdG9yIiwib3B0aW9ucyIsImNvbnRleHQiLCJycyIsImxvZ2dlciIsIm1vZHVsZXMiLCJzZXJ2aWNlcyIsInRyYW5zYWN0aW9ucyIsImxhc3ROYXZpZ2F0aW9uU3RhcnRUaW1lIiwiaGVscGVycyIsIl9sb2FkSGVscGVyRnVuY3Rpb25zIiwiT3hFcnJvciIsImVyckhlbHBlciIsIndhaXRGb3JUaW1lb3V0IiwibmFtZSIsImdldERyaXZlciIsImdldENhcGFiaWxpdGllcyIsImNhcHMiLCJpbml0Iiwic2VsZW5pdW1VcmwiLCJpc0luaXRpYWxpemVkIiwiY3R4IiwiZGVmYXVsdEJyb3dzZXIiLCJicm93c2VyTmFtZSIsImVycm9yQ29kZSIsIklOVkFMSURfQ0FQQUJJTElUSUVTIiwidG9Mb3dlckNhc2UiLCJyZWNvcmRIQVIiLCJicm93c2VyIiwicGVyZm9ybWFuY2UiLCJ1cmwiLCJVUkwiLCJwYXJzZSIsInByb3RvY29sIiwicmVwbGFjZSIsImhvc3QiLCJob3N0bmFtZSIsInBvcnQiLCJwYXJzZUludCIsInBhdGgiLCJwYXRobmFtZSIsImF1dGgiLCJzcGxpdCIsIndkaW9PcHRzIiwidXNlciIsImtleSIsImNhcGFiaWxpdGllcyIsImxvZ0xldmVsIiwicnVubmVyIiwid2FpdGZvclRpbWVvdXQiLCJjb25uZWN0aW9uUmV0cnlUaW1lb3V0IiwiY29ubmVjdGlvblJldHJ5Q291bnQiLCJpbml0RXJyb3IiLCJfdGhpcyIsInByb3ZpZGVyIiwibW9kVXRpbHMiLCJkZXRlcm1pbmVQcm92aWRlciIsIlBFUkZFQ1RPIiwib3BlbkRldmljZVRpbWVvdXQiLCJkcml2ZXIiLCJ3ZGlvIiwicmVtb3RlIiwic2VsZW5pdW1Ccm93c2VyVGltZW91dCIsInNlbGVuaXVtVGltZW91dCIsInBlcmZlY3RvRXhlY3V0aW9uQ29udGV4dCIsInBlcmZlY3RvUmVwb3J0aW5nIiwiUGVyZmVjdG8iLCJQZXJmZWN0b0V4ZWN1dGlvbkNvbnRleHQiLCJ3ZWJkcml2ZXIiLCJleGVjdXRlU2NyaXB0IiwiY29tbWFuZCIsInBhcmFtcyIsImV4ZWN1dGUiLCJyZXBvcnRpbmdDbGllbnQiLCJQZXJmZWN0b1JlcG9ydGluZ0NsaWVudCIsInRlc3RTdGFydCIsImUiLCJnZXRTZWxlbml1bUluaXRFcnJvciIsImNvbGxlY3RCcm93c2VyTG9ncyIsImdldEJyb3dzZXJMb2dzIiwiZXJyb3IiLCJMQU1CREFURVNUIiwiQlJPV1NFUlNUQUNLIiwiaW5jbHVkZXMiLCJtYXhpbWl6ZVdpbmRvdyIsInNldFRpbWVvdXQiLCJlcnIiLCJVTktOT1dOX0VSUk9SIiwibWVzc2FnZSIsInV0aWwiLCJpbnNwZWN0IiwiZGlzcG9zZSIsInN0YXR1cyIsIl93aGVuV2ViTW9kdWxlRGlzcG9zZSIsInN0ZXBzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiZmFpbGVkRmluZGVkIiwiZmluZCIsIml0ZW0iLCJ0b1VwcGVyQ2FzZSIsIlNBVUNFTEFCUyIsInVzZXJuYW1lIiwiYWNjZXNzS2V5IiwicGFzc2VkIiwiaWQiLCJzZXNzaW9uSWQiLCJib2R5IiwibXlBY2NvdW50IiwiU2F1Y2VMYWJzIiwidXBkYXRlSm9iIiwic3RvcEpvYiIsIl9zZW5kUmVzdWx0U3RhdHVzVG9MYW1iZGFUZXN0IiwiZGVsZXRlU2Vzc2lvbiIsIlRFU1RJTkdCT1QiLCJfc2VuZFJlc3VsdFN0YXR1c1RvVGVzdGluZ0JvdCIsInRlc3RTdG9wIiwiQ29uc3RhbnRzIiwicmVzdWx0cyIsImZhaWxlZCIsIl9zZW5kUmVzdWx0U3RhdHVzVG9Ccm93c2Vyc3RhY2siLCJjbG9zZUJyb3dzZXJXaW5kb3dzIiwiZGlzcG9zZUNvbnRpbnVlIiwid2FybiIsInByb21pc2UiLCJzZWxlbml1bVNlc3Npb25UaW1lb3V0Iiwic2VsZW5pdW1QaWQiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJzdGRpbyIsInBncmVwUmVzdWx0IiwidG9TdHJpbmciLCJyZXNvbHZlIiwiX2l0ZXJhdGlvblN0YXJ0IiwiZ2xvYmFsIiwiX2xhc3RUcmFuc2FjdGlvbk5hbWUiLCJfaXRlcmF0aW9uRW5kIiwidHlwZSIsImVycm9ySGVscGVyIiwiU0VMRU5JVU1fU0VTU0lPTl9USU1FT1VUIiwibG9ncyIsImxvZyIsInB1c2giLCJfYWRqdXN0QnJvd3NlckxvZyIsIl9nZXRIQVIiLCJoYXIiLCJfaXNBY3Rpb24iLCJfdGFrZVNjcmVlbnNob3RTaWxlbnQiLCJ0YWtlU2NyZWVuc2hvdCIsInJldHZhbCIsImNhbGwiLCJQcm9taXNlIiwicmVqZWN0Iiwid2FpdFVudGlsUmV0VmFsIiwid2FpdFVudGlsIiwiaW1hZ2VzIiwiaGFuZGxlcyIsImdldFdpbmRvd0hhbmRsZXMiLCJoYW5kbGUiLCJzd2l0Y2hUb1dpbmRvdyIsImltYWdlIiwidGl0bGUiLCJnZXRUaXRsZSIsInRleHRUb0ltYWdlIiwicmVxdWlyZSIsInRpdGxlSW1hZ2UiLCJnZW5lcmF0ZSIsImRlYnVnIiwiZm9udEZhbWlseSIsIm1lcmdlZEltYWdlIiwiZGlyZWN0aW9uIiwidGltZW91dCIsInRoZW4iLCJjYXRjaCIsInRpbWUiLCJ0aW1lc3RhbXAiLCJtc2ciLCJsZXZlbCIsInNyYyIsIl9nZXRTdGF0cyIsImNvbW1hbmROYW1lIiwiZmV0Y2hTdGF0cyIsIm5hdmlnYXRpb25TdGFydCIsImRvbUNvbnRlbnRMb2FkZWQiLCJsb2FkIiwic2FtZVBhZ2UiLCJsYXN0RXJyb3IiLCJ0aW1pbmdzIiwid2luZG93IiwidGltaW5nIiwiZG9tQ29udGVudExvYWRlZEV2ZW50U3RhcnQiLCJsb2FkRXZlbnRTdGFydCIsImV4ZWN1dGVFcnJvciIsImNvbnNvbGUiLCJEb21Db250ZW50TG9hZGVkRXZlbnQiLCJMb2FkRXZlbnQiLCJ0cmFuc2FjdGlvbiIsImNvdW50ZXIiLCJPYmplY3QiLCJrZXlzIiwiZmlsdGVyIiwic3RhcnRzV2l0aCIsImdldFdkaW9Mb2NhdG9yIiwibWF0Y2hQYXR0ZXJuIiwiZ2V0RWxlbWVudCIsImdldEVsZW1lbnRzIiwiZ2V0Q2hpbGRFbGVtZW50IiwiZ2V0Q2hpbGRFbGVtZW50cyIsInNldFRpbWVvdXRJbXBsaWNpdCIsInJlc3RvcmVUaW1lb3V0SW1wbGljaXQiLCJhc3NlcnRBcmd1bWVudCIsImFzc2VydEFyZ3VtZW50Tm9uRW1wdHlTdHJpbmciLCJhc3NlcnRBcmd1bWVudE51bWJlciIsImFzc2VydEFyZ3VtZW50TnVtYmVyTm9uTmVnYXRpdmUiLCJhc3NlcnRBcmd1bWVudEJvb2wiLCJhc3NlcnRBcmd1bWVudEJvb2xPcHRpb25hbCIsImFzc2VydEFyZ3VtZW50VGltZW91dCIsImFzc2VydEFyZ3VtZW50U3RyaW5nIiwidHlwZXMiLCJnZXRMb2dUeXBlcyIsImdldExvZ3MiLCJTeW1ib2wiLCJpdGVyYXRvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJldmVudHMiLCJtc2dPYmoiLCJjaGVja1dhaXRGb3JBbmd1bGFyIiwiYXV0b1dhaXRGb3JBbmd1bGFyIiwid2FpdEZvckFuZ3VsYXIiLCJhdXRvV2FpdEZvckFuZ3VsYXJSb290U2VsZWN0b3IiLCJhdXRvV2FpdEZvckFuZ3VsYXJUaW1lb3V0IiwibGFtYmRhQ3JlZGVudGlhbHMiLCJsYW1iZGFBdXRvbWF0aW9uQ2xpZW50IiwibGFtYmRhUmVzdENsaWVudCIsIkF1dG9tYXRpb25DbGllbnQiLCJyZXF1ZXN0Qm9keSIsInN0YXR1c19pbmQiLCJ1cGRhdGVTZXNzaW9uQnlJZCIsInRiIiwiVGVzdGluZ0JvdCIsImFwaV9rZXkiLCJhcGlfc2VjcmV0IiwidGVzdERhdGEiLCJ1cGRhdGVUZXN0IiwidGVzdERldGFpbHMiLCJtZXRob2QiLCJq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Q0FDLFFBQUFBLE9BQU87QUFDVjtBQUNKLEtBZk0sQ0FBUDtBQWdCSDs7QUFFb0MsUUFBL0JaLCtCQUErQixDQUFDN0IsTUFBRCxFQUFTO0FBQzFDLFdBQU8sSUFBSTRELE9BQUosQ0FBWSxDQUFDbkIsT0FBRCxFQUFVb0IsTUFBVixLQUFxQjtBQUNwQyxZQUFNb0YsV0FBVyxHQUFHO0FBQ2hCakosUUFBQUEsTUFBTSxFQUFFQSxNQUFNLEtBQUssUUFBWCxHQUFzQixRQUF0QixHQUFpQztBQUR6QixPQUFwQjtBQUlBLFlBQU0zRixPQUFPLEdBQUc7QUFDWjZCLFFBQUFBLEdBQUcsRUFBRyxrREFBaUQsS0FBSzZCLE1BQUwsQ0FBWWdELFNBQVUsT0FEakU7QUFFWjRJLFFBQUFBLE1BQU0sRUFBRSxLQUZJO0FBR1pDLFFBQUFBLElBQUksRUFBRSxJQUhNO0FBSVpDLFFBQUFBLGtCQUFrQixFQUFFLEtBSlI7QUFLWjdJLFFBQUFBLElBQUksRUFBRWlJLFdBTE07QUFNWixnQkFBUTtBQUNKLGtCQUFRLEtBQUtsTSxRQUFMLENBQWNDLElBRGxCO0FBRUosa0JBQVEsS0FBS0QsUUFBTCxDQUFjRSxHQUZsQjtBQUdKLDZCQUFtQjtBQUhmO0FBTkksT0FBaEI7O0FBYUEsVUFBSTtBQUNBLDhCQUFRNUMsT0FBUixFQUFpQixDQUFDcUYsR0FBRCxFQUFNb0ssR0FBTixFQUFXOUksSUFBWCxLQUFvQjtBQUNqQ3lCLFVBQUFBLE9BQU87QUFDVixTQUZEO0FBR0gsT0FKRCxDQUlFLE9BQU96RCxDQUFQLEVBQVU7QUFDUixhQUFLeEUsTUFBTCxDQUFZNEUsS0FBWixDQUFrQixtREFBbURKLENBQUMsQ0FBQ3dELFFBQUYsRUFBckU7QUFDQUMsUUFBQUEsT0FBTztBQUNWO0FBQ0osS0ExQk0sQ0FBUDtBQTJCSDs7QUFod0JrRCIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXHJcbi8qXHJcbiAqIENvcHlyaWdodCAoQykgMjAxNS1wcmVzZW50IENsb3VkQmVhdCBMaW1pdGVkXHJcbiAqXHJcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XHJcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XHJcbiAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIGVpdGhlciB2ZXJzaW9uIDMgb2YgdGhlIExpY2Vuc2UsIG9yXHJcbiAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXHJcbiAqL1xyXG5cclxuJ3VzZSBzdHJpY3QnO1xyXG4vKipcclxuICogQG5hbWUgd2ViXHJcbiAqIEBkZXNjcmlwdGlvbiBQcm92aWRlcyBtZXRob2RzIGZvciBicm93c2VyIGF1dG9tYXRpb24uXHJcbiAqIEBzYW1wbGUgKipOb3RlczoqKiAgXHJcbiAqICAgXHJcbiAqIENvbW1hbmRzIHdoaWNoIG9wZXJhdGUgb24gZWxlbWVudHMgc3VjaCBhcyBjbGljaywgYXNzZXJ0LCB3YWl0Rm9yLCB0eXBlLCBzZWxlY3QsIGFuZCBvdGhlcnMgd2lsbCBhdXRvbWF0aWNhbGx5IHdhaXQgZm9yIGEgcGVyaW9kIG9mIHRpbWUgZm9yIHRoZSBlbGVtZW50IHRvIGFwcGVhciBpbiBET00gYW5kIGJlY29tZSB2aXNpYmxlLiBCeSBkZWZhdWx0IHRoaXMgcGVyaW9kIGVxdWFscyB0byA2MCBzZWNvbmRzLCBidXQgY2FuIGJlIGNoYW5nZWQgdXNpbmcgdGhlIGBzZXRUaW1lb3V0YGNvbW1hbmQuXHJcbiAqICAgXHJcbiAqICoqU3RyaW5nIG1hdGNoaW5nIHBhdHRlcm5zOioqIFxyXG4gKiBcclxuICogIENvbW1hbmRzIHdoaWNoIGV4cGVjdCBhIHN0cmluZyBtYXRjaGluZyBwYXR0ZXJuIGluIHRoZWlyIGFyZ3VtZW50cywgc3VwcG9ydCBmb2xsb3dpbmcgcGF0dGVybnMgdW5sZXNzIHNwZWNpZmllZCBvdGhlcndpc2U6XHJcbiAqIFxyXG4gKiAgKiBgcmVnZXg6UEFUVEVSTmAgLSBNYXRjaCB1c2luZyByZWd1bGFyIGV4cHJlc3Npb24uXHJcbiAqICAqIGByZWdleGk6UEFUVEVSTmAgLSBNYXRjaCB1c2luZyBjYXNlLWluc2Vuc2l0aXZlIHJlZ3VsYXIgZXhwcmVzc2lvbi5cclxuICogICogYGV4YWN0OlNUUklOR2AgLSBNYXRjaCB0aGUgc3RyaW5nIHZlcmJhdGltLlxyXG4gKiAgKiBgZ2xvYjpQQVRURVJOYCAtIE1hdGNoIHVzaW5nIGNhc2UtaW5zZW5zaXRpdmUgZ2xvYiBwYXR0ZXJuLiBgP2Agd2lsbCBtYXRjaCBhbnkgc2luZ2xlIGNoYXJhY3RlciBleGNlcHQgbmV3IGxpbmUgXFwoXFxuXFwpLiBgKmAgd2lsbCBtYXRjaCBhbnkgc2VxdWVuY2UgXFwoMCBvciBtb3JlXFwpIG9mIGNoYXJhY3RlcnMgZXhjZXB0IG5ldyBsaW5lLiBFbXB0eSAgICAgUEFUVEVSTiB3aWxsIG1hdGNoIG9ubHkgb3RoZXIgZW1wdHkgc3RyaW5ncy5cclxuICogICogYFBBVFRFUk5gIC0gU2FtZSBhcyBnbG9iIG1hdGNoaW5nLiAgXHJcbiAqXHJcbiAqICoqTG9jYXRvcnM6KiogXHJcbiAqIFxyXG4gKiAgQ29tbWFuZHMgd2hpY2ggZXhwZWN0IGFuIGVsZW1lbnQgbG9jYXRvciBpbiB0aGVpciBhcmd1bWVudHMsIHN1cHBvcnQgZm9sbG93aW5nIGxvY2F0b3IgdHlwZXMgdW5sZXNzIHNwZWNpZmllZCBvdGhlcndpc2U6XHJcbiAqIFxyXG4gKiAgKiBgaWQ9SURgIC0gTG9jYXRlcyBlbGVtZW50IGJ5IGl0cyBJRCBhdHRyaWJ1dGUuXHJcbiAqICAqIGBjc3M9Q1NTX1NFTEVDVE9SYCAtIExvY2F0ZXMgZWxlbWVudCB1c2luZyBhIENTUyBzZWxlY3Rvci5cclxuICogICogYGxpbms9VEVYVGAgLSBMb2NhdGVzIGxpbmsgZWxlbWVudCB3aG9zZSB2aXNpYmxlIHRleHQgbWF0Y2hlcyB0aGUgZ2l2ZW4gc3RyaW5nLlxyXG4gKiAgKiBgbGluay1jb250YWlucz1URVhUYCAtIExvY2F0ZXMgbGluayBlbGVtZW50IHdob3NlIHZpc2libGUgdGV4dCBjb250YWlucyB0aGUgZ2l2ZW4gc3RyaW5nLlxyXG4gKiAgKiBgbmFtZT1OQU1FYCAtIExvY2F0ZXMgZWxlbWVudCBieSBpdHMgTkFNRSBhdHRyaWJ1dGUuXHJcbiAqICAqIGB0YWc9TkFNRWAgLSBMb2NhdGVzIGVsZW1lbnQgYnkgaXRzIHRhZyBuYW1lLlxyXG4gKiAgKiBgL1hQQVRIYCAtIExvY2F0ZXMgZWxlbWVudCB1c2luZyBhbiBYUGF0aCAxLjAgZXhwcmVzc2lvbi5cclxuICogICogYChYUEFUSClbXWAgLSBMb2NhdGVzIGVsZW1lbnQgdXNpbmcgYW4gWFBhdGggMS4wIGV4cHJlc3Npb24uXHJcbiAqL1xyXG5cclxuLyogZXNsaW50LWRpc2FibGUgcXVvdGVzICovXHJcbmltcG9ydCB7IGhhckZyb21NZXNzYWdlcyB9IGZyb20gJ2Nocm9tZS1oYXInO1xyXG5pbXBvcnQgVVJMIGZyb20gJ3VybCc7XHJcbmltcG9ydCAqIGFzIHdkaW8gZnJvbSAnd2ViZHJpdmVyaW8nO1xyXG5pbXBvcnQgV2ViRHJpdmVyTW9kdWxlIGZyb20gJy4uL2NvcmUvV2ViRHJpdmVyTW9kdWxlJztcclxuaW1wb3J0IHsgZGVmZXIgfSBmcm9tICd3aGVuJztcclxuaW1wb3J0IG1vZFV0aWxzIGZyb20gJy4vdXRpbHMnO1xyXG5pbXBvcnQgZXJySGVscGVyIGZyb20gJy4uL2Vycm9ycy9oZWxwZXInO1xyXG5pbXBvcnQgT3hFcnJvciBmcm9tICcuLi9lcnJvcnMvT3h5Z2VuRXJyb3InO1xyXG5pbXBvcnQgdXRpbCBmcm9tICd1dGlsJztcclxuaW1wb3J0IFNhdWNlTGFicyBmcm9tICdzYXVjZWxhYnMnO1xyXG5pbXBvcnQgbGFtYmRhUmVzdENsaWVudCBmcm9tICdAbGFtYmRhdGVzdC9ub2RlLXJlc3QtY2xpZW50JztcclxuaW1wb3J0IFRlc3RpbmdCb3QgZnJvbSAndGVzdGluZ2JvdC1hcGknO1xyXG5pbXBvcnQgeyBleGVjU3luYyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xyXG5pbXBvcnQgcGVyZmVjdG9SZXBvcnRpbmcgZnJvbSAncGVyZmVjdG8tcmVwb3J0aW5nJztcclxuaW1wb3J0IHJlcXVlc3QgZnJvbSAncmVxdWVzdCc7XHJcbmltcG9ydCBtZXJnZUltYWdlcyBmcm9tICcuLi9saWIvaW1nLW1lcmdlJztcclxuaW1wb3J0IGVycm9ySGVscGVyIGZyb20gJy4uL2Vycm9ycy9oZWxwZXInO1xyXG5cclxuY29uc3QgTU9EVUxFX05BTUUgPSAnd2ViJztcclxuY29uc3QgREVGQVVMVF9TRUxFTklVTV9VUkwgPSAnaHR0cDovL2xvY2FsaG9zdDo0NDQ0L3dkL2h1Yic7XHJcbmNvbnN0IERFRkFVTFRfQlJPV1NFUl9OQU1FID0gJ2Nocm9tZSc7XHJcbmNvbnN0IERFRkFVTFRfTU9CSUxFX0JST1dTRVIgPSAnZGVmYXVsdCc7XHJcbmNvbnN0IE5PX1NDUkVFTlNIT1RfQ09NTUFORFMgPSBbJ2luaXQnLCAnYXNzZXJ0QWxlcnQnXTtcclxuY29uc3QgQUNUSU9OX0NPTU1BTkRTID0gWydvcGVuJywgJ2NsaWNrJ107XHJcbmNvbnN0IERFRkFVTFRfV0FJVF9USU1FT1VUID0gNjAgKiAxMDAwOyAgICAgICAgICAgIC8vIGRlZmF1bHQgNjBzIHdhaXQgdGltZW91dFxyXG5cclxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViTW9kdWxlIGV4dGVuZHMgV2ViRHJpdmVyTW9kdWxlIHtcclxuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMsIGNvbnRleHQsIHJzLCBsb2dnZXIsIG1vZHVsZXMsIHNlcnZpY2VzKSB7XHJcbiAgICAgICAgc3VwZXIob3B0aW9ucywgY29udGV4dCwgcnMsIGxvZ2dlciwgbW9kdWxlcywgc2VydmljZXMpO1xyXG4gICAgICAgIHRoaXMudHJhbnNhY3Rpb25zID0ge307ICAgICAgICAgICAgICAgICAgICAgIC8vIHRyYW5zYWN0aW9uLT5oYXIgZGljdGlvbmFyeVxyXG4gICAgICAgIHRoaXMubGFzdE5hdmlnYXRpb25TdGFydFRpbWUgPSBudWxsO1xyXG4gICAgICAgIHRoaXMuaGVscGVycyA9IHt9O1xyXG4gICAgICAgIHRoaXMuX2xvYWRIZWxwZXJGdW5jdGlvbnMoKTtcclxuICAgICAgICAvLyBzdXBwb3J0IGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgKHNvbWUgbW9kdWxlIGNvbW1hbmRzIG1pZ2h0IHJlZmVyIHRvIHRoaXMuT3hFcnJvciBhbmQgdGhpcy5lcnJIZWxwZXIpXHJcbiAgICAgICAgdGhpcy5PeEVycm9yID0gT3hFcnJvcjtcclxuICAgICAgICB0aGlzLmVyckhlbHBlciA9IGVyckhlbHBlcjtcclxuICAgICAgICAvLyBob2xkcyBlbGVtZW50IG9wZXJhdGlvbiB0aW1lb3V0IHZhbHVlXHJcbiAgICAgICAgdGhpcy53YWl0Rm9yVGltZW91dCA9IERFRkFVTFRfV0FJVF9USU1FT1VUO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBuYW1lKCkge1xyXG4gICAgICAgIHJldHVybiBNT0RVTEVfTkFNRTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBmdW5jdGlvbiBnZXREcml2ZXJcclxuICAgICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHVuZGVybHlpbmcgV0RJTyBkcml2ZXIuXHJcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFdESU8gZHJpdmVyLlxyXG4gICAgICovXHJcbiAgICBnZXREcml2ZXIoKSB7XHJcbiAgICAgICAgcmV0dXJuIHN1cGVyLmdldERyaXZlcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGZ1bmN0aW9uIGdldENhcGFiaWxpdGllc1xyXG4gICAgICogQHN1bW1hcnkgUmV0dXJucyBjdXJyZW50bHkgZGVmaW5lZCBjYXBhYmlsaXRpZXMuXHJcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgY2FwYWJpbGl0aWVzIG9iamVjdC5cclxuICAgICAqL1xyXG4gICAgZ2V0Q2FwYWJpbGl0aWVzKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNhcHMgfHwgc3VwZXIuZ2V0Q2FwYWJpbGl0aWVzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZnVuY3Rpb24gaW5pdFxyXG4gICAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgbmV3IFNlbGVuaXVtIHNlc3Npb24uXHJcbiAgICAgKiBAcGFyYW0ge1N0cmluZz19IGNhcHMgLSBEZXNpcmVkIGNhcGFiaWxpdGllcy4gSWYgbm90IHNwZWNpZmllZCBjYXBhYmlsaXRpZXMgd2lsbCBiZSB0YWtlbiBmcm9tIHN1aXRlIGRlZmluaXRpb24uXHJcbiAgICAgKiBAcGFyYW0ge1N0cmluZz19IHNlbGVuaXVtVXJsIC0gUmVtb3RlIHNlcnZlciBVUkwgKGRlZmF1bHQ6IGh0dHA6Ly9sb2NhbGhvc3Q6NDQ0NC93ZC9odWIpLlxyXG4gICAgICovXHJcbiAgICBhc3luYyBpbml0KGNhcHMsIHNlbGVuaXVtVXJsKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNJbml0aWFsaXplZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXNlbGVuaXVtVXJsKSB7XHJcbiAgICAgICAgICAgIHNlbGVuaXVtVXJsID0gdGhpcy5vcHRpb25zLnNlbGVuaXVtVXJsIHx8IERFRkFVTFRfU0VMRU5JVU1fVVJMO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gdGFrZSBjYXBhYmlsaXRpZXMgZWl0aGVyIGZyb20gaW5pdCBtZXRob2QgYXJndW1lbnQgb3IgZnJvbSBjb250ZXh0IHBhcmFtZXRlcnMgcGFzc2VkIGluIHRoZSBjb25zdHJ1Y3RvclxyXG4gICAgICAgIC8vIG1lcmdlIGNhcGFiaWxpdGllcyBmcm9tIGNvbnRleHQgYW5kIGZyb20gaW5pdCBmdW5jdGlvbiBhcmd1bWVudCwgZ2l2ZSBwcmVmZXJlbmNlIHRvIGNvbnRleHQtcGFzc2VkIGNhcGFiaWxpdGllc1xyXG4gICAgICAgIHRoaXMuY2FwcyA9IHt9O1xyXG4gICAgICAgIGlmICh0aGlzLmN0eC5jYXBzKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2FwcyA9IHsgLi4udGhpcy5jdHguY2FwcyB9O1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoY2Fwcykge1xyXG4gICAgICAgICAgICB0aGlzLmNhcHMgPSB7IC4uLnRoaXMuY2FwcywgLi4uY2FwcyB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcG9wdWxhdGUgYnJvd3Nlck5hbWUgY2FwcyBmcm9tIG9wdGlvbnMuIEZJWE1FOiB3aHkgaXMgdGhpcyBldmVuIG5lZWRlZD9cclxuICAgICAgICBsZXQgZGVmYXVsdEJyb3dzZXIgPSBmYWxzZTtcclxuICAgICAgICBpZiAoIXRoaXMuY2Fwcy5icm93c2VyTmFtZSkge1xyXG4gICAgICAgICAgICB0aGlzLmNhcHMuYnJvd3Nlck5hbWUgPSB0aGlzLm9wdGlvbnMuYnJvd3Nlck5hbWUgfHwgREVGQVVMVF9CUk9XU0VSX05BTUU7XHJcbiAgICAgICAgICAgIGRlZmF1bHRCcm93c2VyID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gRklYTUU6IHNoYWxsIHdlIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBicm93c2VyTmFtZSBpcyBub3Qgc3BlY2lmaWVkLCBuZWl0aGVyIGluIGNhcHMgbm9yIGluIG9wdGlvbnM/IVxyXG4gICAgICAgIGlmICghdGhpcy5jYXBzLmJyb3dzZXJOYW1lKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBPeEVycm9yKGVyckhlbHBlci5lcnJvckNvZGUuSU5WQUxJRF9DQVBBQklMSVRJRVMsXHJcbiAgICAgICAgICAgICAgICAnRmFpbGVkIHRvIGluaXRpYWxpemUgYHdlYmAgbW9kdWxlIC0gYnJvd3Nlck5hbWUgbXVzdCBiZSBzcGVjaWZpZWQuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBhZGp1c3QgYnJvd3Nlck5hbWUtc1xyXG4gICAgICAgIGlmICh0aGlzLmNhcHMuYnJvd3Nlck5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2llJykge1xyXG4gICAgICAgICAgICAvLyBJRSBpcyBzcGVjaWZpZWQgYXMgJ2llJyB0aHJvdWdoIHRoZSBjb21tYW5kIGxpbmUgYW5kIHBvc3NpYmx5IHN1aXRlc1xyXG4gICAgICAgICAgICAvLyBidXQgc2VsZW5pdW0gc3RhbmRhbG9uZSBzZXJ2ZXIgZXhwZWN0cyAnaW50ZXJuZXQgZXhwbG9yZXInXHJcbiAgICAgICAgICAgIHRoaXMuY2Fwcy5icm93c2VyTmFtZSA9ICdpbnRlcm5ldCBleHBsb3Jlcic7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmNhcHNbJ2xhbWJkYTpvcHRpb25zJ10pIHtcclxuICAgICAgICAgICAgLy8gbGFtYmRhdGVzdCBleHBlY3RzIG9yaWdpbmFsIGNhc2UgbmFtZXNcclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuY2Fwc1sncGVyZmVjdG9Nb2JpbGU6b3B0aW9ucyddKSB7XHJcbiAgICAgICAgICAgIC8vIHBlcmZlY3RvTW9iaWxlIGV4cGVjdHMgb3JpZ2luYWwgY2FzZSBuYW1lc1xyXG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jYXBzLmJyb3dzZXJOYW1lICE9PSAnTWljcm9zb2Z0RWRnZScpIHtcclxuICAgICAgICAgICAgLy8gc2VsZW5pdW0gc3RhbmRhbG9uZSBzZXJ2ZXIgZXhwZWN0cyBhbGwgYnJvd3Nlck5hbWVzIHRvIGJlIGxvd2VyY2FzZVxyXG4gICAgICAgICAgICAvLyBleGNlcHQgXCJNaWNyb3NvZnRFZGdlXCJcclxuICAgICAgICAgICAgdGhpcy5jYXBzLmJyb3dzZXJOYW1lID0gdGhpcy5jYXBzLmJyb3dzZXJOYW1lLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBhZGp1c3QgY2FwYWJpbGl0aWVzIHRvIGVuYWJsZSBjb2xsZWN0aW5nIGJyb3dzZXIgYW5kIHBlcmZvcm1hbmNlIHN0YXRzIGluIENocm9tZSBcclxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJlY29yZEhBUiAmJiB0aGlzLmNhcHMuYnJvd3Nlck5hbWUgPT09ICdjaHJvbWUnKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2Fwc1snZ29vZzpsb2dnaW5nUHJlZnMnXSA9IHsgICAgIC8vIGZvciBDaHJvbWVEcml2ZXIgPj0gNzVcclxuICAgICAgICAgICAgICAgIGJyb3dzZXI6ICdBTEwnLFxyXG4gICAgICAgICAgICAgICAgcGVyZm9ybWFuY2U6ICdBTEwnXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIC8qXHJcbiAgICAgICAgICAgIC8vIHNwZWNpZnlpbmcgdGhpcyBsZWFkcyBDaHJvbWUgNzcrIHRvIHJlZnVzZSBsb2FkaW5nXHJcbiAgICAgICAgICAgIHRoaXMuY2Fwcy5sb2dnaW5nUHJlZnMgPSB7ICAgICAgICAgICAgIC8vIGZvciBDaHJvbWVEcml2ZXIgPCA3NVxyXG4gICAgICAgICAgICAgICAgYnJvd3NlcjogJ0FMTCcsXHJcbiAgICAgICAgICAgICAgICBwZXJmb3JtYW5jZTogJ0FMTCdcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5jYXBzLmNocm9tZU9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgICAgICBwZXJmTG9nZ2luZ1ByZWZzOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgZW5hYmxlTmV0d29yazogdHJ1ZSxcclxuICAgICAgICAgICAgICAgICAgICBlbmFibGVQYWdlOiBmYWxzZVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAqL1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gcG9wdWxhdGUgV0RJTyBvcHRpb25zXHJcbiAgICAgICAgY29uc3QgdXJsID0gVVJMLnBhcnNlKHNlbGVuaXVtVXJsIHx8IERFRkFVTFRfU0VMRU5JVU1fVVJMKTtcclxuICAgICAgICBjb25zdCBwcm90b2NvbCA9IHVybC5wcm90b2NvbC5yZXBsYWNlKC86JC8sICcnKTtcclxuICAgICAgICBjb25zdCBob3N0ID0gdXJsLmhvc3RuYW1lO1xyXG4gICAgICAgIGNvbnN0IHBvcnQgPSBwYXJzZUludCh1cmwucG9ydCB8fCAocHJvdG9jb2wgPT09ICdodHRwcycgPyA0NDMgOiA4MCkpO1xyXG4gICAgICAgIGNvbnN0IHBhdGggPSB1cmwucGF0aG5hbWU7XHJcblxyXG4gICAgICAgIC8vIGF1dGggaXMgbmVlZGVkIG1vc3RseSBmb3IgY2xvdWQgcHJvdmlkZXJzIHN1Y2ggYXMgTGFtYmRhVGVzdFxyXG4gICAgICAgIGlmICh1cmwuYXV0aCkge1xyXG4gICAgICAgICAgICBjb25zdCBhdXRoID0gdXJsLmF1dGguc3BsaXQoJzonKTtcclxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLndkaW9PcHRzID0ge1xyXG4gICAgICAgICAgICAgICAgdXNlcjogYXV0aFswXSxcclxuICAgICAgICAgICAgICAgIGtleTogYXV0aFsxXVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgd2Rpb09wdHMgPSB7XHJcbiAgICAgICAgICAgIC4uLnRoaXMub3B0aW9ucy53ZGlvT3B0cyB8fCB7fSxcclxuICAgICAgICAgICAgcHJvdG9jb2w6IHByb3RvY29sLFxyXG4gICAgICAgICAgICBob3N0bmFtZTogaG9zdCxcclxuICAgICAgICAgICAgcG9ydDogcG9ydCxcclxuICAgICAgICAgICAgcGF0aDogcGF0aCxcclxuICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiB0aGlzLmNhcHMsXHJcbiAgICAgICAgICAgIGxvZ0xldmVsOiAnc2lsZW50JyxcclxuICAgICAgICAgICAgcnVubmVyOiAncmVwbCcsXHJcbiAgICAgICAgICAgIHdhaXRmb3JUaW1lb3V0OiA1MDAwLCAvLyBpbmNyZWFzZSB0aGUgZGVmYXVsdCAzMDAwXHJcbiAgICAgICAgICAgIGNvbm5lY3Rpb25SZXRyeVRpbWVvdXQ6IDMxMCoxMDAwLFxyXG4gICAgICAgICAgICBjb25uZWN0aW9uUmV0cnlDb3VudDogMVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGxldCBpbml0RXJyb3IgPSBudWxsO1xyXG4gICAgICAgIGNvbnN0IF90aGlzID0gdGhpcztcclxuICAgICAgICBjb25zdCBwcm92aWRlciA9IG1vZFV0aWxzLmRldGVybWluZVByb3ZpZGVyKHdkaW9PcHRzKTtcclxuXHJcbiAgICAgICAgaWYgKHByb3ZpZGVyID09PSBtb2RVdGlscy5wcm92aWRlci5QRVJGRUNUTykge1xyXG4gICAgICAgICAgICB3ZGlvT3B0cy5wYXRoID0gJy9uZXhwZXJpZW5jZS9wZXJmZWN0b21vYmlsZS93ZC9odWInO1xyXG4gICAgICAgICAgICB3ZGlvT3B0cy5wb3J0ID0gODA7XHJcbiAgICAgICAgICAgIHdkaW9PcHRzLnByb3RvY29sID0gJ2h0dHAnO1xyXG4gICAgICAgICAgICB3ZGlvT3B0cy5vcGVuRGV2aWNlVGltZW91dCA9IDE1O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IG5hbWUgPSAnbmFtZSc7XHJcbiAgICAgICAgaWYgKHdkaW9PcHRzLmNhcGFiaWxpdGllc1sncGVyZmVjdG9Nb2JpbGU6b3B0aW9ucyddICYmIHdkaW9PcHRzLmNhcGFiaWxpdGllc1sncGVyZmVjdG9Nb2JpbGU6b3B0aW9ucyddWyduYW1lJ10pIHtcclxuICAgICAgICAgICAgbmFtZSA9IHdkaW9PcHRzLmNhcGFiaWxpdGllc1sncGVyZmVjdG9Nb2JpbGU6b3B0aW9ucyddWyduYW1lJ107XHJcbiAgICAgICAgICAgIGRlbGV0ZSB3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ3BlcmZlY3RvTW9iaWxlOm9wdGlvbnMnXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHdkaW9PcHRzLmNhcGFiaWxpdGllc1snbGFtYmRhOm9wdGlvbnMnXSAmJiB3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ2xhbWJkYTpvcHRpb25zJ11bJ25hbWUnXSkge1xyXG4gICAgICAgICAgICBuYW1lID0gd2Rpb09wdHMuY2FwYWJpbGl0aWVzWydsYW1iZGE6b3B0aW9ucyddWyduYW1lJ107XHJcbiAgICAgICAgICAgIGRlbGV0ZSB3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ2xhbWJkYTpvcHRpb25zJ107XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ3Rlc3RpbmdCb3Q6b3B0aW9ucyddICYmIHdkaW9PcHRzLmNhcGFiaWxpdGllc1sndGVzdGluZ0JvdDpvcHRpb25zJ11bJ25hbWUnXSkge1xyXG4gICAgICAgICAgICBuYW1lID0gd2Rpb09wdHMuY2FwYWJpbGl0aWVzWyd0ZXN0aW5nQm90Om9wdGlvbnMnXVsnbmFtZSddO1xyXG4gICAgICAgICAgICBkZWxldGUgd2Rpb09wdHMuY2FwYWJpbGl0aWVzWyd0ZXN0aW5nQm90Om9wdGlvbnMnXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHdkaW9PcHRzLmNhcGFiaWxpdGllc1snYnN0YWNrOm9wdGlvbnMnXSAmJiB3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ2JzdGFjazpvcHRpb25zJ11bJ25hbWUnXSkge1xyXG4gICAgICAgICAgICBuYW1lID0gd2Rpb09wdHMuY2FwYWJpbGl0aWVzWydic3RhY2s6b3B0aW9ucyddWyduYW1lJ107XHJcbiAgICAgICAgICAgIGRlbGV0ZSB3ZGlvT3B0cy5jYXBhYmlsaXRpZXNbJ2JzdGFjazpvcHRpb25zJ107XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIHNldCBkZWZhdWx0IGJyb3dzZXIgZm9yIG1vYmlsZSB3ZWIgdGVzdHMsIGlmIGV4ZWN1dGVkIGFnYWluc3QgcmVtb3RlIGRldmljZXMgb2YgYSBjbG91ZCBwcm92aWRlclxyXG4gICAgICAgIGlmIChkZWZhdWx0QnJvd3NlciAmJiBwcm92aWRlcikge1xyXG4gICAgICAgICAgICB0aGlzLmNhcHMuYnJvd3Nlck5hbWUgPSB3ZGlvT3B0cy5jYXBhYmlsaXRpZXMuYnJvd3Nlck5hbWUgPSBERUZBVUxUX01PQklMRV9CUk9XU0VSO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLndkaW9PcHRzID0gd2Rpb09wdHM7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgdGhpcy5kcml2ZXIgPSBhd2FpdCB3ZGlvLnJlbW90ZSh3ZGlvT3B0cyk7XHJcbiAgICAgICAgICAgIHRoaXMuZHJpdmVyLnByb3ZpZGVyID0gcHJvdmlkZXI7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnNlbGVuaXVtQnJvd3NlclRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZHJpdmVyLnNlbGVuaXVtQnJvd3NlclRpbWVvdXQgPSB0aGlzLm9wdGlvbnMuc2VsZW5pdW1Ccm93c2VyVGltZW91dDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5zZWxlbml1bVRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZHJpdmVyLnNlbGVuaXVtVGltZW91dCA9IHRoaXMub3B0aW9ucy5zZWxlbml1bVRpbWVvdXQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChwcm92aWRlciA9PT0gbW9kVXRpbHMucHJvdmlkZXIuUEVSRkVDVE8pIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBlcmZlY3RvRXhlY3V0aW9uQ29udGV4dCA9IGF3YWl0IG5ldyBwZXJmZWN0b1JlcG9ydGluZy5QZXJmZWN0by5QZXJmZWN0b0V4ZWN1dGlvbkNvbnRleHQoe1xyXG4gICAgICAgICAgICAgICAgICAgIHdlYmRyaXZlcjoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBleGVjdXRlU2NyaXB0OiBhc3luYyAoY29tbWFuZCwgcGFyYW1zKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5kcml2ZXIuZXhlY3V0ZShjb21tYW5kLCBwYXJhbXMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlcG9ydGluZ0NsaWVudCA9IG5ldyBwZXJmZWN0b1JlcG9ydGluZy5QZXJmZWN0by5QZXJmZWN0b1JlcG9ydGluZ0NsaWVudChwZXJmZWN0b0V4ZWN1dGlvbkNvbnRleHQpO1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXBvcnRpbmdDbGllbnQudGVzdFN0YXJ0KG5hbWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIHRocm93IGVyckhlbHBlci5nZXRTZWxlbml1bUluaXRFcnJvcihlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIHJlc2V0IGJyb3dzZXIgbG9ncyBpZiBhdXRvIGNvbGxlY3QgbG9ncyBvcHRpb24gaXMgZW5hYmxlZFxyXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuY29sbGVjdEJyb3dzZXJMb2dzICYmIHRoaXMuY2Fwcy5icm93c2VyTmFtZSA9PT0gJ2Nocm9tZScpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIC8vIHNpbXBseSBjYWxsIHRoaXMgdG8gY2xlYXIgdGhlIHByZXZpb3VzIGxvZ3MgYW5kIHN0YXJ0IHRoZSB0ZXN0IHdpdGggdGhlIGNsZWFuIGxvZ3NcclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0QnJvd3NlckxvZ3MoKTtcclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ0Nhbm5vdCByZXRyaWV2ZSBicm93c2VyIGxvZ3MuJywgZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgIFttb2RVdGlscy5wcm92aWRlci5MQU1CREFURVNULCBtb2RVdGlscy5wcm92aWRlci5CUk9XU0VSU1RBQ0ssIG1vZFV0aWxzLnByb3ZpZGVyLlBFUkZFQ1RPXS5pbmNsdWRlcyh0aGlzLmRyaXZlci5wcm92aWRlcilcclxuICAgICAgICAgICAgICAgIC8vWydNaWNyb3NvZnRFZGdlJywgJ21zZWRnZScsICdFZGdlJywgJ0ludGVybmV0IEV4cGxvcmVyJ10uaW5jbHVkZXModGhpcy5kcml2ZXIuY2FwYWJpbGl0aWVzLmJyb3dzZXJOYW1lKVxyXG4gICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgIC8vIGRvIG5vdCBtYXhpbWl6ZSB3aW5kb3cgaWYgdGhlIHRlc3QgaXMgZXhlY3V0ZWQgYWdhaW5zdCBleHRlcm5hbCBjbG91ZCBwcm92aWRlciBpbmZyYXN0cnVjdHVyZVxyXG4gICAgICAgICAgICAgICAgLy8gYXMgbW9zdCBvZiBjbG91ZCBwcm92aWRlcnMgZG8gbm90IHN1cHBvcnQgdGhpcyBmdW5jdGlvbmFsaXR5XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBtYXhpbWl6ZSBicm93c2VyIHdpbmRvd1xyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5kcml2ZXIubWF4aW1pemVXaW5kb3coKTtcclxuICAgICAgICAgICAgICAgIC8vIHNldCBpbml0aWFsIFRpbWVvdXRcclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZHJpdmVyLnNldFRpbWVvdXQoe1xyXG4gICAgICAgICAgICAgICAgICAgICdpbXBsaWNpdCc6IHRoaXMud2FpdEZvclRpbWVvdXQsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3BhZ2VMb2FkJzogdGhpcy53YWl0Rm9yVGltZW91dFxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBPeEVycm9yKGVyckhlbHBlci5lcnJvckNvZGUuVU5LTk9XTl9FUlJPUiwgZXJyLm1lc3NhZ2UsIHV0aWwuaW5zcGVjdChlcnIpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgc3VwZXIuaW5pdCh0aGlzLmRyaXZlcik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZnVuY3Rpb24gZGlzcG9zZVxyXG4gICAgICogQHN1bW1hcnkgRW5kcyB0aGUgY3VycmVudCBzZXNzaW9uLlxyXG4gICAgICogQHBhcmFtIHtTdHJpbmc9fSBzdGF0dXMgLSBUZXN0IHN0YXR1cywgZWl0aGVyIGBwYXNzZWRgIG9yIGBmYWlsZWRgLlxyXG4gICAgICovXHJcbiAgICBhc3luYyBkaXNwb3NlKHN0YXR1cykge1xyXG4gICAgICAgIHRoaXMudHJhbnNhY3Rpb25zID0ge307XHJcbiAgICAgICAgdGhpcy5fd2hlbldlYk1vZHVsZURpc3Bvc2UgPSBkZWZlcigpO1xyXG5cclxuICAgICAgICBpZiAoIXN0YXR1cykge1xyXG4gICAgICAgICAgICBzdGF0dXMgPSAncGFzc2VkJztcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLnJzLnN0ZXBzICYmIEFycmF5LmlzQXJyYXkodGhpcy5ycy5zdGVwcykgJiYgdGhpcy5ycy5zdGVwcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBmYWlsZWRGaW5kZWQgPSB0aGlzLnJzLnN0ZXBzLmZpbmQoKGl0ZW0pID0+IGl0ZW0uc3RhdHVzID09PSAnZmFpbGVkJyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoZmFpbGVkRmluZGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhdHVzID0gJ2ZhaWxlZCc7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmRyaXZlciAmJiB0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIHN0YXR1cyA9IHN0YXR1cy50b1VwcGVyQ2FzZSgpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRyaXZlci5wcm92aWRlciA9PT0gbW9kVXRpbHMucHJvdmlkZXIuU0FVQ0VMQUJTKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdXNlcm5hbWUgPSB0aGlzLndkaW9PcHRzLmNhcGFiaWxpdGllc1snc2F1Y2U6b3B0aW9ucyddWyd1c2VybmFtZSddO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjY2Vzc0tleSA9IHRoaXMud2Rpb09wdHMuY2FwYWJpbGl0aWVzWydzYXVjZTpvcHRpb25zJ11bJ2FjY2Vzc0tleSddO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhc3NlZCA9IHN0YXR1cyA9PT0gJ1BBU1NFRCc7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWQgPSB0aGlzLmRyaXZlci5zZXNzaW9uSWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYm9keSA9IFwie1xcXCJwYXNzZWRcXFwiOlwiK3Bhc3NlZCtcIn1cIjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbXlBY2NvdW50ID0gbmV3IFNhdWNlTGFicyh7IHVzZXI6IHVzZXJuYW1lLCBrZXk6IGFjY2Vzc0tleX0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IG15QWNjb3VudC51cGRhdGVKb2IodXNlcm5hbWUsIGlkLCBib2R5KTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCBteUFjY291bnQuc3RvcEpvYih1c2VybmFtZSwgaWQpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmRyaXZlci5wcm92aWRlciA9PT0gbW9kVXRpbHMucHJvdmlkZXIuTEFNQkRBVEVTVCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX3NlbmRSZXN1bHRTdGF0dXNUb0xhbWJkYVRlc3Qoc3RhdHVzKTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmRlbGV0ZVNlc3Npb24oKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5kcml2ZXIucHJvdmlkZXIgPT09IG1vZFV0aWxzLnByb3ZpZGVyLlRFU1RJTkdCT1QpIHtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9zZW5kUmVzdWx0U3RhdHVzVG9UZXN0aW5nQm90KHN0YXR1cyk7XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVTZXNzaW9uKCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZHJpdmVyLnByb3ZpZGVyID09PSBtb2RVdGlscy5wcm92aWRlci5QRVJGRUNUTykge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmVwb3J0aW5nQ2xpZW50LnRlc3RTdG9wKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMgPT09ICdQQVNTRUQnID9cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyZmVjdG9SZXBvcnRpbmcuQ29uc3RhbnRzLnJlc3VsdHMucGFzc2VkIDpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVyZmVjdG9SZXBvcnRpbmcuQ29uc3RhbnRzLnJlc3VsdHMuZmFpbGVkXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZHJpdmVyLnByb3ZpZGVyID09PSBtb2RVdGlscy5wcm92aWRlci5CUk9XU0VSU1RBQ0spIHtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9zZW5kUmVzdWx0U3RhdHVzVG9Ccm93c2Vyc3RhY2soc3RhdHVzKTtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmRlbGV0ZVNlc3Npb24oKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kcml2ZXIucHJvdmlkZXIgPT09IG51bGwgJiYgWydQQVNTRUQnLCdGQUlMRUQnXS5pbmNsdWRlcyhzdGF0dXMpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jbG9zZUJyb3dzZXJXaW5kb3dzKHN0YXR1cyk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNhbmNlbGVkIG9yIG90aGVyIHN0YXR1c1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcG9zZUNvbnRpbnVlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oJ0Vycm9yIGRpc3Bvc2luZyBkcml2ZXI6ICcsIGUpOyAgICAvLyBpZ25vcmUgYW55IGVycm9ycyBhdCBkaXNwb3NhbCBzdGFnZVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5kaXNwb3NlQ29udGludWUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLl93aGVuV2ViTW9kdWxlRGlzcG9zZS5wcm9taXNlO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGRlbGV0ZVNlc3Npb24oKSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuZHJpdmVyICYmIHRoaXMuZHJpdmVyLmRlbGV0ZVNlc3Npb24pIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVuaXVtU2Vzc2lvblRpbWVvdXQpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBpZ25vcmVcclxuICAgICAgICAgICAgICAgICAgICAvLyBkZWxldGVTZXNzaW9uIHdpbGwgdGFrZSA1IG1pbiB0byBjYWxsXHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZHJpdmVyLmRlbGV0ZVNlc3Npb24oKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ2RlbGV0ZVNlc3Npb24gZXJyb3InLCBlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgY2xvc2VCcm93c2VyV2luZG93cyhzdGF0dXMpIHtcclxuICAgICAgICBpZiAoc3RhdHVzICYmICdGQUlMRUQnID09PSBzdGF0dXMudG9VcHBlckNhc2UoKSAmJiB0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLnNlbGVuaXVtUGlkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZGlzcG9zZUNvbnRpbnVlKHN0YXR1cyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlU2Vzc2lvbigpO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKCdGYWlsZWQgdG8gY2xvc2UgYnJvd3NlciB3aW5kb3dzOicsIGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMuZGlzcG9zZUNvbnRpbnVlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGRpc3Bvc2VDb250aW51ZShzdGF0dXMpIHtcclxuICAgICAgICB0aGlzLmRyaXZlciA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5sYXN0TmF2aWdhdGlvblN0YXJ0VGltZSA9IG51bGw7XHJcbiAgICAgICAgc3VwZXIuZGlzcG9zZSgpO1xyXG5cclxuICAgICAgICAvLyBjbGVhbnVwIGNocm9tZWRyaXZlcidzIG9ubHkgd2hlbiBydW5uaW5nIGZyb20gd2l0aGluIHRoZSBJREUgYW5kIHRlc3QgZGlkIG5vdCBmYWlsXHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuc2VsZW5pdW1QaWQgJiYgKCFzdGF0dXMgfHwgJ0ZBSUxFRCcgIT09IHN0YXR1cy50b1VwcGVyQ2FzZSgpKSkge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpIHtcclxuICAgICAgICAgICAgICAgICAgICBleGVjU3luYygndGFza2tpbGwgL0lNIGNocm9tZWRyaXZlci5leGUgL0YnLCB7IHN0ZGlvOiBbJ2lnbm9yZScsICdpZ25vcmUnLCAnaWdub3JlJ10gfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBwZ3JlcFJlc3VsdCA9IGV4ZWNTeW5jKFwicGdyZXAgLWQnICcgY2hyb21lZHJpdmVyXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwZ3JlcFJlc3VsdCAmJiBwZ3JlcFJlc3VsdC50b1N0cmluZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwZ3JlcFJlc3VsdCA9IHBncmVwUmVzdWx0LnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwZ3JlcFJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhlY1N5bmMoJ2tpbGwgLTkgJyArIHBncmVwUmVzdWx0LCB7IHN0ZGlvOiBbJ2lnbm9yZScsICdpZ25vcmUnLCAnaWdub3JlJ10gfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIC8vIGlnbm9yZSBlcnJvcnNcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gY2xlYW51cCBlZGdlZHJpdmVyJ3Mgb25seSB3aGVuIHJ1bm5pbmcgZnJvbSB3aXRoaW4gdGhlIElERSBhbmQgdGVzdCBkaWQgbm90IGZhaWxcclxuICAgICAgICBpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5zZWxlbml1bVBpZCAmJiAoIXN0YXR1cyB8fCAnRkFJTEVEJyAhPT0gc3RhdHVzLnRvVXBwZXJDYXNlKCkpKSB7XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGlnbm9yZSBmb3Igbm93XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBwZ3JlcFJlc3VsdCA9IGV4ZWNTeW5jKFwicGdyZXAgLWQnICcgbXNlZGdlZHJpdmVyXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwZ3JlcFJlc3VsdCAmJiBwZ3JlcFJlc3VsdC50b1N0cmluZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwZ3JlcFJlc3VsdCA9IHBncmVwUmVzdWx0LnRvU3RyaW5nKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwZ3JlcFJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhlY1N5bmMoJ2tpbGwgLTkgJyArIHBncmVwUmVzdWx0LCB7IHN0ZGlvOiBbJ2lnbm9yZScsICdpZ25vcmUnLCAnaWdub3JlJ10gfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIC8vIGlnbm9yZSBlcnJvcnNcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fd2hlbldlYk1vZHVsZURpc3Bvc2UucmVzb2x2ZShudWxsKTtcclxuICAgIH1cclxuXHJcbiAgICBfaXRlcmF0aW9uU3RhcnQoKSB7XHJcbiAgICAgICAgLy8gY2xlYXIgdHJhbnNhY3Rpb24gbmFtZSBzYXZlZCBpbiBwcmV2aW91cyBpdGVyYXRpb24gaWYgYW55XHJcbiAgICAgICAgZ2xvYmFsLl9sYXN0VHJhbnNhY3Rpb25OYW1lID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBfaXRlcmF0aW9uRW5kKGVycm9yKSB7XHJcbiAgICAgICAgaWYgKGVycm9yICYmIGVycm9yLnR5cGUgPT09IGVycm9ySGVscGVyLmVycm9yQ29kZS5TRUxFTklVTV9TRVNTSU9OX1RJTUVPVVQpIHtcclxuICAgICAgICAgICAgdGhpcy5zZWxlbml1bVNlc3Npb25UaW1lb3V0ID0gdHJ1ZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZW5pdW1TZXNzaW9uVGltZW91dCA9IGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmlzSW5pdGlhbGl6ZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvLyBjb2xsZWN0IGJyb3dzZXIgbG9ncyBmb3IgdGhpcyBzZXNzaW9uXHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5jb2xsZWN0QnJvd3NlckxvZ3MgPT09IHRydWUgJiYgdGhpcy5jYXBzLmJyb3dzZXJOYW1lID09PSAnY2hyb21lJykge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbG9ncyA9IGF3YWl0IHRoaXMuZ2V0QnJvd3NlckxvZ3MoKTtcclxuICAgICAgICAgICAgICAgIGlmIChsb2dzICYmIEFycmF5LmlzQXJyYXkobG9ncykpIHtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBsb2cgb2YgbG9ncykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJzLmxvZ3MucHVzaCh0aGlzLl9hZGp1c3RCcm93c2VyTG9nKGxvZykpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgLy8gaWdub3JlIGVycm9yc1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ0Nhbm5vdCByZXRyaWV2ZSBicm93c2VyIGxvZ3MuJywgZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gVE9ETzogc2hvdWxkIGNsZWFyIHRyYW5zYWN0aW9ucyB0byBhdm9pZCBkdXBsaWNhdGUgbmFtZXMgYWNyb3NzIGl0ZXJhdGlvbnNcclxuICAgICAgICAvLyBhbHNvIHNob3VsZCB0aHJvdyBvbiBkdXBsaWNhdGUgbmFtZXMuXHJcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5yZWNvcmRIQVIgJiYgdGhpcy5jYXBzLmJyb3dzZXJOYW1lID09PSAnY2hyb21lJykge1xyXG4gICAgICAgICAgICAvLyB0aGVyZSBtaWdodCBiZSBubyB0cmFuc2FjdGlvbnMgc2V0IGlmIHRlc3QgZmFpbHMgYmVmb3JlIHdlYi50cmFuc2FjdGlvbiBjb21tYW5kXHJcbiAgICAgICAgICAgIGlmIChnbG9iYWwuX2xhc3RUcmFuc2FjdGlvbk5hbWUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNhY3Rpb25zW2dsb2JhbC5fbGFzdFRyYW5zYWN0aW9uTmFtZV0gPSBhd2FpdCB0aGlzLl9nZXRIQVIoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5ycy5oYXIgPSB0aGlzLnRyYW5zYWN0aW9ucztcclxuICAgIH1cclxuXHJcbiAgICBfaXNBY3Rpb24obmFtZSkge1xyXG4gICAgICAgIHJldHVybiBBQ1RJT05fQ09NTUFORFMuaW5jbHVkZXMobmFtZSk7XHJcbiAgICB9XHJcblxyXG4gICAgX3Rha2VTY3JlZW5zaG90U2lsZW50KG5hbWUpIHtcclxuICAgICAgICBpZiAoIU5PX1NDUkVFTlNIT1RfQ09NTUFORFMuaW5jbHVkZXMobmFtZSkpIHtcclxuICAgICAgICAgICAgbGV0IGVycm9yO1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJpdmVyICYmXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcml2ZXIudGFrZVNjcmVlbnNob3RcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZXR2YWw7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kcml2ZXIuY2FsbCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3YWl0VW50aWxSZXRWYWwgPSB0aGlzLmRyaXZlci53YWl0VW50aWwoYXN5bmMoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltYWdlcyA9IFtdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29sbGVjdCBhbGwgKHNjcmVlbnNob3QgYW5kIHRpdGxlKSBpbWFnZXNcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGFuZGxlcyA9IGF3YWl0IHRoaXMuZHJpdmVyLmdldFdpbmRvd0hhbmRsZXMoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlcyAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShoYW5kbGVzKSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlcy5sZW5ndGggPiAwXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBoYW5kbGUgb2YgaGFuZGxlcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuZHJpdmVyLnN3aXRjaFRvV2luZG93KGhhbmRsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSBhd2FpdCB0aGlzLmRyaXZlci50YWtlU2NyZWVuc2hvdCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpdGxlID0gYXdhaXQgdGhpcy5kcml2ZXIuZ2V0VGl0bGUoKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRpdGxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHRUb0ltYWdlID0gcmVxdWlyZSgndGV4dC10by1pbWFnZScpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgdGl0bGVJbWFnZSA9IGF3YWl0IHRleHRUb0ltYWdlLmdlbmVyYXRlKHRpdGxlLCB7IGRlYnVnOiBmYWxzZSwgZm9udEZhbWlseTogJ0FyaWFsJyB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRpdGxlSW1hZ2UgJiYgdHlwZW9mIHRpdGxlSW1hZ2UgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZUltYWdlID0gdGl0bGVJbWFnZS5yZXBsYWNlKCdkYXRhOmltYWdlL3BuZztiYXNlNjQsJywgJycpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1hZ2VzLnB1c2godGl0bGVJbWFnZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlcy5wdXNoKGltYWdlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVyZ2UgYWxsIGltYWdlcyBpbnRvIG9uZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXJnZWRJbWFnZSA9IGF3YWl0IG1lcmdlSW1hZ2VzKGltYWdlcywgeyBkaXJlY3Rpb246IHRydWUgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtZXJnZWRJbWFnZSAmJiB0eXBlb2YgbWVyZ2VkSW1hZ2UgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR2YWwgPSBtZXJnZWRJbWFnZS5yZXBsYWNlKCdkYXRhOmltYWdlL2pwZWc7YmFzZTY0LCcsICcnKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvciA9IGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeyB0aW1lb3V0OiAzMCoxMDAwIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YWl0VW50aWxSZXRWYWwgJiYgd2FpdFVudGlsUmV0VmFsLnRoZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3YWl0VW50aWxSZXRWYWwudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ0Nhbm5vdCBnZXQgc2NyZWVuc2hvdCcsIGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR2YWw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCdDYW5ub3QgZ2V0IHNjcmVlbnNob3QnLCBlKTtcclxuICAgICAgICAgICAgICAgIGlmIChlcnJvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCdDYW5ub3QgZ2V0IHNjcmVlbnNob3QgaW5uZXIgZXJyb3InLCBlcnJvcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvLyBpZ25vcmVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBfYWRqdXN0QnJvd3NlckxvZyhsb2cpIHtcclxuICAgICAgICBpZiAoIWxvZyB8fCB0eXBlb2YgbG9nICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gVE9ETzogY29udmVydCBsb2cudGltZXN0YW1wIGZyb20gdGhlIGJyb3dzZXIgdGltZSB6b25lIHRvIHRoZSBsb2NhbCBvbmUgKHNvIHdlIGNhbiBsYXRlciBjb3JyZWxhdGUgYmV0d2VlbiBzdGVwcyBhbmQgbG9ncylcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICB0aW1lOiBsb2cudGltZXN0YW1wLFxyXG4gICAgICAgICAgICBtc2c6IGxvZy5tZXNzYWdlLFxyXG4gICAgICAgICAgICAvLyBjb252ZXJ0IFNFVkVSRSBsb2cgbGV2ZWwgdG8gRVJST1JcclxuICAgICAgICAgICAgbGV2ZWw6IGxvZy5sZXZlbCA9PT0gJ1NFVkVSRScgPyAnRVJST1InIDogbG9nLmxldmVsLFxyXG4gICAgICAgICAgICBzcmM6ICdicm93c2VyJ1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLypcclxuICAgICAqIEZJWE1FOiBUaGVyZSBpcyBhIGJ1ZyB3aXRoIElFLiBTZWUgdGhlIGNvbW1lbnQgd2l0aGluIGZ1bmN0aW9uIGJvZHkuXHJcbiAgICAgKlxyXG4gICAgICogIGRvbUNvbnRlbnRMb2FkZWQgKGFrYSBGaXJzdCBWaXN1YWwgVGltZSktIFJlcHJlc2VudHMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBkb21Db250ZW50TG9hZGVkRXZlbnRTdGFydCBhbmQgbmF2aWdhdGlvblN0YXJ0LlxyXG4gICAgICogIGxvYWQgKGFrYSBGdWxsIExvYWQgVGltZSkgICAgICAgICAgICAgICAtIFJlcHJlc2VudHMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBsb2FkRXZlbnRTdGFydCBhbmQgbmF2aWdhdGlvblN0YXJ0LlxyXG4gICAgICpcclxuICAgICAqIFRoZSBwcm9jZXNzaW5nIG1vZGVsOlxyXG4gICAgICpcclxuICAgICAqICAxLiBuYXZpZ2F0aW9uU3RhcnQgICAgICAgICAgICAgIC0gVGhlIGJyb3dzZXIgaGFzIHJlcXVlc3RlZCB0aGUgZG9jdW1lbnQuXHJcbiAgICAgKiAgMi4gLi4uICAgICAgICAgICAgICAgICAgICAgICAgICAtIE5vdCByZWxldmFudCB0byB1cy4gU2VlIGh0dHA6Ly93d3cudzMub3JnL1RSL25hdmlnYXRpb24tdGltaW5nLyNwcm9jZXNzIGZvciBtb3JlIGluZm9ybWF0aW9uLlxyXG4gICAgICogIDMuIGRvbUxvYWRpbmcgICAgICAgICAgICAgICAgICAgLSBUaGUgYnJvd3NlciBzdGFydHMgcGFyc2luZyB0aGUgZG9jdW1lbnQuXHJcbiAgICAgKiAgNC4gZG9tSW50ZXJhY3RpdmUgICAgICAgICAgICAgICAtIFRoZSBicm93c2VyIGhhcyBmaW5pc2hlZCBwYXJzaW5nIHRoZSBkb2N1bWVudCBhbmQgdGhlIHVzZXIgY2FuIGludGVyYWN0IHdpdGggdGhlIHBhZ2UuXHJcbiAgICAgKiAgNS4gZG9tQ29udGVudExvYWRlZEV2ZW50U3RhcnQgICAtIFRoZSBkb2N1bWVudCBoYXMgYmVlbiBjb21wbGV0ZWx5IGxvYWRlZCBhbmQgcGFyc2VkIGFuZCBkZWZlcnJlZCBzY3JpcHRzLCBpZiBhbnksIGhhdmUgZXhlY3V0ZWQuIFxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBc3luYyBzY3JpcHRzLCBpZiBhbnksIG1pZ2h0IG9yIG1pZ2h0IG5vdCBoYXZlIGV4ZWN1dGVkLlxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdHlsZXNoZWV0c1sxXSwgaW1hZ2VzLCBhbmQgc3ViZnJhbWVzIG1pZ2h0IG9yIG1pZ2h0IG5vdCBoYXZlIGZpbmlzaGVkIGxvYWRpbmcuXHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWzFdIC0gU3R5bGVzaGVldHMgL3VzdWFsbHkvIGRlZmVyIHRoaXMgZXZlbnQhIC0gaHR0cDovL21vbGlseS5kZS93ZWJsb2cvZG9tY29udGVudGxvYWRlZFxyXG4gICAgICogIDYuIGRvbUNvbnRlbnRMb2FkZWRFdmVudEVuZCAgICAgLSBUaGUgRE9NQ29udGVudExvYWRlZCBldmVudCBjYWxsYmFjaywgaWYgYW55LCBmaW5pc2hlZCBleGVjdXRpbmcuIEUuZy5cclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBmdW5jdGlvbihldmVudCkge1xyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkRPTSBmdWxseSBsb2FkZWQgYW5kIHBhcnNlZFwiKTtcclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAqICA3LiBkb21Db21wbGV0ZSAgICAgICAgICAgICAgICAgIC0gVGhlIERPTSB0cmVlIGlzIGNvbXBsZXRlbHkgYnVpbHQuIEFzeW5jIHNjcmlwdHMsIGlmIGFueSwgaGF2ZSBleGVjdXRlZC5cclxuICAgICAqICA4LiBsb2FkRXZlbnRTdGFydCAgICAgICAgICAgICAgIC0gVGhlIGJyb3dzZXIgaGF2ZSBmaW5pc2hlZCBsb2FkaW5nIGFsbCB0aGUgcmVzb3VyY2VzIGxpa2UgaW1hZ2VzLCBzd2YsIGV0Yy5cclxuICAgICAqICA5LiBsb2FkRXZlbnRFbmQgICAgICAgICAgICAgICAgIC0gVGhlIGxvYWQgZXZlbnQgY2FsbGJhY2ssIGlmIGFueSwgZmluaXNoZWQgZXhlY3V0aW5nLlxyXG4gICAgICovXHJcbiAgICBfZ2V0U3RhdHMoY29tbWFuZE5hbWUpIHtcclxuICAgICAgICBpZiAodGhpcy5vcHRpb25zLmZldGNoU3RhdHMgJiYgdGhpcy5pc0luaXRpYWxpemVkICYmIHRoaXMuX2lzQWN0aW9uKGNvbW1hbmROYW1lKSkge1xyXG4gICAgICAgICAgICB2YXIgbmF2aWdhdGlvblN0YXJ0O1xyXG4gICAgICAgICAgICB2YXIgZG9tQ29udGVudExvYWRlZCA9IDA7XHJcbiAgICAgICAgICAgIHZhciBsb2FkID0gMDtcclxuICAgICAgICAgICAgdmFyIHNhbWVQYWdlID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgZm9sbG93aW5nIHNpdHVhdGlvbjpcclxuICAgICAgICAgICAgLy8gaWYgbmF2aWdhdGVTdGFydCBlcXVhbHMgdG8gdGhlIG9uZSB3ZSBnb3QgZnJvbSBwcmV2aW91cyBhdHRlbXB0ICh3ZSBuZWVkIHRvIHNhdmUgaXQpXHJcbiAgICAgICAgICAgIC8vIGl0IG1lYW5zIHdlIGFyZSBzdGlsbCBvbiB0aGUgc2FtZSBwYWdlIGFuZCBkb24ndCBuZWVkIHRvIHJlY29yZCBsb2FkL2RvbUNvbnRlbnRMb2FkZWQgdGltZXNcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZHJpdmVyLmNhbGwoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsYXN0RXJyb3IgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdFVudGlsUmV0VmFsID0gdGhpcy5kcml2ZXIud2FpdFVudGlsKGFzeW5jKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3cqL1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aW1pbmdzID0gYXdhaXQgdGhpcy5kcml2ZXIuZXhlY3V0ZShmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25TdGFydDogd2luZG93LnBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21Db250ZW50TG9hZGVkRXZlbnRTdGFydDogd2luZG93LnBlcmZvcm1hbmNlLnRpbWluZy5kb21Db250ZW50TG9hZGVkRXZlbnRTdGFydCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRFdmVudFN0YXJ0OiB3aW5kb3cucGVyZm9ybWFuY2UudGltaW5nLmxvYWRFdmVudFN0YXJ0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEVycm9yID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aW1pbmdzLmRvbUNvbnRlbnRMb2FkZWRFdmVudFN0YXJ0ID4gMCAmJiB0aW1pbmdzLmxvYWRFdmVudFN0YXJ0ID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW1lUGFnZSA9IHRoaXMubGFzdE5hdmlnYXRpb25TdGFydFRpbWUgJiYgdGhpcy5sYXN0TmF2aWdhdGlvblN0YXJ0VGltZSA9PSB0aW1pbmdzLm5hdmlnYXRpb25TdGFydDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdGlvblN0YXJ0ID0gdGhpcy5sYXN0TmF2aWdhdGlvblN0YXJ0VGltZSA9IHRpbWluZ3MubmF2aWdhdGlvblN0YXJ0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZG9tQ29udGVudExvYWRlZEV2ZW50U3RhcnQgPSB0aW1pbmdzLmRvbUNvbnRlbnRMb2FkZWRFdmVudFN0YXJ0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9hZEV2ZW50U3RhcnQgPSB0aW1pbmdzLmxvYWRFdmVudFN0YXJ0O1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tQ29udGVudExvYWRlZCA9IGRvbUNvbnRlbnRMb2FkZWRFdmVudFN0YXJ0IC0gbmF2aWdhdGlvblN0YXJ0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkID0gbG9hZEV2ZW50U3RhcnQgLSBuYXZpZ2F0aW9uU3RhcnQ7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tQ29udGVudExvYWRlZEV2ZW50U3RhcnQgPiAwICYmIGxvYWRFdmVudFN0YXJ0ID4gMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXhlY3V0ZUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29sbGVjdCBlcnJvciBpbnNpZGUgZHJpdmVyLmV4ZWN1dGUgb3IgZHJpdmVyLndhaXRVbnRpbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RFcnJvciA9IGV4ZWN1dGVFcnJvcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgeyB0aW1lb3V0OiAzMCoxMDAwIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhaXRVbnRpbFJldFZhbCAmJiB3YWl0VW50aWxSZXRWYWwudGhlbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FpdFVudGlsUmV0VmFsLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0RXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcHJpbnQgZXJyb3IgZnJvbSBkcml2ZXIuZXhlY3V0ZSBvciBkcml2ZXIud2FpdFVudGlsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGxhc3RFcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKChlcnIpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByaW50IGVycm9yIGZyb20gZHJpdmVyLmV4ZWN1dGUgb3IgZHJpdmVyLndhaXRVbnRpbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhsYXN0RXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xyXG4gICAgICAgICAgICAgICAgLy8gY291bGRuJ3QgZ2V0IHRpbWluZ3MuXHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMubGFzdE5hdmlnYXRpb25TdGFydFRpbWUgPSBuYXZpZ2F0aW9uU3RhcnQ7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gc2FtZVBhZ2UgPyB7fSA6IHsgRG9tQ29udGVudExvYWRlZEV2ZW50OiBkb21Db250ZW50TG9hZGVkLCBMb2FkRXZlbnQ6IGxvYWQgfTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7fTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBzdW1tYXJ5IE9wZW5zIG5ldyB0cmFuc2FjdGlvbi5cclxuICAgICAqIEBkZXNjcmlwdGlvbiBUaGUgdHJhbnNhY3Rpb24gd2lsbCBwZXJzaXN0IHRpbGwgYSBuZXcgb25lIGlzIG9wZW5lZC4gVHJhbnNhY3Rpb24gbmFtZXMgbXVzdCBiZVxyXG4gICAgICogICAgICAgICAgICAgIHVuaXF1ZS5cclxuICAgICAqIEBmdW5jdGlvbiB0cmFuc2FjdGlvblxyXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgLSBUaGUgdHJhbnNhY3Rpb24gbmFtZS5cclxuICAgICAqL1xyXG4gICAgYXN5bmMgdHJhbnNhY3Rpb24obmFtZSkge1xyXG4gICAgICAgIGlmIChnbG9iYWwuX2xhc3RUcmFuc2FjdGlvbk5hbWUpIHtcclxuICAgICAgICAgICAgdGhpcy50cmFuc2FjdGlvbnNbZ2xvYmFsLl9sYXN0VHJhbnNhY3Rpb25OYW1lXSA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLnJlY29yZEhBUiAmJiB0aGlzLmlzSW5pdGlhbGl6ZWQgJiYgdGhpcy5jYXBzLmJyb3dzZXJOYW1lID09PSAnY2hyb21lJykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy50cmFuc2FjdGlvbnNbZ2xvYmFsLl9sYXN0VHJhbnNhY3Rpb25OYW1lXSA9IGF3YWl0IHRoaXMuX2dldEhBUigpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodHlwZW9mIHRoaXMudHJhbnNhY3Rpb25zW25hbWVdICE9PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgICAgICBjb25zdCBjb3VudGVyID0gT2JqZWN0LmtleXModGhpcy50cmFuc2FjdGlvbnMpLmZpbHRlcigoaXRlbSkgPT4gaXRlbS5zdGFydHNXaXRoKG5hbWUpKS5sZW5ndGggKyAxO1xyXG4gICAgICAgICAgICBnbG9iYWwuX2xhc3RUcmFuc2FjdGlvbk5hbWUgPSBuYW1lKycgKCMnK2NvdW50ZXIrJyknO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGdsb2JhbC5fbGFzdFRyYW5zYWN0aW9uTmFtZSA9IG5hbWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIF9sb2FkSGVscGVyRnVuY3Rpb25zKCkge1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5nZXRXZGlvTG9jYXRvciA9IG1vZFV0aWxzLmdldFdkaW9Mb2NhdG9yO1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5tYXRjaFBhdHRlcm4gPSBtb2RVdGlscy5tYXRjaFBhdHRlcm47XHJcbiAgICAgICAgdGhpcy5oZWxwZXJzLmdldEVsZW1lbnQgPSBtb2RVdGlscy5nZXRFbGVtZW50O1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5nZXRFbGVtZW50cyA9IG1vZFV0aWxzLmdldEVsZW1lbnRzO1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5nZXRDaGlsZEVsZW1lbnQgPSBtb2RVdGlscy5nZXRDaGlsZEVsZW1lbnQ7XHJcbiAgICAgICAgdGhpcy5oZWxwZXJzLmdldENoaWxkRWxlbWVudHMgPSBtb2RVdGlscy5nZXRDaGlsZEVsZW1lbnRzO1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5zZXRUaW1lb3V0SW1wbGljaXQgPSBtb2RVdGlscy5zZXRUaW1lb3V0SW1wbGljaXQ7XHJcbiAgICAgICAgdGhpcy5oZWxwZXJzLnJlc3RvcmVUaW1lb3V0SW1wbGljaXQgPSBtb2RVdGlscy5yZXN0b3JlVGltZW91dEltcGxpY2l0O1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5hc3NlcnRBcmd1bWVudCA9IG1vZFV0aWxzLmFzc2VydEFyZ3VtZW50O1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5hc3NlcnRBcmd1bWVudE5vbkVtcHR5U3RyaW5nID0gbW9kVXRpbHMuYXNzZXJ0QXJndW1lbnROb25FbXB0eVN0cmluZztcclxuICAgICAgICB0aGlzLmhlbHBlcnMuYXNzZXJ0QXJndW1lbnROdW1iZXIgPSBtb2RVdGlscy5hc3NlcnRBcmd1bWVudE51bWJlcjtcclxuICAgICAgICB0aGlzLmhlbHBlcnMuYXNzZXJ0QXJndW1lbnROdW1iZXJOb25OZWdhdGl2ZSA9IG1vZFV0aWxzLmFzc2VydEFyZ3VtZW50TnVtYmVyTm9uTmVnYXRpdmU7XHJcbiAgICAgICAgdGhpcy5oZWxwZXJzLmFzc2VydEFyZ3VtZW50Qm9vbCA9IG1vZFV0aWxzLmFzc2VydEFyZ3VtZW50Qm9vbDtcclxuICAgICAgICB0aGlzLmhlbHBlcnMuYXNzZXJ0QXJndW1lbnRCb29sT3B0aW9uYWwgPSBtb2RVdGlscy5hc3NlcnRBcmd1bWVudEJvb2xPcHRpb25hbDtcclxuICAgICAgICB0aGlzLmhlbHBlcnMuYXNzZXJ0QXJndW1lbnRUaW1lb3V0ID0gbW9kVXRpbHMuYXNzZXJ0QXJndW1lbnRUaW1lb3V0O1xyXG4gICAgICAgIHRoaXMuaGVscGVycy5hc3NlcnRBcmd1bWVudFN0cmluZyA9IG1vZFV0aWxzLmFzc2VydEFyZ3VtZW50U3RyaW5nO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIF9nZXRIQVIoKSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3QgdHlwZXMgPSBhd2FpdCB0aGlzLmRyaXZlci5nZXRMb2dUeXBlcygpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVzLmluY2x1ZGVzKCdwZXJmb3JtYW5jZScpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsb2dzID0gYXdhaXQgdGhpcy5kcml2ZXIuZ2V0TG9ncygncGVyZm9ybWFuY2UnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBpbiBvbmUgaW5zdGFuY2UsIGxvZ3Mgd2FzIG5vdCBpdGVyYWJsZSBmb3Igc29tZSByZWFzb24gLSBoZW5jZSB0aGUgZm9sbG93aW5nIGNoZWNrOlxyXG4gICAgICAgICAgICAgICAgaWYgKCFsb2dzIHx8IHR5cGVvZiBsb2dzW1N5bWJvbC5pdGVyYXRvcl0gIT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcignZ2V0SEFSOiBsb2dzIG5vdCBpdGVyYWJsZTogJyArIEpTT04uc3RyaW5naWZ5KGxvZ3MpKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBldmVudHMgPSBbXTtcclxuICAgICAgICAgICAgICAgIGZvciAobGV0IGxvZyBvZiBsb2dzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbXNnT2JqID0gSlNPTi5wYXJzZShsb2cubWVzc2FnZSk7ICAgLy8gcmV0dXJuZWQgYXMgc3RyaW5nXHJcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRzLnB1c2gobXNnT2JqLm1lc3NhZ2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGhhciA9IGhhckZyb21NZXNzYWdlcyhldmVudHMpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGhhcik7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ1VuYWJsZSB0byBmZXRjaCBIQVI6ICcgKyBlLnRvU3RyaW5nKCkpO1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgY2hlY2tXYWl0Rm9yQW5ndWxhcigpIHtcclxuICAgICAgICBpZiAodGhpcy5hdXRvV2FpdEZvckFuZ3VsYXIpIHtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yQW5ndWxhcih0aGlzLmF1dG9XYWl0Rm9yQW5ndWxhclJvb3RTZWxlY3RvciwgdGhpcy5hdXRvV2FpdEZvckFuZ3VsYXJUaW1lb3V0KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgX3NlbmRSZXN1bHRTdGF0dXNUb0xhbWJkYVRlc3Qoc3RhdHVzKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgbGFtYmRhQ3JlZGVudGlhbHMgPSB7XHJcbiAgICAgICAgICAgICAgICB1c2VybmFtZTogdGhpcy53ZGlvT3B0cy51c2VyLFxyXG4gICAgICAgICAgICAgICAgYWNjZXNzS2V5OiB0aGlzLndkaW9PcHRzLmtleVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjb25zdCBzZXNzaW9uSWQgPSB0aGlzLmRyaXZlci5zZXNzaW9uSWQ7XHJcbiAgICAgICAgICAgIGNvbnN0IGxhbWJkYUF1dG9tYXRpb25DbGllbnQgPSBsYW1iZGFSZXN0Q2xpZW50LkF1dG9tYXRpb25DbGllbnQoXHJcbiAgICAgICAgICAgICAgICBsYW1iZGFDcmVkZW50aWFsc1xyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0Qm9keSA9IHtcclxuICAgICAgICAgICAgICAgIHN0YXR1c19pbmQ6IHN0YXR1cyA9PT0gJ1BBU1NFRCcgPyAncGFzc2VkJyA6ICdmYWlsZWQnXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBsYW1iZGFBdXRvbWF0aW9uQ2xpZW50LnVwZGF0ZVNlc3Npb25CeUlkKHNlc3Npb25JZCwgcmVxdWVzdEJvZHksIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5lcnJvcignVW5hYmxlIHRvIHNlbmQgcmVzdWx0IHN0YXR1cyB0byBMYW1iZGFUZXN0OiAnICsgZS50b1N0cmluZygpKTtcclxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIF9zZW5kUmVzdWx0U3RhdHVzVG9UZXN0aW5nQm90KHN0YXR1cykge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHNlc3Npb25JZCA9IHRoaXMuZHJpdmVyLnNlc3Npb25JZDtcclxuICAgICAgICAgICAgY29uc3QgdGIgPSBuZXcgVGVzdGluZ0JvdCh7XHJcbiAgICAgICAgICAgICAgICBhcGlfa2V5OiB0aGlzLndkaW9PcHRzLnVzZXIsXHJcbiAgICAgICAgICAgICAgICBhcGlfc2VjcmV0OiB0aGlzLndkaW9PcHRzLmtleVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgY29uc3QgdGVzdERhdGEgPSB7IFwidGVzdFtzdWNjZXNzXVwiIDogc3RhdHVzID09PSAnUEFTU0VEJyA/IFwiMVwiIDogXCIwXCIgfTtcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgIHRiLnVwZGF0ZVRlc3QodGVzdERhdGEsIHNlc3Npb25JZCwgZnVuY3Rpb24oZXJyb3IsIHRlc3REZXRhaWxzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCdVbmFibGUgdG8gc2VuZCByZXN1bHQgc3RhdHVzIHRvIFRlc3RpbmdCb3Q6ICcgKyBlLnRvU3RyaW5nKCkpO1xyXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgX3NlbmRSZXN1bHRTdGF0dXNUb0Jyb3dzZXJzdGFjayhzdGF0dXMpIHtcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0Qm9keSA9IHtcclxuICAgICAgICAgICAgICAgIHN0YXR1czogc3RhdHVzID09PSAnUEFTU0VEJyA/ICdwYXNzZWQnIDogJ2ZhaWxlZCdcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgICAgICB1cmw6IGBodHRwczovL2FwaS5icm93c2Vyc3RhY2suY29tL2F1dG9tYXRlL3Nlc3Npb25zLyR7dGhpcy5kcml2ZXIuc2Vzc2lvbklkfS5qc29uYCxcclxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BVVCcsXHJcbiAgICAgICAgICAgICAgICBqc29uOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIGJvZHk6IHJlcXVlc3RCb2R5LFxyXG4gICAgICAgICAgICAgICAgJ2F1dGgnOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgJ3VzZXInOiB0aGlzLndkaW9PcHRzLnVzZXIsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3Bhc3MnOiB0aGlzLndkaW9PcHRzLmtleSxcclxuICAgICAgICAgICAgICAgICAgICAnc2VuZEltbWVkaWF0ZWx5JzogZmFsc2VcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgcmVxdWVzdChvcHRpb25zLCAoZXJyLCByZXMsIGJvZHkpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoJ1VuYWJsZSB0byBzZW5kIHJlc3VsdCBzdGF0dXMgdG8gQnJvd3NlcnN0YWNrOiAnICsgZS50b1N0cmluZygpKTtcclxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG4iXX0=
|