1 | ;
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const async_event_emitter_1 = __importDefault(require("../utils/async-event-emitter"));
|
7 | const testcafe_legacy_api_1 = require("testcafe-legacy-api");
|
8 | const test_run_1 = __importDefault(require("../test-run"));
|
9 | const session_controller_1 = __importDefault(require("../test-run/session-controller"));
|
10 | const QUARANTINE_THRESHOLD = 3;
|
11 | const DISCONNECT_THRESHOLD = 3;
|
12 | class Quarantine {
|
13 | constructor() {
|
14 | this.attempts = [];
|
15 | }
|
16 | getFailedAttempts() {
|
17 | return this.attempts.filter(errors => !!errors.length);
|
18 | }
|
19 | getPassedAttempts() {
|
20 | return this.attempts.filter(errors => errors.length === 0);
|
21 | }
|
22 | getNextAttemptNumber() {
|
23 | return this.attempts.length + 1;
|
24 | }
|
25 | isThresholdReached(extraErrors) {
|
26 | const { failedTimes, passedTimes } = this._getAttemptsResult(extraErrors);
|
27 | const failedThresholdReached = failedTimes >= QUARANTINE_THRESHOLD;
|
28 | const passedThresholdReached = passedTimes >= QUARANTINE_THRESHOLD;
|
29 | return failedThresholdReached || passedThresholdReached;
|
30 | }
|
31 | isFirstAttemptSuccessful(extraErrors) {
|
32 | const { failedTimes, passedTimes } = this._getAttemptsResult(extraErrors);
|
33 | return failedTimes === 0 && passedTimes > 0;
|
34 | }
|
35 | _getAttemptsResult(extraErrors) {
|
36 | let failedTimes = this.getFailedAttempts().length;
|
37 | let passedTimes = this.getPassedAttempts().length;
|
38 | if (extraErrors) {
|
39 | if (extraErrors.length)
|
40 | failedTimes += extraErrors.length;
|
41 | else
|
42 | passedTimes += 1;
|
43 | }
|
44 | return { failedTimes, passedTimes };
|
45 | }
|
46 | }
|
47 | class TestRunController extends async_event_emitter_1.default {
|
48 | constructor(test, index, proxy, screenshots, warningLog, fixtureHookController, opts) {
|
49 | super();
|
50 | this.test = test;
|
51 | this.index = index;
|
52 | this.opts = opts;
|
53 | this.proxy = proxy;
|
54 | this.screenshots = screenshots;
|
55 | this.warningLog = warningLog;
|
56 | this.fixtureHookController = fixtureHookController;
|
57 | this.TestRunCtor = TestRunController._getTestRunCtor(test, opts);
|
58 | this.testRun = null;
|
59 | this.done = false;
|
60 | this.quarantine = null;
|
61 | this.disconnectionCount = 0;
|
62 | if (this.opts.quarantineMode)
|
63 | this.quarantine = new Quarantine();
|
64 | }
|
65 | static _getTestRunCtor(test, opts) {
|
66 | if (opts.TestRunCtor)
|
67 | return opts.TestRunCtor;
|
68 | return test.isLegacy ? testcafe_legacy_api_1.TestRun : test_run_1.default;
|
69 | }
|
70 | async _createTestRun(connection) {
|
71 | const screenshotCapturer = this.screenshots.createCapturerFor(this.test, this.index, this.quarantine, connection, this.warningLog);
|
72 | const TestRunCtor = this.TestRunCtor;
|
73 | this.testRun = new TestRunCtor(this.test, connection, screenshotCapturer, this.warningLog, this.opts);
|
74 | if (this.testRun.addQuarantineInfo)
|
75 | this.testRun.addQuarantineInfo(this.quarantine);
|
76 | if (!this.quarantine || this._isFirstQuarantineAttempt()) {
|
77 | await this.emit('test-run-create', {
|
78 | testRun: this.testRun,
|
79 | legacy: TestRunCtor === testcafe_legacy_api_1.TestRun,
|
80 | test: this.test,
|
81 | index: this.index,
|
82 | quarantine: this.quarantine,
|
83 | });
|
84 | }
|
85 | return this.testRun;
|
86 | }
|
87 | async _endQuarantine() {
|
88 | if (this.quarantine.attempts.length > 1)
|
89 | this.testRun.unstable = this.quarantine.getPassedAttempts().length > 0;
|
90 | await this._emitTestRunDone();
|
91 | }
|
92 | _shouldKeepInQuarantine() {
|
93 | const errors = this.testRun.errs;
|
94 | const hasErrors = !!errors.length;
|
95 | const attempts = this.quarantine.attempts;
|
96 | const isFirstAttempt = this._isFirstQuarantineAttempt();
|
97 | attempts.push(errors);
|
98 | return isFirstAttempt ? hasErrors : !this.quarantine.isThresholdReached();
|
99 | }
|
100 | _isFirstQuarantineAttempt() {
|
101 | return this.quarantine && !this.quarantine.attempts.length;
|
102 | }
|
103 | async _keepInQuarantine() {
|
104 | await this._restartTest();
|
105 | }
|
106 | async _restartTest() {
|
107 | await this.emit('test-run-restart');
|
108 | }
|
109 | async _testRunDoneInQuarantineMode() {
|
110 | if (this._shouldKeepInQuarantine())
|
111 | await this._keepInQuarantine();
|
112 | else
|
113 | await this._endQuarantine();
|
114 | }
|
115 | async _testRunDone() {
|
116 | if (this.quarantine)
|
117 | await this._testRunDoneInQuarantineMode();
|
118 | else
|
119 | await this._emitTestRunDone();
|
120 | }
|
121 | async _emitActionStart(args) {
|
122 | await this.emit('test-action-start', args);
|
123 | }
|
124 | async _emitActionDone(args) {
|
125 | await this.emit('test-action-done', args);
|
126 | }
|
127 | async _emitTestRunDone() {
|
128 | // NOTE: we should report test run completion in order they were completed in browser.
|
129 | // To keep a sequence after fixture hook execution we use completion queue.
|
130 | await this.fixtureHookController.runFixtureAfterHookIfNecessary(this.testRun);
|
131 | this.done = true;
|
132 | await this.emit('test-run-done');
|
133 | }
|
134 | async _emitTestRunStart() {
|
135 | await this.emit('test-run-start');
|
136 | }
|
137 | async _testRunBeforeDone() {
|
138 | let raiseEvent = !this.quarantine;
|
139 | if (!raiseEvent) {
|
140 | const isSuccessfulQuarantineFirstAttempt = this._isFirstQuarantineAttempt() && !this.testRun.errs.length;
|
141 | const isAttemptsThresholdReached = this.quarantine.isThresholdReached(this.testRun.errs);
|
142 | raiseEvent = isSuccessfulQuarantineFirstAttempt || isAttemptsThresholdReached;
|
143 | }
|
144 | if (raiseEvent)
|
145 | await this.emit('test-run-before-done');
|
146 | }
|
147 | _testRunDisconnected(connection) {
|
148 | this.disconnectionCount++;
|
149 | const disconnectionThresholdExceedeed = this.disconnectionCount >= DISCONNECT_THRESHOLD;
|
150 | return connection
|
151 | .processDisconnection(disconnectionThresholdExceedeed)
|
152 | .then(() => {
|
153 | return this._restartTest();
|
154 | });
|
155 | }
|
156 | _assignTestRunEvents(testRun, connection) {
|
157 | testRun.on('action-start', async (args) => this._emitActionStart(Object.assign(args, { testRun })));
|
158 | testRun.on('action-done', async (args) => this._emitActionDone(Object.assign(args, { testRun })));
|
159 | testRun.once('start', async () => this._emitTestRunStart());
|
160 | testRun.once('ready', async () => {
|
161 | if (!this.quarantine || this._isFirstQuarantineAttempt())
|
162 | await this.emit('test-run-ready');
|
163 | });
|
164 | testRun.once('before-done', () => this._testRunBeforeDone());
|
165 | testRun.once('done', () => this._testRunDone());
|
166 | testRun.once('disconnected', () => this._testRunDisconnected(connection));
|
167 | }
|
168 | get blocked() {
|
169 | return this.fixtureHookController.isTestBlocked(this.test);
|
170 | }
|
171 | async start(connection) {
|
172 | const testRun = await this._createTestRun(connection);
|
173 | const hookOk = await this.fixtureHookController.runFixtureBeforeHookIfNecessary(testRun);
|
174 | if (this.test.skip || !hookOk) {
|
175 | await this.emit('test-run-start');
|
176 | await this._emitTestRunDone();
|
177 | return null;
|
178 | }
|
179 | this._assignTestRunEvents(testRun, connection);
|
180 | testRun.start();
|
181 | return session_controller_1.default.getSessionUrl(testRun, this.proxy);
|
182 | }
|
183 | }
|
184 | exports.default = TestRunController;
|
185 | module.exports = exports.default;
|
186 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1ydW4tY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW5uZXIvdGVzdC1ydW4tY29udHJvbGxlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHVGQUE2RDtBQUM3RCw2REFBK0Q7QUFDL0QsMkRBQWtDO0FBQ2xDLHdGQUErRDtBQUUvRCxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUMvQixNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUUvQixNQUFNLFVBQVU7SUFDWjtRQUNJLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxpQkFBaUI7UUFDYixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzRCxDQUFDO0lBRUQsaUJBQWlCO1FBQ2IsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVELG9CQUFvQjtRQUNoQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsa0JBQWtCLENBQUUsV0FBVztRQUMzQixNQUFNLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUUxRSxNQUFNLHNCQUFzQixHQUFHLFdBQVcsSUFBSSxvQkFBb0IsQ0FBQztRQUNuRSxNQUFNLHNCQUFzQixHQUFHLFdBQVcsSUFBSSxvQkFBb0IsQ0FBQztRQUVuRSxPQUFPLHNCQUFzQixJQUFJLHNCQUFzQixDQUFDO0lBQzVELENBQUM7SUFFRCx3QkFBd0IsQ0FBRSxXQUFXO1FBQ2pD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TSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsK0JBQStCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFekYsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUMzQixNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUNsQyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFFRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBRS9DLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUVoQixPQUFPLDRCQUFpQixDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2hFLENBQUM7Q0FDSjtBQXBMRCxvQ0FvTEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQXN5bmNFdmVudEVtaXR0ZXIgZnJvbSAnLi4vdXRpbHMvYXN5bmMtZXZlbnQtZW1pdHRlcic7XG5pbXBvcnQgeyBUZXN0UnVuIGFzIExlZ2FjeVRlc3RSdW4gfSBmcm9tICd0ZXN0Y2FmZS1sZWdhY3ktYXBpJztcbmltcG9ydCBUZXN0UnVuIGZyb20gJy4uL3Rlc3QtcnVuJztcbmltcG9ydCBTZXNzaW9uQ29udHJvbGxlciBmcm9tICcuLi90ZXN0LXJ1bi9zZXNzaW9uLWNvbnRyb2xsZXInO1xuXG5jb25zdCBRVUFSQU5USU5FX1RIUkVTSE9MRCA9IDM7XG5jb25zdCBESVNDT05ORUNUX1RIUkVTSE9MRCA9IDM7XG5cbmNsYXNzIFF1YXJhbnRpbmUge1xuICAgIGNvbnN0cnVjdG9yICgpIHtcbiAgICAgICAgdGhpcy5hdHRlbXB0cyA9IFtdO1xuICAgIH1cblxuICAgIGdldEZhaWxlZEF0dGVtcHRzICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXR0ZW1wdHMuZmlsdGVyKGVycm9ycyA9PiAhIWVycm9ycy5sZW5ndGgpO1xuICAgIH1cblxuICAgIGdldFBhc3NlZEF0dGVtcHRzICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXR0ZW1wdHMuZmlsdGVyKGVycm9ycyA9PiBlcnJvcnMubGVuZ3RoID09PSAwKTtcbiAgICB9XG5cbiAgICBnZXROZXh0QXR0ZW1wdE51bWJlciAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmF0dGVtcHRzLmxlbmd0aCArIDE7XG4gICAgfVxuXG4gICAgaXNUaHJlc2hvbGRSZWFjaGVkIChleHRyYUVycm9ycykge1xuICAgICAgICBjb25zdCB7IGZhaWxlZFRpbWVzLCBwYXNzZWRUaW1lcyB9ID0gdGhpcy5fZ2V0QXR0ZW1wdHNSZXN1bHQoZXh0cmFFcnJvcnMpO1xuXG4gICAgICAgIGNvbnN0IGZhaWxlZFRocmVzaG9sZFJlYWNoZWQgPSBmYWlsZWRUaW1lcyA+PSBRVUFSQU5USU5FX1RIUkVTSE9MRDtcbiAgICAgICAgY29uc3QgcGFzc2VkVGhyZXNob2xkUmVhY2hlZCA9IHBhc3NlZFRpbWVzID49IFFVQVJBTlRJTkVfVEhSRVNIT0xEO1xuXG4gICAgICAgIHJldHVybiBmYWlsZWRUaHJlc2hvbGRSZWFjaGVkIHx8IHBhc3NlZFRocmVzaG9sZFJlYWNoZWQ7XG4gICAgfVxuXG4gICAgaXNGaXJzdEF0dGVtcHRTdWNjZXNzZnVsIChleHRyYUVycm9ycykge1xuICAgICAgICBjb25zdCB7IGZhaWxlZFRpbWVzLCBwYXNzZWRUaW1lcyB9ID0gdGhpcy5fZ2V0QXR0ZW1wdHNSZXN1bHQoZXh0cmFFcnJvcnMpO1xuXG4gICAgICAgIHJldHVybiBmYWlsZWRUaW1lcyA9PT0gMCAmJiBwYXNzZWRUaW1lcyA+IDA7XG4gICAgfVxuXG4gICAgX2dldEF0dGVtcHRzUmVzdWx0IChleHRyYUVycm9ycykge1xuICAgICAgICBsZXQgZmFpbGVkVGltZXMgPSB0aGlzLmdldEZhaWxlZEF0dGVtcHRzKCkubGVuZ3RoO1xuICAgICAgICBsZXQgcGFzc2VkVGltZXMgPSB0aGlzLmdldFBhc3NlZEF0dGVtcHRzKCkubGVuZ3RoO1xuXG4gICAgICAgIGlmIChleHRyYUVycm9ycykge1xuICAgICAgICAgICAgaWYgKGV4dHJhRXJyb3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmYWlsZWRUaW1lcyArPSBleHRyYUVycm9ycy5sZW5ndGg7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgcGFzc2VkVGltZXMgKz0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGZhaWxlZFRpbWVzLCBwYXNzZWRUaW1lcyB9O1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVGVzdFJ1bkNvbnRyb2xsZXIgZXh0ZW5kcyBBc3luY0V2ZW50RW1pdHRlciB7XG4gICAgY29uc3RydWN0b3IgKHRlc3QsIGluZGV4LCBwcm94eSwgc2NyZWVuc2hvdHMsIHdhcm5pbmdMb2csIGZpeHR1cmVIb29rQ29udHJvbGxlciwgb3B0cykge1xuICAgICAgICBzdXBlcigpO1xuXG4gICAgICAgIHRoaXMudGVzdCAgPSB0ZXN0O1xuICAgICAgICB0aGlzLmluZGV4ID0gaW5kZXg7XG4gICAgICAgIHRoaXMub3B0cyAgPSBvcHRzO1xuXG4gICAgICAgIHRoaXMucHJveHkgICAgICAgICAgICAgICAgID0gcHJveHk7XG4gICAgICAgIHRoaXMuc2NyZWVuc2hvdHMgICAgICAgICAgID0gc2NyZWVuc2hvdHM7XG4gICAgICAgIHRoaXMud2FybmluZ0xvZyAgICAgICAgICAgID0gd2FybmluZ0xvZztcbiAgICAgICAgdGhpcy5maXh0dXJlSG9va0NvbnRyb2xsZXIgPSBmaXh0dXJlSG9va0NvbnRyb2xsZXI7XG5cbiAgICAgICAgdGhpcy5UZXN0UnVuQ3RvciA9IFRlc3RSdW5Db250cm9sbGVyLl9nZXRUZXN0UnVuQ3Rvcih0ZXN0LCBvcHRzKTtcblxuICAgICAgICB0aGlzLnRlc3RSdW4gICAgICAgICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMuZG9uZSAgICAgICAgICAgICAgID0gZmFsc2U7XG4gICAgICAgIHRoaXMucXVhcmFudGluZSAgICAgICAgID0gbnVsbDtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0aW9uQ291bnQgPSAwO1xuXG4gICAgICAgIGlmICh0aGlzLm9wdHMucXVhcmFudGluZU1vZGUpXG4gICAgICAgICAgICB0aGlzLnF1YXJhbnRpbmUgPSBuZXcgUXVhcmFudGluZSgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBfZ2V0VGVzdFJ1bkN0b3IgKHRlc3QsIG9wdHMpIHtcbiAgICAgICAgaWYgKG9wdHMuVGVzdFJ1bkN0b3IpXG4gICAgICAgICAgICByZXR1cm4gb3B0cy5UZXN0UnVuQ3RvcjtcblxuICAgICAgICByZXR1cm4gdGVzdC5pc0xlZ2FjeSA/IExlZ2FjeVRlc3RSdW4gOiBUZXN0UnVuO1xuICAgIH1cblxuICAgIGFzeW5jIF9jcmVhdGVUZXN0UnVuIChjb25uZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IHNjcmVlbnNob3RDYXB0dXJlciA9IHRoaXMuc2NyZWVuc2hvdHMuY3JlYXRlQ2FwdHVyZXJGb3IodGhpcy50ZXN0LCB0aGlzLmluZGV4LCB0aGlzLnF1YXJhbnRpbmUsIGNvbm5lY3Rpb24sIHRoaXMud2FybmluZ0xvZyk7XG4gICAgICAgIGNvbnN0IFRlc3RSdW5DdG9yICAgICAgICA9IHRoaXMuVGVzdFJ1bkN0b3I7XG5cbiAgICAgICAgdGhpcy50ZXN0UnVuID0gbmV3IFRlc3RSdW5DdG9yKHRoaXMudGVzdCwgY29ubmVjdGlvbiwgc2NyZWVuc2hvdENhcHR1cmVyLCB0aGlzLndhcm5pbmdMb2csIHRoaXMub3B0cyk7XG5cbiAgICAgICAgaWYgKHRoaXMudGVzdFJ1bi5hZGRRdWFyYW50aW5lSW5mbylcbiAgICAgICAgICAgIHRoaXMudGVzdFJ1bi5hZGRRdWFyYW50aW5lSW5mbyh0aGlzLnF1YXJhbnRpbmUpO1xuXG4gICAgICAgIGlmICghdGhpcy5xdWFyYW50aW5lIHx8IHRoaXMuX2lzRmlyc3RRdWFyYW50aW5lQXR0ZW1wdCgpKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLWNyZWF0ZScsIHtcbiAgICAgICAgICAgICAgICB0ZXN0UnVuOiAgICB0aGlzLnRlc3RSdW4sXG4gICAgICAgICAgICAgICAgbGVnYWN5OiAgICAgVGVzdFJ1bkN0b3IgPT09IExlZ2FjeVRlc3RSdW4sXG4gICAgICAgICAgICAgICAgdGVzdDogICAgICAgdGhpcy50ZXN0LFxuICAgICAgICAgICAgICAgIGluZGV4OiAgICAgIHRoaXMuaW5kZXgsXG4gICAgICAgICAgICAgICAgcXVhcmFudGluZTogdGhpcy5xdWFyYW50aW5lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy50ZXN0UnVuO1xuICAgIH1cblxuICAgIGFzeW5jIF9lbmRRdWFyYW50aW5lICgpIHtcbiAgICAgICAgaWYgKHRoaXMucXVhcmFudGluZS5hdHRlbXB0cy5sZW5ndGggPiAxKVxuICAgICAgICAgICAgdGhpcy50ZXN0UnVuLnVuc3RhYmxlID0gdGhpcy5xdWFyYW50aW5lLmdldFBhc3NlZEF0dGVtcHRzKCkubGVuZ3RoID4gMDtcblxuICAgICAgICBhd2FpdCB0aGlzLl9lbWl0VGVzdFJ1bkRvbmUoKTtcbiAgICB9XG5cbiAgICBfc2hvdWxkS2VlcEluUXVhcmFudGluZSAoKSB7XG4gICAgICAgIGNvbnN0IGVycm9ycyAgICAgICAgID0gdGhpcy50ZXN0UnVuLmVycnM7XG4gICAgICAgIGNvbnN0IGhhc0Vycm9ycyAgICAgID0gISFlcnJvcnMubGVuZ3RoO1xuICAgICAgICBjb25zdCBhdHRlbXB0cyAgICAgICA9IHRoaXMucXVhcmFudGluZS5hdHRlbXB0cztcbiAgICAgICAgY29uc3QgaXNGaXJzdEF0dGVtcHQgPSB0aGlzLl9pc0ZpcnN0UXVhcmFudGluZUF0dGVtcHQoKTtcblxuICAgICAgICBhdHRlbXB0cy5wdXNoKGVycm9ycyk7XG5cbiAgICAgICAgcmV0dXJuIGlzRmlyc3RBdHRlbXB0ID8gaGFzRXJyb3JzIDogIXRoaXMucXVhcmFudGluZS5pc1RocmVzaG9sZFJlYWNoZWQoKTtcbiAgICB9XG5cbiAgICBfaXNGaXJzdFF1YXJhbnRpbmVBdHRlbXB0ICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucXVhcmFudGluZSAmJiAhdGhpcy5xdWFyYW50aW5lLmF0dGVtcHRzLmxlbmd0aDtcbiAgICB9XG5cbiAgICBhc3luYyBfa2VlcEluUXVhcmFudGluZSAoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX3Jlc3RhcnRUZXN0KCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX3Jlc3RhcnRUZXN0ICgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LXJ1bi1yZXN0YXJ0Jyk7XG4gICAgfVxuXG4gICAgYXN5bmMgX3Rlc3RSdW5Eb25lSW5RdWFyYW50aW5lTW9kZSAoKSB7XG4gICAgICAgIGlmICh0aGlzLl9zaG91bGRLZWVwSW5RdWFyYW50aW5lKCkpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9rZWVwSW5RdWFyYW50aW5lKCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2VuZFF1YXJhbnRpbmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfdGVzdFJ1bkRvbmUgKCkge1xuICAgICAgICBpZiAodGhpcy5xdWFyYW50aW5lKVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fdGVzdFJ1bkRvbmVJblF1YXJhbnRpbmVNb2RlKCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2VtaXRUZXN0UnVuRG9uZSgpO1xuICAgIH1cblxuICAgIGFzeW5jIF9lbWl0QWN0aW9uU3RhcnQgKGFyZ3MpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LWFjdGlvbi1zdGFydCcsIGFyZ3MpO1xuICAgIH1cblxuICAgIGFzeW5jIF9lbWl0QWN0aW9uRG9uZSAoYXJncykge1xuICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtYWN0aW9uLWRvbmUnLCBhcmdzKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZW1pdFRlc3RSdW5Eb25lICgpIHtcbiAgICAgICAgLy8gTk9URTogd2Ugc2hvdWxkIHJlcG9ydCB0ZXN0IHJ1biBjb21wbGV0aW9uIGluIG9yZGVyIHRoZXkgd2VyZSBjb21wbGV0ZWQgaW4gYnJvd3Nlci5cbiAgICAgICAgLy8gVG8ga2VlcCBhIHNlcXVlbmNlIGFmdGVyIGZpeHR1cmUgaG9vayBleGVjdXRpb24gd2UgdXNlIGNvbXBsZXRpb24gcXVldWUuXG4gICAgICAgIGF3YWl0IHRoaXMuZml4dHVyZUhvb2tDb250cm9sbGVyLnJ1bkZpeHR1cmVBZnRlckhvb2tJZk5lY2Vzc2FyeSh0aGlzLnRlc3RSdW4pO1xuXG4gICAgICAgIHRoaXMuZG9uZSA9IHRydWU7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5lbWl0KCd0ZXN0LXJ1bi1kb25lJyk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2VtaXRUZXN0UnVuU3RhcnQgKCkge1xuICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLXN0YXJ0Jyk7XG4gICAgfVxuXG4gICAgYXN5bmMgX3Rlc3RSdW5CZWZvcmVEb25lICgpIHtcbiAgICAgICAgbGV0IHJhaXNlRXZlbnQgPSAhdGhpcy5xdWFyYW50aW5lO1xuXG4gICAgICAgIGlmICghcmFpc2VFdmVudCkge1xuICAgICAgICAgICAgY29uc3QgaXNTdWNjZXNzZnVsUXVhcmFudGluZUZpcnN0QXR0ZW1wdCA9IHRoaXMuX2lzRmlyc3RRdWFyYW50aW5lQXR0ZW1wdCgpICYmICF0aGlzLnRlc3RSdW4uZXJycy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBpc0F0dGVtcHRzVGhyZXNob2xkUmVhY2hlZCAgICAgICAgID0gdGhpcy5xdWFyYW50aW5lLmlzVGhyZXNob2xkUmVhY2hlZCh0aGlzLnRlc3RSdW4uZXJycyk7XG5cbiAgICAgICAgICAgIHJhaXNlRXZlbnQgPSBpc1N1Y2Nlc3NmdWxRdWFyYW50aW5lRmlyc3RBdHRlbXB0IHx8IGlzQXR0ZW1wdHNUaHJlc2hvbGRSZWFjaGVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJhaXNlRXZlbnQpXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLWJlZm9yZS1kb25lJyk7XG4gICAgfVxuXG4gICAgX3Rlc3RSdW5EaXNjb25uZWN0ZWQgKGNvbm5lY3Rpb24pIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0aW9uQ291bnQrKztcblxuICAgICAgICBjb25zdCBkaXNjb25uZWN0aW9uVGhyZXNob2xkRXhjZWVkZWVkID0gdGhpcy5kaXNjb25uZWN0aW9uQ291bnQgPj0gRElTQ09OTkVDVF9USFJFU0hPTEQ7XG5cbiAgICAgICAgcmV0dXJuIGNvbm5lY3Rpb25cbiAgICAgICAgICAgIC5wcm9jZXNzRGlzY29ubmVjdGlvbihkaXNjb25uZWN0aW9uVGhyZXNob2xkRXhjZWVkZWVkKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZXN0YXJ0VGVzdCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2Fzc2lnblRlc3RSdW5FdmVudHMgKHRlc3RSdW4sIGNvbm5lY3Rpb24pIHtcbiAgICAgICAgdGVzdFJ1bi5vbignYWN0aW9uLXN0YXJ0JywgYXN5bmMgYXJncyA9PiB0aGlzLl9lbWl0QWN0aW9uU3RhcnQoT2JqZWN0LmFzc2lnbihhcmdzLCB7IHRlc3RSdW4gfSkpKTtcbiAgICAgICAgdGVzdFJ1bi5vbignYWN0aW9uLWRvbmUnLCBhc3luYyBhcmdzID0+IHRoaXMuX2VtaXRBY3Rpb25Eb25lKE9iamVjdC5hc3NpZ24oYXJncywgeyB0ZXN0UnVuIH0pKSk7XG5cbiAgICAgICAgdGVzdFJ1bi5vbmNlKCdzdGFydCcsIGFzeW5jICgpID0+IHRoaXMuX2VtaXRUZXN0UnVuU3RhcnQoKSk7XG4gICAgICAgIHRlc3RSdW4ub25jZSgncmVhZHknLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMucXVhcmFudGluZSB8fCB0aGlzLl9pc0ZpcnN0UXVhcmFudGluZUF0dGVtcHQoKSlcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLXJlYWR5Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICB0ZXN0UnVuLm9uY2UoJ2JlZm9yZS1kb25lJywgKCkgPT4gdGhpcy5fdGVzdFJ1bkJlZm9yZURvbmUoKSk7XG4gICAgICAgIHRlc3RSdW4ub25jZSgnZG9uZScsICgpID0+IHRoaXMuX3Rlc3RSdW5Eb25lKCkpO1xuICAgICAgICB0ZXN0UnVuLm9uY2UoJ2Rpc2Nvbm5lY3RlZCcsICgpID0+IHRoaXMuX3Rlc3RSdW5EaXNjb25uZWN0ZWQoY29ubmVjdGlvbikpO1xuICAgIH1cblxuICAgIGdldCBibG9ja2VkICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZml4dHVyZUhvb2tDb250cm9sbGVyLmlzVGVzdEJsb2NrZWQodGhpcy50ZXN0KTtcbiAgICB9XG5cbiAgICBhc3luYyBzdGFydCAoY29ubmVjdGlvbikge1xuICAgICAgICBjb25zdCB0ZXN0UnVuID0gYXdhaXQgdGhpcy5fY3JlYXRlVGVzdFJ1bihjb25uZWN0aW9uKTtcblxuICAgICAgICBjb25zdCBob29rT2sgPSBhd2FpdCB0aGlzLmZpeHR1cmVIb29rQ29udHJvbGxlci5ydW5GaXh0dXJlQmVmb3JlSG9va0lmTmVjZXNzYXJ5KHRlc3RSdW4pO1xuXG4gICAgICAgIGlmICh0aGlzLnRlc3Quc2tpcCB8fCAhaG9va09rKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmVtaXQoJ3Rlc3QtcnVuLXN0YXJ0Jyk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9lbWl0VGVzdFJ1bkRvbmUoKTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fYXNzaWduVGVzdFJ1bkV2ZW50cyh0ZXN0UnVuLCBjb25uZWN0aW9uKTtcblxuICAgICAgICB0ZXN0UnVuLnN0YXJ0KCk7XG5cbiAgICAgICAgcmV0dXJuIFNlc3Npb25Db250cm9sbGVyLmdldFNlc3Npb25VcmwodGVzdFJ1biwgdGhpcy5wcm94eSk7XG4gICAgfVxufVxuIl19 |
\ | No newline at end of file |