UNPKG

wdio-lambdatest-service

Version:

A WebdriverIO service that manages tunnel and job metadata for LambdaTest.

196 lines (195 loc) 32.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; require("source-map-support/register"); var _formData = _interopRequireDefault(require("form-data")); var _fs = _interopRequireDefault(require("fs")); var _axios = _interopRequireDefault(require("axios")); var _perf_hooks = require("perf_hooks"); var _logger = _interopRequireDefault(require("@wdio/logger")); var _nodeTunnel = _interopRequireDefault(require("@lambdatest/node-tunnel")); var _constants = require("./constants.js"); var _util = require("./util.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } const log = (0, _logger.default)('@wdio/lambdatest-service'); const colors = require('colors'); class LambdaTestLauncher { constructor(options) { _defineProperty(this, "lambdatestTunnelProcess", void 0); _defineProperty(this, "options", void 0); this.options = options; } configureCapabilities(capabilities, key, value) { const updateCapability = capability => { if (capability['lt:options']) { capability['LT:Options'] = { ...capability['lt:options'] }; delete capability['lt:options']; } if (capability['LT:Options'] === undefined) { capability[key] = value; } else { capability['LT:Options'][key] = value; } }; if (Array.isArray(capabilities)) { capabilities.forEach(updateCapability); } else if (typeof capabilities === 'object') { updateCapability(capabilities); } } async onPrepare(config, capabilities) { if (this.options.app_upload) { try { var _this$options$app, _this$options$app$app, _this$options$app2, _this$options$app$app2, _this$options$app3, _this$options$app$cus, _this$options$app4; const appName = (_this$options$app = this.options.app) === null || _this$options$app === void 0 ? void 0 : _this$options$app.app_name; if (!appName) throw new Error(colors.yellow('App name is missing.\n')); const appPath = (_this$options$app$app = (_this$options$app2 = this.options.app) === null || _this$options$app2 === void 0 ? void 0 : _this$options$app2.app_path) !== null && _this$options$app$app !== void 0 ? _this$options$app$app : null; const appUrl = (_this$options$app$app2 = (_this$options$app3 = this.options.app) === null || _this$options$app3 === void 0 ? void 0 : _this$options$app3.app_url) !== null && _this$options$app$app2 !== void 0 ? _this$options$app$app2 : null; const customId = (_this$options$app$cus = (_this$options$app4 = this.options.app) === null || _this$options$app4 === void 0 ? void 0 : _this$options$app4.custom_id) !== null && _this$options$app$cus !== void 0 ? _this$options$app$cus : null; let data = new _formData.default(); data.append('name', appName); data.append(appPath !== null ? 'appFile' : 'url', appPath !== null ? _fs.default.createReadStream(appPath) : appUrl); if (customId !== null) data.append('custom_id', customId); let headerEnv = `Basic ${Buffer.from(config.user + ':' + config.key).toString('base64')}`; let body = { method: 'post', maxBodyLength: Infinity, url: 'https://manual-api.lambdatest.com/app/upload/realDevice', headers: { 'Authorization': headerEnv, ...data.getHeaders() }, data: data }; const response = await _axios.default.request(body); console.log(colors.green(JSON.stringify(response.data))); const envAppUrl = response.data.app_url; if (this.options.app.enableCapability) { this.configureCapabilities(capabilities, 'app', envAppUrl); } const appId = response.data.app_id; if (appPath && appPath.includes('.apk') || appUrl && appUrl.includes('.apk')) { await checkPatchUrl(appId, headerEnv); } } catch (error) { console.error(error.message); } } if (!this.options.tunnel) { return; } const tunnelArguments = { user: config.user, key: config.key, ...this.options.lambdatestOpts }; this.lambdatestTunnelProcess = new _nodeTunnel.default(); this.configureCapabilities(capabilities, 'tunnel', true); const obs = new _perf_hooks.PerformanceObserver(list => { const entry = list.getEntries()[0]; log.info(`LambdaTest Tunnel successfully started after ${entry.duration}ms`); }); obs.observe({ entryTypes: ['measure'], buffered: false }); let timer; _perf_hooks.performance.mark('ltTunnelStart'); return Promise.race([(new Promise((resolve, reject) => { this.lambdatestTunnelProcess.start(tunnelArguments, err => { if (err) { obs.disconnect(); return reject(err); } this.lambdatestTunnelProcess.getTunnelName(tunnelName => { this.configureCapabilities(capabilities, 'tunnelName', tunnelName); obs.disconnect(); resolve(); }); }); })), new Promise((resolve, reject) => { timer = setTimeout(() => { obs.disconnect(); reject(new Error(_constants.TUNNEL_START_FAILED)); }, _constants.TUNNEL_STOP_TIMEOUT); })]).then(result => { clearTimeout(timer); _perf_hooks.performance.mark('ltTunnelEnd'); _perf_hooks.performance.measure('bootTime', 'ltTunnelStart', 'ltTunnelEnd'); obs.disconnect(); return Promise.resolve(result); }, err => { clearTimeout(timer); obs.disconnect(); return Promise.reject(err); }); } async onComplete(exitCode, config) { try { var _this$options; const updateBuildStatus = ((_this$options = this.options) === null || _this$options === void 0 ? void 0 : _this$options.updateBuildStatusOnRetry) === true; if (updateBuildStatus && exitCode === 0 && (config === null || config === void 0 ? void 0 : config.product) === 'appAutomation' && config !== null && config !== void 0 && config.sessionId) { const lambdaCredentials = { username: config.user, accessKey: config.key, isApp: (config === null || config === void 0 ? void 0 : config.product) === 'appAutomation' ? true : false }; await (0, _util.updateBuildStatusForSession)(config.sessionId, lambdaCredentials, exitCode); } } catch (error) { console.error(error.message); } if (!this.lambdatestTunnelProcess || typeof this.lambdatestTunnelProcess.isRunning !== 'function' || !this.lambdatestTunnelProcess.isRunning()) { return; } let timer; return Promise.race([new Promise((resolve, reject) => { this.lambdatestTunnelProcess.stop(err => { if (err) return reject(err); resolve(); }); }), new Promise((resolve, reject) => { timer = setTimeout(() => reject(new Error(_constants.TUNNEL_STOP_FAILED)), _constants.TUNNEL_STOP_TIMEOUT); })]).then(() => { clearTimeout(timer); return Promise.resolve(); }, err => { clearTimeout(timer); return Promise.reject(err); }); } } exports.default = LambdaTestLauncher; async function checkPatchUrl(appId, headerEnv) { let config = { method: 'get', maxBodyLength: Infinity, url: `https://manual-api.lambdatest.com/app/${appId}/url?reinstall=true`, headers: { 'Authorization': headerEnv } }; let isLoaded = false; while (!isLoaded) { try { const response = await _axios.default.request(config); const patchedUrl = response.data.patched_url; if (patchedUrl !== null) { isLoaded = true; break; } console.log('Waiting for app to be loaded...'); } catch (error) { console.error('Error occurred:', error.message); } await new Promise(resolve => setTimeout(resolve, 15000)); } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfZm9ybURhdGEiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9mcyIsIl9heGlvcyIsIl9wZXJmX2hvb2tzIiwiX2xvZ2dlciIsIl9ub2RlVHVubmVsIiwiX2NvbnN0YW50cyIsIl91dGlsIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiX2RlZmluZVByb3BlcnR5IiwiciIsInQiLCJfdG9Qcm9wZXJ0eUtleSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwidmFsdWUiLCJlbnVtZXJhYmxlIiwiY29uZmlndXJhYmxlIiwid3JpdGFibGUiLCJpIiwiX3RvUHJpbWl0aXZlIiwiU3ltYm9sIiwidG9QcmltaXRpdmUiLCJjYWxsIiwiVHlwZUVycm9yIiwiU3RyaW5nIiwiTnVtYmVyIiwibG9nIiwibG9nZ2VyIiwiY29sb3JzIiwiTGFtYmRhVGVzdExhdW5jaGVyIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwiY29uZmlndXJlQ2FwYWJpbGl0aWVzIiwiY2FwYWJpbGl0aWVzIiwia2V5IiwidXBkYXRlQ2FwYWJpbGl0eSIsImNhcGFiaWxpdHkiLCJ1bmRlZmluZWQiLCJBcnJheSIsImlzQXJyYXkiLCJmb3JFYWNoIiwib25QcmVwYXJlIiwiY29uZmlnIiwiYXBwX3VwbG9hZCIsIl90aGlzJG9wdGlvbnMkYXBwIiwiX3RoaXMkb3B0aW9ucyRhcHAkYXBwIiwiX3RoaXMkb3B0aW9ucyRhcHAyIiwiX3RoaXMkb3B0aW9ucyRhcHAkYXBwMiIsIl90aGlzJG9wdGlvbnMkYXBwMyIsIl90aGlzJG9wdGlvbnMkYXBwJGN1cyIsIl90aGlzJG9wdGlvbnMkYXBwNCIsImFwcE5hbWUiLCJhcHAiLCJhcHBfbmFtZSIsIkVycm9yIiwieWVsbG93IiwiYXBwUGF0aCIsImFwcF9wYXRoIiwiYXBwVXJsIiwiYXBwX3VybCIsImN1c3RvbUlkIiwiY3VzdG9tX2lkIiwiZGF0YSIsIkZvcm1EYXRhIiwiYXBwZW5kIiwiZnMiLCJjcmVhdGVSZWFkU3RyZWFtIiwiaGVhZGVyRW52IiwiQnVmZmVyIiwiZnJvbSIsInVzZXIiLCJ0b1N0cmluZyIsImJvZHkiLCJtZXRob2QiLCJtYXhCb2R5TGVuZ3RoIiwiSW5maW5pdHkiLCJ1cmwiLCJoZWFkZXJzIiwiZ2V0SGVhZGVycyIsInJlc3BvbnNlIiwiYXhpb3MiLCJyZXF1ZXN0IiwiY29uc29sZSIsImdyZWVuIiwiSlNPTiIsInN0cmluZ2lmeSIsImVudkFwcFVybCIsImVuYWJsZUNhcGFiaWxpdHkiLCJhcHBJZCIsImFwcF9pZCIsImluY2x1ZGVzIiwiY2hlY2tQYXRjaFVybCIsImVycm9yIiwibWVzc2FnZSIsInR1bm5lbCIsInR1bm5lbEFyZ3VtZW50cyIsImxhbWJkYXRlc3RPcHRzIiwibGFtYmRhdGVzdFR1bm5lbFByb2Nlc3MiLCJMYW1iZGFUZXN0VHVubmVsTGF1bmNoZXIiLCJvYnMiLCJQZXJmb3JtYW5jZU9ic2VydmVyIiwibGlzdCIsImVudHJ5IiwiZ2V0RW50cmllcyIsImluZm8iLCJkdXJhdGlvbiIsIm9ic2VydmUiLCJlbnRyeVR5cGVzIiwiYnVmZmVyZWQiLCJ0aW1lciIsInBlcmZvcm1hbmNlIiwibWFyayIsIlByb21pc2UiLCJyYWNlIiwicmVzb2x2ZSIsInJlamVjdCIsInN0YXJ0IiwiZXJyIiwiZGlzY29ubmVjdCIsImdldFR1bm5lbE5hbWUiLCJ0dW5uZWxOYW1lIiwic2V0VGltZW91dCIsIlRVTk5FTF9TVEFSVF9GQUlMRUQiLCJUVU5ORUxfU1RPUF9USU1FT1VUIiwidGhlbiIsInJlc3VsdCIsImNsZWFyVGltZW91dCIsIm1lYXN1cmUiLCJvbkNvbXBsZXRlIiwiZXhpdENvZGUiLCJfdGhpcyRvcHRpb25zIiwidXBkYXRlQnVpbGRTdGF0dXMiLCJ1cGRhdGVCdWlsZFN0YXR1c09uUmV0cnkiLCJwcm9kdWN0Iiwic2Vzc2lvbklkIiwibGFtYmRhQ3JlZGVudGlhbHMiLCJ1c2VybmFtZSIsImFjY2Vzc0tleSIsImlzQXBwIiwidXBkYXRlQnVpbGRTdGF0dXNGb3JTZXNzaW9uIiwiaXNSdW5uaW5nIiwic3RvcCIsIlRVTk5FTF9TVE9QX0ZBSUxFRCIsImV4cG9ydHMiLCJpc0xvYWRlZCIsInBhdGNoZWRVcmwiLCJwYXRjaGVkX3VybCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9sYXVuY2hlci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgRm9ybURhdGEgZnJvbSAnZm9ybS1kYXRhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuXG5pbXBvcnQgeyBwZXJmb3JtYW5jZSwgUGVyZm9ybWFuY2VPYnNlcnZlciB9IGZyb20gJ3BlcmZfaG9va3MnXG5pbXBvcnQgbG9nZ2VyIGZyb20gJ0B3ZGlvL2xvZ2dlcidcbmltcG9ydCBMYW1iZGFUZXN0VHVubmVsTGF1bmNoZXIgZnJvbSAnQGxhbWJkYXRlc3Qvbm9kZS10dW5uZWwnXG5pbXBvcnQgeyBUVU5ORUxfU1RBUlRfRkFJTEVELCBUVU5ORUxfU1RPUF9GQUlMRUQsIFRVTk5FTF9TVE9QX1RJTUVPVVQgfSBmcm9tICcuL2NvbnN0YW50cy5qcydcbmltcG9ydCB7IHVwZGF0ZUJ1aWxkU3RhdHVzRm9yU2Vzc2lvbiB9IGZyb20gJy4vdXRpbC5qcydcbmNvbnN0IGxvZyA9IGxvZ2dlcignQHdkaW8vbGFtYmRhdGVzdC1zZXJ2aWNlJylcbmNvbnN0IGNvbG9ycyA9IHJlcXVpcmUoJ2NvbG9ycycpO1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGFtYmRhVGVzdExhdW5jaGVyIHtcbiAgICBsYW1iZGF0ZXN0VHVubmVsUHJvY2Vzc1xuICAgIG9wdGlvbnNcblxuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9uc1xuICAgIH1cblxuICAgIGNvbmZpZ3VyZUNhcGFiaWxpdGllcyhjYXBhYmlsaXRpZXMsIGtleSwgdmFsdWUpIHtcbiAgICAgICAgY29uc3QgdXBkYXRlQ2FwYWJpbGl0eSA9IChjYXBhYmlsaXR5KSA9PiB7XG4gICAgICAgICAgICBpZiAoY2FwYWJpbGl0eVsnbHQ6b3B0aW9ucyddKSB7XG4gICAgICAgICAgICAgICAgY2FwYWJpbGl0eVsnTFQ6T3B0aW9ucyddID0geyAuLi5jYXBhYmlsaXR5WydsdDpvcHRpb25zJ10gfTtcbiAgICAgICAgICAgICAgICBkZWxldGUgY2FwYWJpbGl0eVsnbHQ6b3B0aW9ucyddO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNhcGFiaWxpdHlbJ0xUOk9wdGlvbnMnXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgY2FwYWJpbGl0eVtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhcGFiaWxpdHlbJ0xUOk9wdGlvbnMnXVtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNhcGFiaWxpdGllcykpIHtcbiAgICAgICAgICAgIGNhcGFiaWxpdGllcy5mb3JFYWNoKHVwZGF0ZUNhcGFiaWxpdHkpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjYXBhYmlsaXRpZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB1cGRhdGVDYXBhYmlsaXR5KGNhcGFiaWxpdGllcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtb2RpZnkgY29uZmlnIGFuZCBsYXVuY2ggdHVubmVsXG4gICAgYXN5bmMgb25QcmVwYXJlKGNvbmZpZywgY2FwYWJpbGl0aWVzKSB7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5hcHBfdXBsb2FkKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBjb25zdCBhcHBOYW1lID0gdGhpcy5vcHRpb25zLmFwcD8uYXBwX25hbWU7XG4gICAgICAgICAgICAgIGlmICghYXBwTmFtZSkgdGhyb3cgbmV3IEVycm9yKGNvbG9ycy55ZWxsb3coJ0FwcCBuYW1lIGlzIG1pc3NpbmcuXFxuJykpO1xuICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgY29uc3QgYXBwUGF0aCA9IHRoaXMub3B0aW9ucy5hcHA/LmFwcF9wYXRoID8/IG51bGw7XG4gICAgICAgICAgICAgIGNvbnN0IGFwcFVybCA9IHRoaXMub3B0aW9ucy5hcHA/LmFwcF91cmwgPz8gbnVsbDtcbiAgICAgICAgICAgICAgY29uc3QgY3VzdG9tSWQgPSB0aGlzLm9wdGlvbnMuYXBwPy5jdXN0b21faWQgPz8gbnVsbDtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICBsZXQgZGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgICBkYXRhLmFwcGVuZCgnbmFtZScsIGFwcE5hbWUpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgIGRhdGEuYXBwZW5kKGFwcFBhdGggIT09IG51bGwgPyAnYXBwRmlsZScgOiAndXJsJywgYXBwUGF0aCAhPT0gbnVsbCA/IGZzLmNyZWF0ZVJlYWRTdHJlYW0oYXBwUGF0aCkgOiBhcHBVcmwpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgIGlmIChjdXN0b21JZCAhPT0gbnVsbCkgZGF0YS5hcHBlbmQoJ2N1c3RvbV9pZCcsIGN1c3RvbUlkKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICBsZXQgaGVhZGVyRW52ID0gYEJhc2ljICR7QnVmZmVyLmZyb20oY29uZmlnLnVzZXIgKyAnOicgKyBjb25maWcua2V5KS50b1N0cmluZygnYmFzZTY0Jyl9YDtcbiAgICAgICAgICAgICAgbGV0IGJvZHkgPSB7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAncG9zdCcsXG4gICAgICAgICAgICAgICAgbWF4Qm9keUxlbmd0aDogSW5maW5pdHksXG4gICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9tYW51YWwtYXBpLmxhbWJkYXRlc3QuY29tL2FwcC91cGxvYWQvcmVhbERldmljZScsXG4gICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgJ0F1dGhvcml6YXRpb24nOiBoZWFkZXJFbnYsXG4gICAgICAgICAgICAgICAgICAuLi5kYXRhLmdldEhlYWRlcnMoKVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZGF0YTogZGF0YVxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MucmVxdWVzdChib2R5KTtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coY29sb3JzLmdyZWVuKEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLmRhdGEpKSk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgY29uc3QgZW52QXBwVXJsID0gcmVzcG9uc2UuZGF0YS5hcHBfdXJsO1xuICAgICAgICAgICAgICBpZih0aGlzLm9wdGlvbnMuYXBwLmVuYWJsZUNhcGFiaWxpdHkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyZUNhcGFiaWxpdGllcyhjYXBhYmlsaXRpZXMsICdhcHAnLCBlbnZBcHBVcmwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgYXBwSWQgPSByZXNwb25zZS5kYXRhLmFwcF9pZDtcbiAgICAgICAgICAgIGlmKChhcHBQYXRoICYmIGFwcFBhdGguaW5jbHVkZXMoJy5hcGsnKSkgfHwgKGFwcFVybCAmJiBhcHBVcmwuaW5jbHVkZXMoJy5hcGsnKSkpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2hlY2tQYXRjaFVybChhcHBJZCwgaGVhZGVyRW52KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLnR1bm5lbCkge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0dW5uZWxBcmd1bWVudHMgPSB7XG4gICAgICAgICAgICB1c2VyOiBjb25maWcudXNlcixcbiAgICAgICAgICAgIGtleTogY29uZmlnLmtleSxcbiAgICAgICAgICAgIC4uLnRoaXMub3B0aW9ucy5sYW1iZGF0ZXN0T3B0c1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5sYW1iZGF0ZXN0VHVubmVsUHJvY2VzcyA9IG5ldyBMYW1iZGFUZXN0VHVubmVsTGF1bmNoZXIoKVxuXG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FwYWJpbGl0aWVzKGNhcGFiaWxpdGllcywgJ3R1bm5lbCcsIHRydWUpO1xuICAgICAgICAvLyBtZWFzdXJlIExUIGJvb3QgdGltZVxuICAgICAgICBjb25zdCBvYnMgPSBuZXcgUGVyZm9ybWFuY2VPYnNlcnZlcihsaXN0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVudHJ5ID0gbGlzdC5nZXRFbnRyaWVzKClbMF1cbiAgICAgICAgICAgIGxvZy5pbmZvKFxuICAgICAgICAgICAgICAgIGBMYW1iZGFUZXN0IFR1bm5lbCBzdWNjZXNzZnVsbHkgc3RhcnRlZCBhZnRlciAke2VudHJ5LmR1cmF0aW9ufW1zYFxuICAgICAgICAgICAgKVxuICAgICAgICB9KVxuICAgICAgICBvYnMub2JzZXJ2ZSh7IGVudHJ5VHlwZXM6IFsnbWVhc3VyZSddLCBidWZmZXJlZDogZmFsc2UgfSlcblxuICAgICAgICBsZXQgdGltZXJcbiAgICAgICAgcGVyZm9ybWFuY2UubWFyaygnbHRUdW5uZWxTdGFydCcpXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJhY2UoW1xuICAgICAgICAgICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+fSAqLyhuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5sYW1iZGF0ZXN0VHVubmVsUHJvY2Vzcy5zdGFydCh0dW5uZWxBcmd1bWVudHMsIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9icy5kaXNjb25uZWN0KClcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXJyKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGFtYmRhdGVzdFR1bm5lbFByb2Nlc3MuZ2V0VHVubmVsTmFtZSh0dW5uZWxOYW1lID0+IHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmVDYXBhYmlsaXRpZXMoY2FwYWJpbGl0aWVzLCAndHVubmVsTmFtZScsIHR1bm5lbE5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMuZGlzY29ubmVjdCgpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKClcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgb2JzLmRpc2Nvbm5lY3QoKVxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFRVTk5FTF9TVEFSVF9GQUlMRUQpKVxuICAgICAgICAgICAgICAgIH0sIFRVTk5FTF9TVE9QX1RJTUVPVVQpXG4gICAgICAgICAgICB9KVxuICAgICAgICBdKS50aGVuKFxuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgICAgIChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpXG4gICAgICAgICAgICAgICAgcGVyZm9ybWFuY2UubWFyaygnbHRUdW5uZWxFbmQnKVxuICAgICAgICAgICAgICAgIHBlcmZvcm1hbmNlLm1lYXN1cmUoJ2Jvb3RUaW1lJywgJ2x0VHVubmVsU3RhcnQnLCAnbHRUdW5uZWxFbmQnKVxuICAgICAgICAgICAgICAgIG9icy5kaXNjb25uZWN0KClcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdClcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKVxuICAgICAgICAgICAgICAgIG9icy5kaXNjb25uZWN0KClcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyKVxuICAgICAgICAgICAgfVxuICAgICAgICApXG4gICAgfVxuXG4gICAgYXN5bmMgb25Db21wbGV0ZShleGl0Q29kZSwgY29uZmlnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCB1cGRhdGVCdWlsZFN0YXR1cyA9IHRoaXMub3B0aW9ucz8udXBkYXRlQnVpbGRTdGF0dXNPblJldHJ5ID09PSB0cnVlO1xuICAgICAgICAgICAgaWYgKHVwZGF0ZUJ1aWxkU3RhdHVzICYmIGV4aXRDb2RlID09PSAwICYmIGNvbmZpZz8ucHJvZHVjdCA9PT0gJ2FwcEF1dG9tYXRpb24nICYmIGNvbmZpZz8uc2Vzc2lvbklkKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGFtYmRhQ3JlZGVudGlhbHMgPSB7XG4gICAgICAgICAgICAgICAgICAgIHVzZXJuYW1lOiBjb25maWcudXNlcixcbiAgICAgICAgICAgICAgICAgICAgYWNjZXNzS2V5OiBjb25maWcua2V5LFxuICAgICAgICAgICAgICAgICAgICBpc0FwcDogY29uZmlnPy5wcm9kdWN0ID09PSAnYXBwQXV0b21hdGlvbicgPyB0cnVlIDogZmFsc2VcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGF3YWl0IHVwZGF0ZUJ1aWxkU3RhdHVzRm9yU2Vzc2lvbihjb25maWcuc2Vzc2lvbklkLCBsYW1iZGFDcmVkZW50aWFscywgZXhpdENvZGUpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1jYXRjaChlcnJvcil7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgIXRoaXMubGFtYmRhdGVzdFR1bm5lbFByb2Nlc3MgfHxcbiAgICAgICAgICAgIHR5cGVvZiB0aGlzLmxhbWJkYXRlc3RUdW5uZWxQcm9jZXNzLmlzUnVubmluZyAhPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAgICAgIXRoaXMubGFtYmRhdGVzdFR1bm5lbFByb2Nlc3MuaXNSdW5uaW5nKClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB0aW1lclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmxhbWJkYXRlc3RUdW5uZWxQcm9jZXNzLnN0b3AoZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikgcmV0dXJuIHJlamVjdChlcnIpXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICAgICAgICAgIHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiByZWplY3QoIG5ldyBFcnJvcihUVU5ORUxfU1RPUF9GQUlMRUQpKSwgVFVOTkVMX1NUT1BfVElNRU9VVClcbiAgICAgICAgICAgIH0pXG4gICAgICAgIF0pLnRoZW4oXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKVxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKVxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnIpXG4gICAgICAgICAgICB9XG4gICAgICAgIClcbiAgICB9XG5cbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tQYXRjaFVybChhcHBJZCwgaGVhZGVyRW52KSB7XG4gICAgbGV0IGNvbmZpZyA9IHtcbiAgICAgICAgbWV0aG9kOiAnZ2V0JyxcbiAgICAgICAgbWF4Qm9keUxlbmd0aDogSW5maW5pdHksXG4gICAgICAgIHVybDogYGh0dHBzOi8vbWFudWFsLWFwaS5sYW1iZGF0ZXN0LmNvbS9hcHAvJHthcHBJZH0vdXJsP3JlaW5zdGFsbD10cnVlYCxcbiAgICAgICAgaGVhZGVyczogeyBcbiAgICAgICAgICAnQXV0aG9yaXphdGlvbic6IGhlYWRlckVudlxuICAgICAgICB9XG4gICAgICB9O1xuICAgIGxldCBpc0xvYWRlZCA9IGZhbHNlO1xuICAgIHdoaWxlICghaXNMb2FkZWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5yZXF1ZXN0KGNvbmZpZyk7XG4gICAgICAgIGNvbnN0IHBhdGNoZWRVcmwgPSByZXNwb25zZS5kYXRhLnBhdGNoZWRfdXJsO1xuXG4gICAgICAgIGlmIChwYXRjaGVkVXJsICE9PSBudWxsKSB7XG4gICAgICAgICAgICBpc0xvYWRlZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUubG9nKCdXYWl0aW5nIGZvciBhcHAgdG8gYmUgbG9hZGVkLi4uJyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG9jY3VycmVkOicsIGVycm9yLm1lc3NhZ2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgMTUgc2Vjb25kcyBiZWZvcmUgbWFraW5nIHRoZSBuZXh0IHJlcXVlc3RcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDE1MDAwKSk7XG4gICAgfVxufSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLElBQUFBLFNBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLEdBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFFLE1BQUEsR0FBQUgsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFHLFdBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLE9BQUEsR0FBQUwsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFLLFdBQUEsR0FBQU4sc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFNLFVBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLEtBQUEsR0FBQVAsT0FBQTtBQUF1RCxTQUFBRCx1QkFBQVMsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUFBLFNBQUFHLGdCQUFBSCxDQUFBLEVBQUFJLENBQUEsRUFBQUMsQ0FBQSxZQUFBRCxDQUFBLEdBQUFFLGNBQUEsQ0FBQUYsQ0FBQSxNQUFBSixDQUFBLEdBQUFPLE1BQUEsQ0FBQUMsY0FBQSxDQUFBUixDQUFBLEVBQUFJLENBQUEsSUFBQUssS0FBQSxFQUFBSixDQUFBLEVBQUFLLFVBQUEsTUFBQUMsWUFBQSxNQUFBQyxRQUFBLFVBQUFaLENBQUEsQ0FBQUksQ0FBQSxJQUFBQyxDQUFBLEVBQUFMLENB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