testcafe
Version:
Automated browser testing for the modern web development stack.
151 lines • 23.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = __importDefault(require("debug"));
const path_1 = require("path");
const fs_1 = __importDefault(require("fs"));
const child_process_1 = require("child_process");
const make_dir_1 = __importDefault(require("make-dir"));
const temp_directory_1 = __importDefault(require("../utils/temp-directory"));
const path_pattern_1 = __importDefault(require("../utils/path-pattern"));
const warning_message_1 = __importDefault(require("../notifications/warning-message"));
const string_1 = require("../utils/string");
const test_run_video_recorder_1 = __importDefault(require("./test-run-video-recorder"));
const events_1 = require("events");
const create_safe_listener_1 = __importDefault(require("../utils/create-safe-listener"));
const DEBUG_LOGGER = (0, debug_1.default)('testcafe:video-recorder');
const VIDEO_EXTENSION = 'mp4';
const TEMP_DIR_PREFIX = 'video';
class VideoRecorder extends events_1.EventEmitter {
constructor(browserJob, basePath, opts, encodingOpts, warningLog) {
super();
this.browserJob = browserJob;
this.basePath = basePath;
this.failedOnly = opts.failedOnly;
this.singleFile = opts.singleFile;
this.ffmpegPath = opts.ffmpegPath;
this.customPathPattern = opts.pathPattern;
this.timeStamp = opts.timeStamp;
this.encodingOptions = encodingOpts;
this.warningLog = warningLog;
this.tempDirectory = new temp_directory_1.default(TEMP_DIR_PREFIX);
this.firstFile = true;
this.testRunVideoRecorders = {};
this._assignEventHandlers(browserJob);
}
_createSafeListener(listener) {
return (0, create_safe_listener_1.default)(this, listener, DEBUG_LOGGER);
}
_assignEventHandlers(browserJob) {
browserJob.once('start', this._createSafeListener(() => {
this.tempDirectoryInitializedPromise = this._onBrowserJobStart();
return this.tempDirectoryInitializedPromise;
}));
browserJob.once('done', this._createSafeListener(this._onBrowserJobDone));
browserJob.on('test-run-create', this._createSafeListener(this._onTestRunCreate));
browserJob.on('test-run-ready', this._createSafeListener(this._onTestRunReady));
browserJob.on('test-run-before-done', this._createSafeListener(this._onTestRunBeforeDone));
browserJob.on('test-run-restart', this._createSafeListener(this._onTestRunRestart));
}
_addProblematicPlaceholdersWarning(placeholders) {
const problematicPlaceholderListStr = (0, string_1.getConcatenatedValuesString)(placeholders);
const suffix = (0, string_1.getPluralSuffix)(placeholders);
const verb = (0, string_1.getToBeInPastTense)(placeholders);
this.warningLog.addWarning(warning_message_1.default.problematicPathPatternPlaceholderForVideoRecording, suffix, problematicPlaceholderListStr, suffix, verb);
}
_getTargetVideoPath(testRunRecorder) {
const data = Object.assign(testRunRecorder.testRunInfo, { now: this.timeStamp });
if (this.singleFile) {
data.testIndex = null;
data.fixture = null;
data.test = null;
}
const pathPattern = new path_pattern_1.default(this.customPathPattern, VIDEO_EXTENSION, data);
pathPattern.on('problematic-placeholders-found', ({ placeholders }) => this._addProblematicPlaceholdersWarning(placeholders));
return (0, path_1.join)(this.basePath, pathPattern.getPath());
}
_concatVideo(targetVideoPath, { tempVideoPath, tempMergeConfigPath, tmpMergeName }) {
if (this.firstFile) {
this.firstFile = false;
return;
}
fs_1.default.writeFileSync(tempMergeConfigPath, `
file '${targetVideoPath}'
file '${tempVideoPath}'
`);
(0, child_process_1.spawnSync)(this.ffmpegPath, ['-y', '-f', 'concat', '-safe', '0', '-i', tempMergeConfigPath, '-c', 'copy', tmpMergeName], { stdio: 'ignore' });
fs_1.default.copyFileSync(tmpMergeName, tempVideoPath);
}
async _onBrowserJobStart() {
await this.tempDirectory.init();
}
async _onBrowserJobDone() {
await this.tempDirectory.dispose();
}
async _onTestRunCreate(testRunInfo) {
if (testRunInfo.legacy)
return;
await this.tempDirectoryInitializedPromise;
const recordingOptions = {
path: this.tempDirectory.path,
ffmpegPath: this.ffmpegPath,
encodingOptions: this.encodingOptions,
};
const testRunVideoRecorder = this._createTestRunVideoRecorder(testRunInfo, recordingOptions);
const isVideoSupported = await testRunVideoRecorder.isVideoSupported();
if (!isVideoSupported) {
this.warningLog.addWarning(warning_message_1.default.videoNotSupportedByBrowser, testRunVideoRecorder.testRunInfo.alias);
return;
}
const isVideoEnabled = await testRunVideoRecorder.isVideoEnabled();
if (!isVideoEnabled)
return;
await testRunVideoRecorder.init();
this.testRunVideoRecorders[testRunVideoRecorder.index] = testRunVideoRecorder;
}
_createTestRunVideoRecorder(testRunInfo, recordingOptions) {
return new test_run_video_recorder_1.default(testRunInfo, recordingOptions, this.warningLog);
}
async _onTestRunReady({ index }) {
const testRunRecorder = this.testRunVideoRecorders[index];
if (!testRunRecorder)
return;
await testRunRecorder.startCapturing();
}
async _onTestRunRestart({ index }) {
const testRunRecorder = this.testRunVideoRecorders[index];
if (!testRunRecorder)
return;
testRunRecorder.onTestRunRestart();
}
async _onTestRunBeforeDone({ index }) {
const testRunRecorder = this.testRunVideoRecorders[index];
if (!testRunRecorder)
return;
delete this.testRunVideoRecorders[index];
await testRunRecorder.finishCapturing();
if (this.failedOnly && !testRunRecorder.hasErrors)
return;
const videoPath = this._getTargetVideoPath(testRunRecorder);
await this._saveFiles(testRunRecorder, videoPath);
const testRunVideoSavedEventArgs = {
testRun: testRunRecorder.testRun,
videoPath,
singleFile: !!this.singleFile,
};
if (!this.singleFile)
testRunVideoSavedEventArgs.timecodes = testRunRecorder.testRunInfo.timecodes;
this.emit('test-run-video-saved', testRunVideoSavedEventArgs);
}
async _saveFiles(testRunRecorder, videoPath) {
await (0, make_dir_1.default)((0, path_1.dirname)(videoPath));
if (this.singleFile)
this._concatVideo(videoPath, testRunRecorder.tempFiles);
fs_1.default.copyFileSync(testRunRecorder.tempFiles.tempVideoPath, videoPath);
}
}
exports.default = VideoRecorder;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmlkZW8tcmVjb3JkZXIvcmVjb3JkZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxrREFBMEI7QUFDMUIsK0JBQXFDO0FBQ3JDLDRDQUFvQjtBQUNwQixpREFBMEM7QUFDMUMsd0RBQStCO0FBQy9CLDZFQUFvRDtBQUNwRCx5RUFBZ0Q7QUFDaEQsdUZBQWdFO0FBQ2hFLDRDQUl5QjtBQUV6Qix3RkFBNkQ7QUFDN0QsbUNBQXNDO0FBQ3RDLHlGQUErRDtBQUUvRCxNQUFNLFlBQVksR0FBRyxJQUFBLGVBQUssRUFBQyx5QkFBeUIsQ0FBQyxDQUFDO0FBRXRELE1BQU0sZUFBZSxHQUFHLEtBQUssQ0FBQztBQUM5QixNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUM7QUFFaEMsTUFBcUIsYUFBYyxTQUFRLHFCQUFZO0lBQ25ELFlBQWEsVUFBVSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFVBQVU7UUFDN0QsS0FBSyxFQUFFLENBQUM7UUFFUixJQUFJLENBQUMsVUFBVSxHQUFVLFVBQVUsQ0FBQztRQUNwQyxJQUFJLENBQUMsUUFBUSxHQUFZLFFBQVEsQ0FBQztRQUNsQyxJQUFJLENBQUMsVUFBVSxHQUFVLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDekMsSUFBSSxDQUFDLFVBQVUsR0FBVSxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxVQUFVLEdBQVUsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUN6QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUMxQyxJQUFJLENBQUMsU0FBUyxHQUFXLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDeEMsSUFBSSxDQUFDLGVBQWUsR0FBSyxZQUFZLENBQUM7UUFFdEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFFN0IsSUFBSSxDQUFDLGFBQWEs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QUFTLENBQUMsQ0FBQztJQUN4RSxDQUFDO0NBQ0o7QUFsTEQsZ0NBa0xDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCB7IGpvaW4sIGRpcm5hbWUgfSBmcm9tICdwYXRoJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCBtYWtlRGlyIGZyb20gJ21ha2UtZGlyJztcbmltcG9ydCBUZW1wRGlyZWN0b3J5IGZyb20gJy4uL3V0aWxzL3RlbXAtZGlyZWN0b3J5JztcbmltcG9ydCBQYXRoUGF0dGVybiBmcm9tICcuLi91dGlscy9wYXRoLXBhdHRlcm4nO1xuaW1wb3J0IFdBUk5JTkdfTUVTU0FHRVMgZnJvbSAnLi4vbm90aWZpY2F0aW9ucy93YXJuaW5nLW1lc3NhZ2UnO1xuaW1wb3J0IHtcbiAgICBnZXRQbHVyYWxTdWZmaXgsXG4gICAgZ2V0Q29uY2F0ZW5hdGVkVmFsdWVzU3RyaW5nLFxuICAgIGdldFRvQmVJblBhc3RUZW5zZSxcbn0gZnJvbSAnLi4vdXRpbHMvc3RyaW5nJztcblxuaW1wb3J0IFRlc3RSdW5WaWRlb1JlY29yZGVyIGZyb20gJy4vdGVzdC1ydW4tdmlkZW8tcmVjb3JkZXInO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCBjcmVhdGVTYWZlTGlzdGVuZXIgZnJvbSAnLi4vdXRpbHMvY3JlYXRlLXNhZmUtbGlzdGVuZXInO1xuXG5jb25zdCBERUJVR19MT0dHRVIgPSBkZWJ1ZygndGVzdGNhZmU6dmlkZW8tcmVjb3JkZXInKTtcblxuY29uc3QgVklERU9fRVhURU5TSU9OID0gJ21wNCc7XG5jb25zdCBURU1QX0RJUl9QUkVGSVggPSAndmlkZW8nO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWaWRlb1JlY29yZGVyIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgICBjb25zdHJ1Y3RvciAoYnJvd3NlckpvYiwgYmFzZVBhdGgsIG9wdHMsIGVuY29kaW5nT3B0cywgd2FybmluZ0xvZykge1xuICAgICAgICBzdXBlcigpO1xuXG4gICAgICAgIHRoaXMuYnJvd3NlckpvYiAgICAgICAgPSBicm93c2VySm9iO1xuICAgICAgICB0aGlzLmJhc2VQYXRoICAgICAgICAgID0gYmFzZVBhdGg7XG4gICAgICAgIHRoaXMuZmFpbGVkT25seSAgICAgICAgPSBvcHRzLmZhaWxlZE9ubHk7XG4gICAgICAgIHRoaXMuc2luZ2xlRmlsZSAgICAgICAgPSBvcHRzLnNpbmdsZUZpbGU7XG4gICAgICAgIHRoaXMuZmZtcGVnUGF0aCAgICAgICAgPSBvcHRzLmZmbXBlZ1BhdGg7XG4gICAgICAgIHRoaXMuY3VzdG9tUGF0aFBhdHRlcm4gPSBvcHRzLnBhdGhQYXR0ZXJuO1xuICAgICAgICB0aGlzLnRpbWVTdGFtcCAgICAgICAgID0gb3B0cy50aW1lU3RhbXA7XG4gICAgICAgIHRoaXMuZW5jb2RpbmdPcHRpb25zICAgPSBlbmNvZGluZ09wdHM7XG5cbiAgICAgICAgdGhpcy53YXJuaW5nTG9nID0gd2FybmluZ0xvZztcblxuICAgICAgICB0aGlzLnRlbXBEaXJlY3RvcnkgPSBuZXcgVGVtcERpcmVjdG9yeShURU1QX0RJUl9QUkVGSVgpO1xuXG4gICAgICAgIHRoaXMuZmlyc3RGaWxlID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLnRlc3RSdW5WaWRlb1JlY29yZGVycyA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2Fzc2lnbkV2ZW50SGFuZGxlcnMoYnJvd3NlckpvYik7XG4gICAgfVxuXG4gICAgX2NyZWF0ZVNhZmVMaXN0ZW5lciAobGlzdGVuZXIpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVNhZmVMaXN0ZW5lcih0aGlzLCBsaXN0ZW5lciwgREVCVUdfTE9HR0VSKTtcbiAgICB9XG5cbiAgICBfYXNzaWduRXZlbnRIYW5kbGVycyAoYnJvd3NlckpvYikge1xuICAgICAgICBicm93c2VySm9iLm9uY2UoJ3N0YXJ0JywgdGhpcy5fY3JlYXRlU2FmZUxpc3RlbmVyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMudGVtcERpcmVjdG9yeUluaXRpYWxpemVkUHJvbWlzZSA9IHRoaXMuX29uQnJvd3NlckpvYlN0YXJ0KCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRlbXBEaXJlY3RvcnlJbml0aWFsaXplZFByb21pc2U7XG4gICAgICAgIH0pKTtcblxuICAgICAgICBicm93c2VySm9iLm9uY2UoJ2RvbmUnLCB0aGlzLl9jcmVhdGVTYWZlTGlzdGVuZXIodGhpcy5fb25Ccm93c2VySm9iRG9uZSkpO1xuICAgICAgICBicm93c2VySm9iLm9uKCd0ZXN0LXJ1bi1jcmVhdGUnLCB0aGlzLl9jcmVhdGVTYWZlTGlzdGVuZXIodGhpcy5fb25UZXN0UnVuQ3JlYXRlKSk7XG4gICAgICAgIGJyb3dzZXJKb2Iub24oJ3Rlc3QtcnVuLXJlYWR5JywgdGhpcy5fY3JlYXRlU2FmZUxpc3RlbmVyKHRoaXMuX29uVGVzdFJ1blJlYWR5KSk7XG4gICAgICAgIGJyb3dzZXJKb2Iub24oJ3Rlc3QtcnVuLWJlZm9yZS1kb25lJywgdGhpcy5fY3JlYXRlU2FmZUxpc3RlbmVyKHRoaXMuX29uVGVzdFJ1bkJlZm9yZURvbmUpKTtcbiAgICAgICAgYnJvd3NlckpvYi5vbigndGVzdC1ydW4tcmVzdGFydCcsIHRoaXMuX2NyZWF0ZVNhZmVMaXN0ZW5lcih0aGlzLl9vblRlc3RSdW5SZXN0YXJ0KSk7XG4gICAgfVxuXG4gICAgX2FkZFByb2JsZW1hdGljUGxhY2Vob2xkZXJzV2FybmluZyAocGxhY2Vob2xkZXJzKSB7XG4gICAgICAgIGNvbnN0IHByb2JsZW1hdGljUGxhY2Vob2xkZXJMaXN0U3RyID0gZ2V0Q29uY2F0ZW5hdGVkVmFsdWVzU3RyaW5nKHBsYWNlaG9sZGVycyk7XG4gICAgICAgIGNvbnN0IHN1ZmZpeCAgICAgICAgICAgICAgICAgICAgICAgID0gZ2V0UGx1cmFsU3VmZml4KHBsYWNlaG9sZGVycyk7XG4gICAgICAgIGNvbnN0IHZlcmIgICAgICAgICAgICAgICAgICAgICAgICAgID0gZ2V0VG9CZUluUGFzdFRlbnNlKHBsYWNlaG9sZGVycyk7XG5cbiAgICAgICAgdGhpcy53YXJuaW5nTG9nLmFkZFdhcm5pbmcoV0FSTklOR19NRVNTQUdFUy5wcm9ibGVtYXRpY1BhdGhQYXR0ZXJuUGxhY2Vob2xkZXJGb3JWaWRlb1JlY29yZGluZywgc3VmZml4LCBwcm9ibGVtYXRpY1BsYWNlaG9sZGVyTGlzdFN0ciwgc3VmZml4LCB2ZXJiKTtcbiAgICB9XG5cbiAgICBfZ2V0VGFyZ2V0VmlkZW9QYXRoICh0ZXN0UnVuUmVjb3JkZXIpIHtcbiAgICAgICAgY29uc3QgZGF0YSA9IE9iamVjdC5hc3NpZ24odGVzdFJ1blJlY29yZGVyLnRlc3RSdW5JbmZvLCB7IG5vdzogdGhpcy50aW1lU3RhbXAgfSk7XG5cbiAgICAgICAgaWYgKHRoaXMuc2luZ2xlRmlsZSkge1xuICAgICAgICAgICAgZGF0YS50ZXN0SW5kZXggPSBudWxsO1xuICAgICAgICAgICAgZGF0YS5maXh0dXJlID0gbnVsbDtcbiAgICAgICAgICAgIGRhdGEudGVzdCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwYXRoUGF0dGVybiA9IG5ldyBQYXRoUGF0dGVybih0aGlzLmN1c3RvbVBhdGhQYXR0ZXJuLCBWSURFT19FWFRFTlNJT04sIGRhdGEpO1xuXG4gICAgICAgIHBhdGhQYXR0ZXJuLm9uKCdwcm9ibGVtYXRpYy1wbGFjZWhvbGRlcnMtZm91bmQnLCAoeyBwbGFjZWhvbGRlcnMgfSkgPT4gdGhpcy5fYWRkUHJvYmxlbWF0aWNQbGFjZWhvbGRlcnNXYXJuaW5nKHBsYWNlaG9sZGVycykpO1xuXG4gICAgICAgIHJldHVybiBqb2luKHRoaXMuYmFzZVBhdGgsIHBhdGhQYXR0ZXJuLmdldFBhdGgoKSk7XG4gICAgfVxuXG4gICAgX2NvbmNhdFZpZGVvICh0YXJnZXRWaWRlb1BhdGgsIHsgdGVtcFZpZGVvUGF0aCwgdGVtcE1lcmdlQ29uZmlnUGF0aCwgdG1wTWVyZ2VOYW1lIH0pIHtcbiAgICAgICAgaWYgKHRoaXMuZmlyc3RGaWxlKSB7XG4gICAgICAgICAgICB0aGlzLmZpcnN0RmlsZSA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyh0ZW1wTWVyZ2VDb25maWdQYXRoLCBgXG4gICAgICAgICAgICBmaWxlICcke3RhcmdldFZpZGVvUGF0aH0nXG4gICAgICAgICAgICBmaWxlICcke3RlbXBWaWRlb1BhdGh9J1xuICAgICAgICBgKTtcblxuICAgICAgICBzcGF3blN5bmModGhpcy5mZm1wZWdQYXRoLCBbJy15JywgJy1mJywgJ2NvbmNhdCcsICctc2FmZScsICcwJywgJy1pJywgdGVtcE1lcmdlQ29uZmlnUGF0aCwgJy1jJywgJ2NvcHknLCB0bXBNZXJnZU5hbWVdLCB7IHN0ZGlvOiAnaWdub3JlJyB9KTtcbiAgICAgICAgZnMuY29weUZpbGVTeW5jKHRtcE1lcmdlTmFtZSwgdGVtcFZpZGVvUGF0aCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX29uQnJvd3NlckpvYlN0YXJ0ICgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy50ZW1wRGlyZWN0b3J5LmluaXQoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfb25Ccm93c2VySm9iRG9uZSAoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMudGVtcERpcmVjdG9yeS5kaXNwb3NlKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX29uVGVzdFJ1bkNyZWF0ZSAodGVzdFJ1bkluZm8pIHtcbiAgICAgICAgaWYgKHRlc3RSdW5JbmZvLmxlZ2FjeSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBhd2FpdCB0aGlzLnRlbXBEaXJlY3RvcnlJbml0aWFsaXplZFByb21pc2U7XG5cbiAgICAgICAgY29uc3QgcmVjb3JkaW5nT3B0aW9ucyA9IHtcbiAgICAgICAgICAgIHBhdGg6ICAgICAgICAgICAgdGhpcy50ZW1wRGlyZWN0b3J5LnBhdGgsXG4gICAgICAgICAgICBmZm1wZWdQYXRoOiAgICAgIHRoaXMuZmZtcGVnUGF0aCxcbiAgICAgICAgICAgIGVuY29kaW5nT3B0aW9uczogdGhpcy5lbmNvZGluZ09wdGlvbnMsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgdGVzdFJ1blZpZGVvUmVjb3JkZXIgPSB0aGlzLl9jcmVhdGVUZXN0UnVuVmlkZW9SZWNvcmRlcih0ZXN0UnVuSW5mbywgcmVjb3JkaW5nT3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGlzVmlkZW9TdXBwb3J0ZWQgICAgID0gYXdhaXQgdGVzdFJ1blZpZGVvUmVjb3JkZXIuaXNWaWRlb1N1cHBvcnRlZCgpO1xuXG4gICAgICAgIGlmICghaXNWaWRlb1N1cHBvcnRlZCkge1xuICAgICAgICAgICAgdGhpcy53YXJuaW5nTG9nLmFkZFdhcm5pbmcoV0FSTklOR19NRVNTQUdFUy52aWRlb05vdFN1cHBvcnRlZEJ5QnJvd3NlciwgdGVzdFJ1blZpZGVvUmVjb3JkZXIudGVzdFJ1bkluZm8uYWxpYXMpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNWaWRlb0VuYWJsZWQgPSBhd2FpdCB0ZXN0UnVuVmlkZW9SZWNvcmRlci5pc1ZpZGVvRW5hYmxlZCgpO1xuXG4gICAgICAgIGlmICghaXNWaWRlb0VuYWJsZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXdhaXQgdGVzdFJ1blZpZGVvUmVjb3JkZXIuaW5pdCgpO1xuXG4gICAgICAgIHRoaXMudGVzdFJ1blZpZGVvUmVjb3JkZXJzW3Rlc3RSdW5WaWRlb1JlY29yZGVyLmluZGV4XSA9IHRlc3RSdW5WaWRlb1JlY29yZGVyO1xuICAgIH1cblxuICAgIF9jcmVhdGVUZXN0UnVuVmlkZW9SZWNvcmRlciAodGVzdFJ1bkluZm8sIHJlY29yZGluZ09wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUZXN0UnVuVmlkZW9SZWNvcmRlcih0ZXN0UnVuSW5mbywgcmVjb3JkaW5nT3B0aW9ucywgdGhpcy53YXJuaW5nTG9nKTtcbiAgICB9XG5cbiAgICBhc3luYyBfb25UZXN0UnVuUmVhZHkgKHsgaW5kZXggfSkge1xuICAgICAgICBjb25zdCB0ZXN0UnVuUmVjb3JkZXIgPSB0aGlzLnRlc3RSdW5WaWRlb1JlY29yZGVyc1tpbmRleF07XG5cbiAgICAgICAgaWYgKCF0ZXN0UnVuUmVjb3JkZXIpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgYXdhaXQgdGVzdFJ1blJlY29yZGVyLnN0YXJ0Q2FwdHVyaW5nKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX29uVGVzdFJ1blJlc3RhcnQgKHsgaW5kZXggfSkge1xuICAgICAgICBjb25zdCB0ZXN0UnVuUmVjb3JkZXIgPSB0aGlzLnRlc3RSdW5WaWRlb1JlY29yZGVyc1tpbmRleF07XG5cbiAgICAgICAgaWYgKCF0ZXN0UnVuUmVjb3JkZXIpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdGVzdFJ1blJlY29yZGVyLm9uVGVzdFJ1blJlc3RhcnQoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfb25UZXN0UnVuQmVmb3JlRG9uZSAoeyBpbmRleCB9KSB7XG4gICAgICAgIGNvbnN0IHRlc3RSdW5SZWNvcmRlciA9IHRoaXMudGVzdFJ1blZpZGVvUmVjb3JkZXJzW2luZGV4XTtcblxuICAgICAgICBpZiAoIXRlc3RSdW5SZWNvcmRlcilcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBkZWxldGUgdGhpcy50ZXN0UnVuVmlkZW9SZWNvcmRlcnNbaW5kZXhdO1xuXG4gICAgICAgIGF3YWl0IHRlc3RSdW5SZWNvcmRlci5maW5pc2hDYXB0dXJpbmcoKTtcblxuICAgICAgICBpZiAodGhpcy5mYWlsZWRPbmx5ICYmICF0ZXN0UnVuUmVjb3JkZXIuaGFzRXJyb3JzKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHZpZGVvUGF0aCA9IHRoaXMuX2dldFRhcmdldFZpZGVvUGF0aCh0ZXN0UnVuUmVjb3JkZXIpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX3NhdmVGaWxlcyh0ZXN0UnVuUmVjb3JkZXIsIHZpZGVvUGF0aCk7XG5cbiAgICAgICAgY29uc3QgdGVzdFJ1blZpZGVvU2F2ZWRFdmVudEFyZ3MgPSB7XG4gICAgICAgICAgICB0ZXN0UnVuOiAgICB0ZXN0UnVuUmVjb3JkZXIudGVzdFJ1bixcbiAgICAgICAgICAgIHZpZGVvUGF0aCxcbiAgICAgICAgICAgIHNpbmdsZUZpbGU6ICEhdGhpcy5zaW5nbGVGaWxlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICghdGhpcy5zaW5nbGVGaWxlKVxuICAgICAgICAgICAgdGVzdFJ1blZpZGVvU2F2ZWRFdmVudEFyZ3MudGltZWNvZGVzID0gdGVzdFJ1blJlY29yZGVyLnRlc3RSdW5JbmZvLnRpbWVjb2RlcztcblxuICAgICAgICB0aGlzLmVtaXQoJ3Rlc3QtcnVuLXZpZGVvLXNhdmVkJywgdGVzdFJ1blZpZGVvU2F2ZWRFdmVudEFyZ3MpO1xuICAgIH1cblxuICAgIGFzeW5jIF9zYXZlRmlsZXMgKHRlc3RSdW5SZWNvcmRlciwgdmlkZW9QYXRoKSB7XG4gICAgICAgIGF3YWl0IG1ha2VEaXIoZGlybmFtZSh2aWRlb1BhdGgpKTtcblxuICAgICAgICBpZiAodGhpcy5zaW5nbGVGaWxlKVxuICAgICAgICAgICAgdGhpcy5fY29uY2F0VmlkZW8odmlkZW9QYXRoLCB0ZXN0UnVuUmVjb3JkZXIudGVtcEZpbGVzKTtcblxuICAgICAgICBmcy5jb3B5RmlsZVN5bmModGVzdFJ1blJlY29yZGVyLnRlbXBGaWxlcy50ZW1wVmlkZW9QYXRoLCB2aWRlb1BhdGgpO1xuICAgIH1cbn1cbiJdfQ==