filestack-js
Version:
Official JavaScript library for Filestack
1,201 lines • 154 kB
JavaScript
"use strict";
/*
* Copyright (c) 2019 by Filestack.
* Some rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var s3_1 = require("./s3");
var file_1 = require("./../file");
var nock_1 = tslib_1.__importDefault(require("nock"));
var abstract_1 = require("./abstract");
var utils = tslib_1.__importStar(require("../../../utils/index.node"));
var testBufferSize = 1024 * 1024 * 9;
var testSmallBufferSize = 1024 * 1024 * 2;
var testBuff = Buffer.alloc(testBufferSize).fill('t', 0, testBufferSize);
var smallTestBuff = Buffer.alloc(testSmallBufferSize).fill('t', 0, testSmallBufferSize);
var scope;
var interceptorS3;
var interceptorStart;
var interceptorCommit;
var interceptorUpload;
var interceptorComplete;
var getTestFile = function () {
return new file_1.File({
slice: function (start, end) { return Promise.resolve(testBuff.slice(start, end)); },
type: 'text/plain',
// @ts-ignore
size: testBuff.length,
name: 'test.txt',
});
};
var getSmallTestFile = function () {
return new file_1.File({
slice: function (start, end) { return Promise.resolve(testBuff.slice(start, end)); },
type: 'text/plain',
// @ts-ignore
size: smallTestBuff.length,
name: 'test.txt',
});
};
var getNullSizeFile = function () {
return new file_1.File({
slice: function (start, end) { return Promise.resolve(testBuff.slice(start, end)); },
type: 'text/plain',
// @ts-ignore
size: 0,
name: 'test.txt',
});
};
var testApikey = 'testapikey';
var testHost = 'https://filestack-test.com';
var mockUploadId = '123132123';
var mockRegion = 'test-region';
var mockedUri = '/sometest';
var s3Url = testHost + '/fakes3';
var mockStart = jest.fn().mockName('multipart/start');
var mockUpload = jest.fn().mockName('multipart/upload');
var mockPut = jest.fn().mockName('s3/put');
var mockCommit = jest.fn().mockName('multipart/commit');
var mockComplete = jest.fn().mockName('multipart/complete');
var s3Callback = function (url) {
return mockPut(url, this.req.headers);
};
describe('Api/Upload/Uploaders/S3', function () {
beforeEach(function () {
scope = (0, nock_1.default)(testHost);
// scope.defaultReplyHeaders({ 'access-control-allow-origin': '*', 'content-type': 'application/json' });
scope.persist();
interceptorStart = scope.post('/multipart/start');
interceptorUpload = scope.post('/multipart/upload');
interceptorCommit = scope.post('/multipart/commit');
interceptorComplete = scope.post('/multipart/complete');
interceptorS3 = scope.put('/fakes3');
interceptorStart.reply(200, function (_, data) { return mockStart(data); });
interceptorUpload.twice().reply(200, function (_, data) { return mockUpload(data); });
interceptorCommit.reply(200, function (_, data) { return mockCommit(data); });
interceptorComplete.reply(200, function (_, data) { return mockComplete(data); });
interceptorS3.twice().reply(201, s3Callback, { etag: 'test' });
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost,
});
mockUpload.mockReturnValue({
url: s3Url,
headers: {
test: 'test',
},
location_url: testHost,
});
mockPut.mockReturnValue({});
mockCommit.mockReturnValue({});
mockComplete.mockReturnValue({
handle: 'test_handle',
url: 'test_url',
filename: 'test_filename',
size: 123,
mimetype: 'test_mimetype',
status: 'test_status',
upload_tags: { test: 123 },
});
});
afterEach(function () {
nock_1.default.cleanAll();
nock_1.default.enableNetConnect();
jest.clearAllMocks();
});
describe('Standart tests', function () {
it('should initialize class without errors', function () {
expect(function () {
var u = new s3_1.S3Uploader({});
var uu = new s3_1.S3Uploader({}, 10);
}).not.toThrowError();
});
it('should allow adding files', function () {
var u = new s3_1.S3Uploader({});
u.addFile(getTestFile());
});
it('should not allow to set min part size lower than defined', function () {
var u = new s3_1.S3Uploader({});
expect(function () { return u.setPartSize(10); }).toThrowError();
});
it('should throw an error when setting to small intelligent chunk size', function () {
var u = new s3_1.S3Uploader({});
expect(function () { return u.setIntelligentChunkSize(10); }).toThrowError();
});
it('should throw an error when trying to get host when it is undefined', function () {
var u = new s3_1.S3Uploader({});
expect(function () { return u.getUrl(); }).toThrowError();
});
it('should set intelligent mobile chunk size on mobile devices', function () {
jest.spyOn(utils, 'isMobile').mockReturnValue(true);
var u = new s3_1.S3Uploader({});
return expect(u.getIntelligentChunkSize()).toEqual(abstract_1.INTELLIGENT_MOBILE_CHUNK_SIZE);
});
it('should allow to set part size on other mode thant regular', function () {
var u = new s3_1.S3Uploader({});
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
var partSize = 1024 * 1024;
u.setPartSize(partSize);
expect(u.getPartSize()).toEqual(abstract_1.DEFAULT_PART_SIZE);
});
it('should retry complete request on 202 status code', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var mock202, u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mock202 = jest
.fn()
.mockName('202 mock')
.mockReturnValue('');
nock_1.default.removeInterceptor(interceptorComplete);
scope.persist(false);
scope.post('/multipart/complete').reply(202, function () { return mock202(); });
scope.post('/multipart/complete').reply(200, function (_, data) { return mockComplete(data); });
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
expect(mock202).toHaveBeenCalledTimes(1);
expect(mockComplete).toHaveBeenCalledTimes(1);
return [2 /*return*/];
}
});
}); });
it('should respect provided store options', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var storeOption, u;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
storeOption = {
container: 'test',
location: abstract_1.DEFAULT_STORE_LOCATION,
workflows: [{
id: 'test',
}],
};
u = new s3_1.S3Uploader(storeOption);
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
_a.sent();
expect(mockStart).toHaveBeenCalledWith(expect.objectContaining({ store: storeOption }));
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining({ store: storeOption }));
return [2 /*return*/];
}
});
}); });
it('should add https protocol to location_url', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost.replace('https://', ''),
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
expect(mockPut).toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should throw error on file size 0', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost.replace('https://', ''),
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getNullSizeFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockStart).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should throw error on wrong etag field', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost.replace('https://', ''),
});
interceptorS3.once().reply(200, s3Callback, {});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
u.on('error', function (err) {
expect(err.message).toEqual('Cannot upload file, check S3 bucket settings');
});
return [4 /*yield*/, u.execute()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
it('should add Filestack-Upload-Region header on location_region param', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res, testFile, firstPartMetadata, firstPartChunk;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_region: 'test',
location_url: testHost.replace('https://', ''),
});
interceptorUpload.reply(200, function (_, data) {
return mockUpload(data, this.req.headers);
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
testFile = getSmallTestFile();
firstPartMetadata = testFile.getPartMetadata(0, abstract_1.DEFAULT_PART_SIZE);
return [4 /*yield*/, testFile.getPartByMetadata(firstPartMetadata)];
case 2:
firstPartChunk = _a.sent();
expect(mockUpload).toHaveBeenCalledWith({
md5: firstPartChunk.md5,
size: testFile.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 1,
}, expect.objectContaining({ 'filestack-upload-region': 'test' }));
expect(mockPut).toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should respect pause() and resume() command', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getTestFile());
setImmediate(function () { return u.pause(); });
setTimeout(function () { return u.resume(); }, 10);
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
return [2 /*return*/];
}
});
}); });
it('should respect abort() command', function (done) {
var u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getTestFile());
setImmediate(function () { return u.abort(); });
u.execute().then(function (res) {
expect(res[0].status).toEqual('Failed');
done();
}).catch(function () {
done('Execution failed');
});
});
it('should send correct security', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var testSecurity, u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
testSecurity = {
policy: 'test_p',
signature: 'test_s',
};
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setSecurity(testSecurity);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
expect(mockStart).toHaveBeenCalledWith(expect.objectContaining(testSecurity));
expect(mockUpload).toHaveBeenCalledWith(expect.objectContaining(testSecurity));
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining(testSecurity));
return [2 /*return*/];
}
});
}); });
it('should respect disableStorageKey option', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new s3_1.S3Uploader({
disableStorageKey: true,
path: '/test/',
});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
storageKeyExpect = {
store: {
location: 's3',
path: '/test/test.txt',
},
};
expect(mockStart).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockUpload).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
return [2 /*return*/];
}
});
}); });
it('should respect disableStorageKey option when path is missing', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new s3_1.S3Uploader({
disableStorageKey: true,
});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
storageKeyExpect = {
store: {
location: 's3',
path: '/test.txt',
},
};
expect(mockStart).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockUpload).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
return [2 /*return*/];
}
});
}); });
it('should respect disableStorageKey option when path has missing /', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new s3_1.S3Uploader({
disableStorageKey: true,
path: '/test',
});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
storageKeyExpect = {
store: {
location: 's3',
path: '/test/test.txt',
},
};
expect(mockStart).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockUpload).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining(storageKeyExpect));
return [2 /*return*/];
}
});
}); });
});
describe('Tags', function () {
it('Make correct request with upload tags', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, tags, res, tagsExpected;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new s3_1.S3Uploader({
disableStorageKey: true,
path: '/test',
});
tags = {
test: '123',
test2: 'test',
};
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
u.setUploadTags(tags);
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
tagsExpected = {
upload_tags: tags,
};
expect(res[0].uploadTags).toEqual({ test: 123 });
expect(mockComplete).toHaveBeenCalledWith(expect.objectContaining(tagsExpected));
return [2 /*return*/];
}
});
}); });
});
describe('Upload modes', function () {
describe('Intelligent ingession', function () {
beforeEach(function () {
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost,
upload_type: 'intelligent_ingestion',
});
});
it('should upload file', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var chunkSize, u, res, testFile, firstPartOffset, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
chunkSize = 1024 * 1024;
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.setIntelligentChunkSize(chunkSize);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _b.sent();
expect(res[0].handle).toEqual('test_handle');
testFile = getSmallTestFile();
expect(mockStart).toHaveBeenCalledWith({
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
fii: true,
});
firstPartOffset = 0;
_a = testFile.getPartsCount(abstract_1.INTELLIGENT_CHUNK_SIZE, true), partsCount = _a.partsCount, dynamicPartSize = _a.chunkSize;
firstPartMetadata = testFile.getPartMetadata(0, dynamicPartSize);
return [4 /*yield*/, testFile.getChunkByMetadata(firstPartMetadata, firstPartOffset, dynamicPartSize)];
case 2:
firstPartChunk = _b.sent();
expect(mockUpload).toHaveBeenCalledWith({
md5: firstPartChunk.md5,
size: firstPartChunk.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
offset: firstPartOffset,
fii: true,
part: 1,
});
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockCommit).toHaveBeenCalledWith({
apikey: testApikey,
part: 1,
size: testFile.size,
region: mockRegion,
uri: mockedUri,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
});
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
region: mockRegion,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
fii: true,
uri: mockedUri,
});
return [2 /*return*/];
}
});
}); });
it('should upload file', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var chunkSize, u, res, testFile, firstPartOffset, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
chunkSize = 1024 * 1024;
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.setIntelligentChunkSize(chunkSize);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _b.sent();
expect(res[0].handle).toEqual('test_handle');
testFile = getSmallTestFile();
expect(mockStart).toHaveBeenCalledWith({
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
fii: true,
});
firstPartOffset = 0;
_a = testFile.getPartsCount(abstract_1.INTELLIGENT_CHUNK_SIZE, true), partsCount = _a.partsCount, dynamicPartSize = _a.chunkSize;
firstPartMetadata = testFile.getPartMetadata(0, dynamicPartSize);
return [4 /*yield*/, testFile.getChunkByMetadata(firstPartMetadata, firstPartOffset, dynamicPartSize)];
case 2:
firstPartChunk = _b.sent();
expect(mockUpload).toHaveBeenCalledWith({
md5: firstPartChunk.md5,
size: firstPartChunk.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
offset: firstPartOffset,
fii: true,
part: 1,
});
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockCommit).toHaveBeenCalledWith({
apikey: testApikey,
part: 1,
size: testFile.size,
region: mockRegion,
uri: mockedUri,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
});
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
region: mockRegion,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
fii: true,
uri: mockedUri,
});
return [2 /*return*/];
}
});
}); });
it('should lower chunk size on network error', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var putRequestTimeout, delayApplied, u, res, testFile, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk, chunkSize, updatedFirstPartMetaData, chunk1;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
putRequestTimeout = 300;
delayApplied = false;
nock_1.default.removeInterceptor(interceptorS3);
scope.put('/fakes3').reply(function (url, _, cb) {
if (!delayApplied) {
delayApplied = true;
setTimeout(function () {
cb(504);
}, 3000);
}
else {
cb(null, [201, mockPut(url, this.req.headers), { etag: 'test' }]);
}
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setTimeout(putRequestTimeout);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.setIntelligentChunkSize(abstract_1.INTELLIGENT_CHUNK_SIZE);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _b.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
testFile = getSmallTestFile();
_a = testFile.getPartsCount(abstract_1.INTELLIGENT_CHUNK_SIZE, true), partsCount = _a.partsCount, dynamicPartSize = _a.chunkSize;
firstPartMetadata = testFile.getPartMetadata(0, dynamicPartSize);
return [4 /*yield*/, testFile.getChunkByMetadata(firstPartMetadata, 0, dynamicPartSize)];
case 2:
firstPartChunk = _b.sent();
// this request will be aborted but called on mock upload
expect(mockUpload).toHaveBeenNthCalledWith(1, {
md5: firstPartChunk.md5,
size: firstPartChunk.size,
apikey: testApikey,
region: mockRegion,
fii: true,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
offset: 0,
part: 1,
});
chunkSize = testFile.getPartsCount(abstract_1.INTELLIGENT_CHUNK_SIZE, true).chunkSize;
chunkSize = chunkSize / 2;
updatedFirstPartMetaData = testFile.getPartMetadata(0, chunkSize);
return [4 /*yield*/, testFile.getChunkByMetadata(updatedFirstPartMetaData, 0, chunkSize)];
case 3:
chunk1 = _b.sent();
expect(mockUpload).toHaveBeenNthCalledWith(2, {
md5: chunk1.md5,
size: chunk1.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
fii: true,
uri: mockedUri,
upload_id: mockUploadId,
offset: 0,
part: 1,
});
return [2 /*return*/];
}
});
}); });
it('should exit on 4xx errors', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost,
upload_type: 'intelligent_ingestion',
});
interceptorS3.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setTimeout(100);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
return [2 /*return*/];
}
});
}); });
it('should nor process upload on multipart/upload network error', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorUpload.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockStart).toHaveBeenCalled();
expect(mockPut).not.toHaveBeenCalled();
expect(mockCommit).not.toHaveBeenCalled();
expect(mockComplete).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
});
describe('Fallback mode', function () {
it('should switch to fallback mode if regular upload fails', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res, testFile, firstPartMeta, firstPart;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost,
upload_type: 'intelligent_ingestion',
});
networkFail = true;
nock_1.default.removeInterceptor(interceptorS3);
scope.put('/fakes3').reply(function (url, _, cb) {
if (networkFail) {
networkFail = false;
return cb('Error');
}
cb(null, [201, mockPut(url, this.req.headers), { etag: 'test' }]);
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("fallback" /* UploadMode.FALLBACK */);
u.setIntelligentChunkSize(abstract_1.INTELLIGENT_CHUNK_SIZE);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
testFile = getSmallTestFile();
firstPartMeta = testFile.getPartMetadata(0, abstract_1.DEFAULT_PART_SIZE);
return [4 /*yield*/, testFile.getPartByMetadata(firstPartMeta)];
case 2:
firstPart = _a.sent();
expect(mockUpload).toHaveBeenNthCalledWith(1, {
md5: firstPart.md5,
size: firstPart.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 1,
});
expect(mockUpload).toHaveBeenNthCalledWith(2, {
md5: firstPart.md5,
size: firstPart.size,
fii: true,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
offset: 0,
upload_id: mockUploadId,
part: 1,
});
return [2 /*return*/];
}
});
}); });
it('should exit if intelligent ingestion is not enabled in account settings', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReturnValue({
uri: mockedUri,
region: mockRegion,
upload_id: mockUploadId,
location_url: testHost,
});
networkFail = true;
interceptorS3.reply(function (url, _, cb) {
if (networkFail) {
networkFail = false;
return cb({
message: 'ConnectionError',
code: 'ETIMEDOUT',
});
}
cb(null, [201, mockPut(url, this.req.headers), { etag: 'test' }]);
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("fallback" /* UploadMode.FALLBACK */);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockCommit).not.toHaveBeenCalled();
expect(mockComplete).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
});
});
describe('Regular upload', function () {
it('should upload file', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var partSize, u, res, testFile, firstPartMeta, firstPart, secondPartMeta, secondPart;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
partSize = 1024 * 1024 * 7;
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setPartSize(partSize);
u.addFile(getTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
testFile = getTestFile();
expect(mockStart).toHaveBeenCalledWith({
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
});
firstPartMeta = testFile.getPartMetadata(0, partSize);
return [4 /*yield*/, testFile.getPartByMetadata(firstPartMeta)];
case 2:
firstPart = _a.sent();
expect(mockUpload).toHaveBeenNthCalledWith(1, {
md5: firstPart.md5,
size: firstPart.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 1,
});
secondPartMeta = testFile.getPartMetadata(1, partSize);
return [4 /*yield*/, testFile.getPartByMetadata(secondPartMeta)];
case 3:
secondPart = _a.sent();
expect(mockUpload).toHaveBeenNthCalledWith(2, {
md5: secondPart.md5,
size: secondPart.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 2,
});
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
parts: [{ part_number: 1, etag: 'test' }, { part_number: 2, etag: 'test' }],
region: mockRegion,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
});
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
return [2 /*return*/];
}
});
}); });
it('should upload file with disable integrity check enabled', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var partSize, u, res, testFile, firstPartMeta, firstPart, secondPartMeta, secondPart;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
partSize = 1024 * 1024 * 7;
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setPartSize(partSize);
u.addFile(getTestFile());
u.setIntegrityCheck(false);
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
testFile = getTestFile();
expect(mockStart).toHaveBeenCalledWith({
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
});
firstPartMeta = testFile.getPartMetadata(0, partSize);
return [4 /*yield*/, testFile.getPartByMetadata(firstPartMeta)];
case 2:
firstPart = _a.sent();
expect(mockUpload).toHaveBeenNthCalledWith(1, {
size: firstPart.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 1,
});
secondPartMeta = testFile.getPartMetadata(1, partSize);
return [4 /*yield*/, testFile.getPartByMetadata(secondPartMeta)];
case 3:
secondPart = _a.sent();
expect(mockUpload).toHaveBeenNthCalledWith(2, {
size: secondPart.size,
apikey: testApikey,
region: mockRegion,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
part: 2,
});
expect(mockPut).toHaveBeenCalledWith('/fakes3', expect.any(Object));
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
parts: [{ part_number: 1, etag: 'test' }, { part_number: 2, etag: 'test' }],
region: mockRegion,
upload_id: mockUploadId,
store: {
location: abstract_1.DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
});
expect(res[0].handle).toEqual('test_handle');
expect(res[0].status).toEqual('test_status');
return [2 /*return*/];
}
});
}); });
it('should not process upload on multipart/upload network error', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorUpload.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockStart).toHaveBeenCalled();
expect(mockPut).not.toHaveBeenCalled();
expect(mockCommit).not.toHaveBeenCalled();
expect(mockComplete).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should respect retry config', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
networkFail = true;
nock_1.default.removeInterceptor(interceptorS3);
scope.persist(false);
scope.put('/fakes3').twice().reply(function (url, _, cb) {
if (networkFail) {
networkFail = false;
return cb(Error('error'));
}
cb(null, [201, mockPut(url, this.req.headers), { etag: 'test' }]);
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
u.setRetryConfig({
retry: 1,
retryFactor: 2,
retryMaxTime: 10,
});
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('test_status');
return [2 /*return*/];
}
});
}); });
});
describe('Common network errors', function () {
it('should not process upload on wrong start response', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReset();
mockStart.mockReturnValue({
test: 123,
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockPut).not.toHaveBeenCalled();
expect(mockUpload).not.toHaveBeenCalled();
expect(mockCommit).not.toHaveBeenCalled();
expect(mockComplete).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should not process upload on start error', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorStart.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockPut).not.toHaveBeenCalled();
expect(mockUpload).not.toHaveBeenCalled();
expect(mockCommit).not.toHaveBeenCalled();
expect(mockComplete).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
it('should nor process upload on multipart/complete network error', function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () {
var u, res;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorComplete.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new s3_1.S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.addFile(getSmallTestFile());
return [4 /*yield*/, u.execute()];
case 1:
res = _a.sent();
expect(res[0].status).toEqual('Failed');
expect(mockStart).toHaveBeenCalled();
expect(mockPut).toHaveBeenCalled();
expect(mockCommit).not.toHaveBeenCalled();
return [2 /*return*/];
}
});
}); });
});
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL3VwbG9hZC91cGxvYWRlcnMvczMuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHOzs7QUFFSCwyQkFBa0M7QUFDbEMsa0NBQWlDO0FBQ2pDLHNEQUF3QjtBQUN4Qix1Q0FBMEk7QUFDMUksdUVBQW1EO0FBRW5ELElBQU0sY0FBYyxHQUFHLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZDLElBQU0sbUJBQW1CLEdBQUcsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7QUFDNUMsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUN6RSxJQUFJLGFBQWEsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztBQUV4RixJQUFJLEtBQUssQ0FBQztBQUNWLElBQUksYUFBYSxDQUFDO0FBQ2xCLElBQUksZ0JBQWdCLENBQUM7QUFDckIsSUFBSSxpQkFBaUIsQ0FBQztBQUN0QixJQUFJLGlCQUFpQixDQUFDO0FBQ3RCLElBQUksbUJBQW1CLENBQUM7QUFFeEIsSUFBTSxXQUFXLEdBQUc7SUFDbEIsT0FBQSxJQUFJLFdBQUksQ0FBQztRQUNQLEtBQUssRUFBRSxVQUFDLEtBQUssRUFBRSxHQUFHLElBQUssT0FBQSxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEVBQTNDLENBQTJDO1FBQ2xFLElBQUksRUFBRSxZQUFZO1FBQ2xCLGFBQWE7UUFDYixJQUFJLEVBQUUsUUFBUSxDQUFDLE1BQU07UUFDckIsSUFBSSxFQUFFLFVBQVU7S0FDakIsQ0FBQztBQU5GLENB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TyxFQUFFLEVBQUE7O3dCQUF2QixHQUFHLEdBQUcsU0FBaUI7d0JBRTdCLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO3dCQUV4QyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQzt3QkFDckMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7d0JBQ25DLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQzs7OzthQUMzQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwiZmlsZSI6ImxpYi9hcGkvdXBsb2FkL3VwbG9hZGVycy9zMy5zcGVjLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOSBieSBGaWxlc3RhY2suXG4gKiBTb21lIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgUzNVcGxvYWRlciB9IGZyb20gJy4vczMnO1xuaW1wb3J0IHsgRmlsZSB9IGZyb20gJy4vLi4vZmlsZSc7XG5pbXBvcnQgbm9jayBmcm9tICdub2NrJztcbmltcG9ydCB7IFVwbG9hZE1vZGUsIERFRkFVTFRfU1RPUkVfTE9DQVRJT04sIElOVEVMTElHRU5UX0NIVU5LX1NJWkUsIERFRkFVTFRfUEFSVF9TSVpFLCBJTlRFTExJR0VOVF9NT0JJTEVfQ0hVTktfU0laRSB9IGZyb20gJy4vYWJzdHJhY3QnO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSAnLi4vLi4vLi4vdXRpbHMvaW5kZXgubm9kZSc7XG5cbmNvbnN0IHRlc3RCdWZmZXJTaXplID0gMTAyNCAqIDEwMjQgKiA5O1xuY29uc3QgdGVzdFNtYWxsQnVmZmVyU2l6ZSA9IDEwMjQgKiAxMDI0ICogMjtcbmxldCB0ZXN0QnVmZiA9IEJ1ZmZlci5hbGxvYyh0ZXN0QnVmZmVyU2l6ZSkuZmlsbCgndCcsIDAsIHRlc3RCdWZmZXJTaXplKTtcbmxldCBzbWFsbFRlc3RCdWZmID0gQnVmZmVyLmFsbG9jKHRlc3RTbWFsbEJ1ZmZlclNpemUpLmZpbGwoJ3QnLCAwLCB0ZXN0U21hbGxCdWZmZXJTaXplKTtcblxubGV0IHNjb3BlO1xubGV0IGludGVyY2VwdG9yUzM7XG5sZXQgaW50ZXJjZXB0b3JTdGFydDtcbmxldCBpbnRlcmNlcHRvckNvbW1pdDtcbmxldCBpbnRlcmNlcHRvclVwbG9hZDtcbmxldCBpbnRlcmNlcHRvckNvbXBsZXRlO1xuXG5jb25zdCBnZXRUZXN0RmlsZSA9ICgpID0+XG4gIG5ldyBGaWxlKHtcbiAgICBzbGljZTogKHN0YXJ0LCBlbmQpID0+IFByb21pc2UucmVzb2x2ZSh0ZXN0QnVmZi5zbGljZShzdGFydCwgZW5kKSksXG4gICAgdHlwZTogJ3RleHQvcGxhaW4nLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBzaXplOiB0ZXN0QnVmZi5sZW5ndGgsXG4gICAgbmFtZTogJ3Rlc3QudHh0JyxcbiAgfSk7XG5cbmNvbnN0IGdldFNtYWxsVGVzdEZpbGUgPSAoKSA9PlxuICBuZXcgRmlsZSh7XG4gICAgc2xpY2U6IChzdGFydCwgZW5kKSA9PiBQcm9taXNlLnJlc29sdmUodGVzdEJ1ZmYuc2xpY2Uoc3RhcnQsIGVuZCkpLFxuICAgIHR5cGU6ICd0ZXh0L3BsYWluJyxcbiAgICAvLyBAdHMtaWdub3JlXG4gICAgc2l6ZTogc21hbGxUZXN0QnVmZi5sZW5ndGgsXG4gICAgbmFtZTogJ3Rlc3QudHh0JyxcbiAgfSk7XG5cbmNvbnN0IGdldE51bGxTaXplRmlsZSA9ICgpID0+XG4gIG5ldyBGaWxlKHtcbiAgICBzbGljZTogKHN0YXJ0LCBlbmQpID0+IFByb21pc2UucmVzb2x2ZSh0ZXN0QnVmZi5zbGljZShzdGFydCwgZW5kKSksXG4gICAgdHlwZTogJ3RleHQvcGxhaW4nLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBzaXplOiAwLFxuICAgIG5hbWU6ICd0ZXN0LnR4dCcsXG4gIH0pO1xuXG5jb25zdCB0ZXN0QXBpa2V5ID0gJ3Rlc3RhcGlrZXknO1xuY29uc3QgdGVzdEhvc3QgPSAnaHR0cHM6Ly9maWxlc3RhY2stdGVzdC5jb20nO1xuY29uc3QgbW9ja1VwbG9hZElkID0gJzEyMzEzMjEyMyc7XG5jb25zdCBtb2NrUmVnaW9uID0gJ3Rlc3QtcmVnaW9uJztcbmNvbnN0IG1vY2tlZFVyaSA9ICcvc29tZXRlc3QnO1xuY29uc3QgczNVcmwgPSB0ZXN0SG9zdCArICcvZmFrZXMzJztcblxuY29uc3QgbW9ja1N0YXJ0ID0gamVzdC5mbigpLm1vY2tOYW1lKCdtdWx0aXBhcnQvc3RhcnQnKTtcbmNvbnN0IG1vY2tVcGxvYWQgPSBqZXN0LmZuKCkubW9ja05hbWUoJ211bHRpcGFydC91cGxvYWQnKTtcbmNvbnN0IG1vY2tQdXQgPSBqZXN0LmZuKCkubW9ja05hbWUoJ3MzL3B1dCcpO1xuY29uc3QgbW9ja0NvbW1pdCA9IGplc3QuZm4oKS5tb2NrTmFtZSgnbXVsdGlwYXJ0L2NvbW1pdCcpO1xuY29uc3QgbW9ja0NvbXBsZXRlID0gamVzdC5mbigpLm1vY2tOYW1lKCdtdWx0aXBhcnQvY29tcGxldGUnKTtcblxuY29uc3QgczNDYWxsYmFjayA9IGZ1bmN0aW9uKHVybCkge1xuICByZXR1cm4gbW9ja1B1dCh1cmwsIHRoaXMucmVxLmhlYWRlcnMpO1xufTtcblxuZGVzY3JpYmUoJ0FwaS9VcGxvYWQvVXBsb2FkZXJzL1MzJywgKCkgPT4ge1xuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBzY29wZSA9IG5vY2sodGVzdEhvc3QpO1xuICAgIC8vIHNjb3BlLmRlZmF1bHRSZXBseUhlYWRlcnMoeyAnYWNjZXNzLWNvbnRyb2wtYWxsb3ctb3JpZ2luJzogJyonLCAnY29udGVudC10eXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0pO1xuICAgIHNjb3BlLnBlcnNpc3QoKTtcblxuICAgIGludGVyY2VwdG9yU3RhcnQgPSBzY29wZS5wb3N0KCcvbXVsdGlwYXJ0L3N0YXJ0Jyk7XG4gICAgaW50ZXJjZXB0b3JVcGxvYWQgPSBzY29wZS5wb3N0KCcvbXVsdGlwYXJ0L3VwbG9hZCcpO1xuICAgIGludGVyY2VwdG9yQ29tbWl0ID0gc2NvcGUucG9zdCgnL211bHRpcGFydC9jb21taXQnKTtcbiAgICBpbnRlcmNlcHRvckNvbXBsZXRlID0gc2NvcGUucG9zdCgnL211bHRpcGFydC9jb21wbGV0ZScpO1xuICAgIGludGVyY2VwdG9yUzMgPSBzY29wZS5wdXQoJy9mYWtlczMnKTtcblxuICAgIGludGVyY2VwdG9yU3RhcnQucmVwbHkoMjAwLCAoXywgZGF0YSkgPT4gbW9ja1N0YXJ0KGRhdGEpKTtcbiAgICBpbnRlcmNlcHRvclVwbG9hZC50d2ljZSgpLnJlcGx5KDIwMCwgKF8sIGRhdGEpID0+IG1vY2tVcGxvYWQoZGF0YSkpO1xuICAgIGludGVyY2VwdG9yQ29tbWl0LnJlcGx5KDIwMCwgKF8sIGRhdGEpID0+IG1vY2tDb21taXQoZGF0YSkpO1xuICAgIGludGVyY2VwdG9yQ29tcGxldGUucmVwbHkoMjAwLCAoXywgZGF0YSkgPT4gbW9ja0NvbXBsZXRlKGRhdGEpKTtcbiAgICBpbnRlcmNlcHRvclMzLnR3aWNlKCkucmVwbHkoMjAxLCBzM0NhbGxiYWNrLCB7IGV0YWc6ICd0ZXN0JyB9KTtcblxuICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QsXG4gICAgfSk7XG5cbiAgICBtb2NrVXBsb2FkLm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICB1cmw6IHMzVXJsLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICB0ZXN0OiAndGVzdCcsXG4gICAgICB9LFxuICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdCxcbiAgICB9KTtcblxuICAgIG1vY2tQdXQubW9ja1JldHVyblZhbHVlKHt9KTtcbiAgICBtb2NrQ29tbWl0Lm1vY2tSZXR1cm5WYWx1ZSh7fSk7XG5cbiAgICBtb2NrQ29tcGxldGUubW9ja1JldHVyblZhbHVlKHtcbiAgICAgIGhhbmRsZTogJ3Rlc3RfaGFuZGxlJyxcbiAgICAgIHVybDogJ3Rlc3RfdXJsJyxcbiAgICAgIGZpbGVuYW1lOiAndGVzdF9maWxlbmFtZScsXG4gICAgICBzaXplOiAxMjMsXG4gICAgICBtaW1ldHlwZTogJ3Rlc3RfbWltZXR5cGUnLFxuICAgICAgc3RhdHVzOiAndGVzdF9zdGF0dXMnLFxuICAgICAgdXBsb2FkX3RhZ3M6IHsgdGVzdDogMTIzIH0sXG4gICAgfSk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIG5vY2suZW5hYmxlTmV0Q29ubmVjdCgpO1xuICAgIGplc3QuY2xlYXJBbGxNb2NrcygpO1xuICB9KTtcblxuICBkZXNjcmliZSgnU3RhbmRhcnQgdGVzdHMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBpbml0aWFsaXplIGNsYXNzIHdpdGhvdXQgZXJyb3JzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgICAgY29uc3QgdXUgPSBuZXcgUzNVcGxvYWRlcih7fSwgMTApO1xuICAgICAgfSkubm90LnRvVGhyb3dFcnJvcigpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyBhZGRpbmcgZmlsZXMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5hZGRGaWxlKGdldFRlc3RGaWxlKCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgYWxsb3cgdG8gc2V0IG1pbiBwYXJ0IHNpemUgbG93ZXIgdGhhbiBkZWZpbmVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIGV4cGVjdCgoKSA9PiB1LnNldFBhcnRTaXplKDEwKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIHdoZW4gc2V0dGluZyB0byBzbWFsbCBpbnRlbGxpZ2VudCBjaHVuayBzaXplJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIGV4cGVjdCgoKSA9PiB1LnNldEludGVsbGlnZW50Q2h1bmtTaXplKDEwKSkudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGFuIGVycm9yIHdoZW4gdHJ5aW5nIHRvIGdldCBob3N0IHdoZW4gaXQgaXMgdW5kZWZpbmVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIGV4cGVjdCgoKSA9PiB1LmdldFVybCgpKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2V0IGludGVsbGlnZW50IG1vYmlsZSBjaHVuayBzaXplIG9uIG1vYmlsZSBkZXZpY2VzJywgKCkgPT4ge1xuICAgICAgamVzdC5zcHlPbih1dGlscywgJ2lzTW9iaWxlJykubW9ja1JldHVyblZhbHVlKHRydWUpO1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIHJldHVybiBleHBlY3QodS5nZXRJbnRlbGxpZ2VudENodW5rU2l6ZSgpKS50b0VxdWFsKElOVEVMTElHRU5UX01PQklMRV9DSFVOS19TSVpFKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWxsb3cgdG8gc2V0IHBhcnQgc2l6ZSBvbiBvdGhlciBtb2RlIHRoYW50IHJlZ3VsYXInLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpO1xuXG4gICAgICBjb25zdCBwYXJ0U2l6ZSA9IDEwMjQgKiAxMDI0O1xuICAgICAgdS5zZXRQYXJ0U2l6ZShwYXJ0U2l6ZSk7XG5cbiAgICAgIGV4cGVjdCh1LmdldFBhcnRTaXplKCkpLnRvRXF1YWwoREVGQVVMVF9QQVJUX1NJWkUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXRyeSBjb21wbGV0ZSByZXF1ZXN0IG9uIDIwMiBzdGF0dXMgY29kZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IG1vY2syMDIgPSBqZXN0XG4gICAgICAgIC5mbigpXG4gICAgICAgIC5tb2NrTmFtZSgnMjAyIG1vY2snKVxuICAgICAgICAubW9ja1JldHVyblZhbHVlKCcnKTtcblxuICAgICAgbm9jay5yZW1vdmVJbnRlcmNlcHRvcihpbnRlcmNlcHRvckNvbXBsZXRlKTtcbiAgICAgIHNjb3BlLnBlcnNpc3QoZmFsc2UpO1xuICAgICAgc2NvcGUucG9zdCgnL211bHRpcGFydC9jb21wbGV0ZScpLnJlcGx5KDIwMiwgKCkgPT4gbW9jazIwMigpKTtcbiAgICAgIHNjb3BlLnBvc3QoJy9tdWx0aXBhcnQvY29tcGxldGUnKS5yZXBseSgyMDAsIChfLCBkYXRhKSA9PiBtb2NrQ29tcGxldGUoZGF0YSkpO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0VGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLmhhbmRsZSkudG9FcXVhbCgndGVzdF9oYW5kbGUnKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICBleHBlY3QobW9jazIwMikudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDEpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IHByb3ZpZGVkIHN0b3JlIG9wdGlvbnMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzdG9yZU9wdGlvbiA9IHtcbiAgICAgICAgY29udGFpbmVyOiAndGVzdCcsXG4gICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICB3b3JrZmxvd3M6IFt7XG4gICAgICAgICAgaWQ6ICd0ZXN0JyxcbiAgICAgICAgfV0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoc3RvcmVPcHRpb24pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHN0b3JlOiBzdG9yZU9wdGlvbiB9KSk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7IHN0b3JlOiBzdG9yZU9wdGlvbiB9KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFkZCBodHRwcyBwcm90b2NvbCB0byBsb2NhdGlvbl91cmwnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QucmVwbGFjZSgnaHR0cHM6Ly8nLCAnJyksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLmhhbmRsZSkudG9FcXVhbCgndGVzdF9oYW5kbGUnKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBvbiBmaWxlIHNpemUgMCcsIGFzeW5jICgpID0+IHtcbiAgICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdC5yZXBsYWNlKCdodHRwczovLycsICcnKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0TnVsbFNpemVGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuICAgICAgZXhwZWN0KG1vY2tTdGFydCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igb24gd3JvbmcgZXRhZyBmaWVsZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdC5yZXBsYWNlKCdodHRwczovLycsICcnKSxcbiAgICAgIH0pO1xuXG4gICAgICBpbnRlcmNlcHRvclMzLm9uY2UoKS5yZXBseSgyMDAsIHMzQ2FsbGJhY2ssIHt9KTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcblxuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgdS5vbignZXJyb3InLCAoZXJyKSA9PiB7XG4gICAgICAgIGV4cGVjdChlcnIubWVzc2FnZSkudG9FcXVhbCgnQ2Fubm90IHVwbG9hZCBmaWxlLCBjaGVjayBTMyBidWNrZXQgc2V0dGluZ3MnKTtcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWRkIEZpbGVzdGFjay1VcGxvYWQtUmVnaW9uIGhlYWRlciBvbiBsb2NhdGlvbl9yZWdpb24gcGFyYW0nLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIGxvY2F0aW9uX3JlZ2lvbjogJ3Rlc3QnLFxuICAgICAgICBsb2NhdGlvbl91cmw6IHRlc3RIb3N0LnJlcGxhY2UoJ2h0dHBzOi8vJywgJycpLFxuICAgICAgfSk7XG5cbiAgICAgIGludGVyY2VwdG9yVXBsb2FkLnJlcGx5KDIwMCwgZnVuY3Rpb24oXywgZGF0YSkge1xuICAgICAgICByZXR1cm4gbW9ja1VwbG9hZChkYXRhLCB0aGlzLnJlcS5oZWFkZXJzKTtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG5cbiAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0U21hbGxUZXN0RmlsZSgpO1xuXG4gICAgICBjb25zdCBmaXJzdFBhcnRNZXRhZGF0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgwLCBERUZBVUxUX1BBUlRfU0laRSk7XG4gICAgICBjb25zdCBmaXJzdFBhcnRDaHVuayA9IGF3YWl0IHRlc3RGaWxlLmdldFBhcnRCeU1ldGFkYXRhKGZpcnN0UGFydE1ldGFkYXRhKTtcblxuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKFxuICAgICAgICB7XG4gICAgICAgICAgbWQ1OiBmaXJzdFBhcnRDaHVuay5tZDUsXG4gICAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgIH0sXG4gICAgICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgJ2ZpbGVzdGFjay11cGxvYWQtcmVnaW9uJzogJ3Rlc3QnIH0pXG4gICAgICApO1xuXG4gICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IHBhdXNlKCkgYW5kIHJlc3VtZSgpIGNvbW1hbmQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0VGVzdEZpbGUoKSk7XG5cbiAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB1LnBhdXNlKCkpO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB1LnJlc3VtZSgpLCAxMCk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLmhhbmRsZSkudG9FcXVhbCgndGVzdF9oYW5kbGUnKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IGFib3J0KCkgY29tbWFuZCcsIChkb25lKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0VGVzdEZpbGUoKSk7XG5cbiAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB1LmFib3J0KCkpO1xuICAgICAgdS5leGVjdXRlKCkudGhlbigocmVzKSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCdGYWlsZWQnKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICBkb25lKCdFeGVjdXRpb24gZmFpbGVkJyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2VuZCBjb3JyZWN0IHNlY3VyaXR5JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdFNlY3VyaXR5ID0ge1xuICAgICAgICBwb2xpY3k6ICd0ZXN0X3AnLFxuICAgICAgICBzaWduYXR1cmU6ICd0ZXN0X3MnLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgdS5zZXRTZWN1cml0eSh0ZXN0U2VjdXJpdHkpO1xuICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHRlc3RTZWN1cml0eSkpO1xuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHRlc3RTZWN1cml0eSkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcodGVzdFNlY3VyaXR5KSk7XG5cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBkaXNhYmxlU3RvcmFnZUtleSBvcHRpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe1xuICAgICAgICBkaXNhYmxlU3RvcmFnZUtleTogdHJ1ZSxcbiAgICAgICAgcGF0aDogJy90ZXN0LycsXG4gICAgICB9KTtcblxuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgY29uc3Qgc3RvcmFnZUtleUV4cGVjdCA9IHtcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogJ3MzJyxcbiAgICAgICAgICBwYXRoOiAnL3Rlc3QvdGVzdC50eHQnLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHN0b3JhZ2VLZXlFeHBlY3QpKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHN0b3JhZ2VLZXlFeHBlY3QpKTtcblxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IGRpc2FibGVTdG9yYWdlS2V5IG9wdGlvbiB3aGVuIHBhdGggaXMgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7XG4gICAgICAgIGRpc2FibGVTdG9yYWdlS2V5OiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG5cbiAgICAgIGNvbnN0IHN0b3JhZ2VLZXlFeHBlY3QgPSB7XG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246ICdzMycsXG4gICAgICAgICAgcGF0aDogJy90ZXN0LnR4dCcsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyhzdG9yYWdlS2V5RXhwZWN0KSk7XG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuXG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgZGlzYWJsZVN0b3JhZ2VLZXkgb3B0aW9uIHdoZW4gcGF0aCBoYXMgbWlzc2luZyAvJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHtcbiAgICAgICAgZGlzYWJsZVN0b3JhZ2VLZXk6IHRydWUsXG4gICAgICAgIHBhdGg6ICcvdGVzdCcsXG4gICAgICB9KTtcblxuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgY29uc3Qgc3RvcmFnZUtleUV4cGVjdCA9IHtcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogJ3MzJyxcbiAgICAgICAgICBwYXRoOiAnL3Rlc3QvdGVzdC50eHQnLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHN0b3JhZ2VLZXlFeHBlY3QpKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHN0b3JhZ2VLZXlFeHBlY3QpKTtcbiAgICB9KTtcblxuICB9KTtcblxuICBkZXNjcmliZSgnVGFncycsICgpID0+IHtcbiAgICBpdCgnTWFrZSBjb3JyZWN0IHJlcXVlc3Qgd2l0aCB1cGxvYWQgdGFncycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7XG4gICAgICAgIGRpc2FibGVTdG9yYWdlS2V5OiB0cnVlLFxuICAgICAgICBwYXRoOiAnL3Rlc3QnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRhZ3MgPSB7XG4gICAgICAgIHRlc3Q6ICcxMjMnLFxuICAgICAgICB0ZXN0MjogJ3Rlc3QnLFxuICAgICAgfTtcblxuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcbiAgICAgIHUuc2V0VXBsb2FkVGFncyh0YWdzKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgY29uc3QgdGFnc0V4cGVjdGVkID0ge1xuICAgICAgICB1cGxvYWRfdGFnczogdGFncyxcbiAgICAgIH07XG5cbiAgICAgIGV4cGVjdChyZXNbMF0udXBsb2FkVGFncykudG9FcXVhbCh7IHRlc3Q6IDEyMyB9KTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHRhZ3NFeHBlY3RlZCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVXBsb2FkIG1vZGVzJywgKCkgPT4ge1xuICAgIGRlc2NyaWJlKCdJbnRlbGxpZ2VudCBpbmdlc3Npb24nLCAoKSA9PiB7XG4gICAgICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QsXG4gICAgICAgICAgdXBsb2FkX3R5cGU6ICdpbnRlbGxpZ2VudF9pbmdlc3Rpb24nLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHVwbG9hZCBmaWxlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBjaHVua1NpemUgPSAxMDI0ICogMTAyNDtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG4gICAgICAgIHUuc2V0SW50ZWxsaWdlbnRDaHVua1NpemUoY2h1bmtTaXplKTtcbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuXG4gICAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0U21hbGxUZXN0RmlsZSgpO1xuICAgICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgZmlsZW5hbWU6IHRlc3RGaWxlLm5hbWUsXG4gICAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0T2Zmc2V0ID0gMDtcbiAgICAgICAgY29uc3QgeyBwYXJ0c0NvdW50LCBjaHVua1NpemU6IGR5bmFtaWNQYXJ0U2l6ZSB9ID0gdGVzdEZpbGUuZ2V0UGFydHNDb3VudChJTlRFTExJR0VOVF9DSFVOS19TSVpFLCB0cnVlKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0TWV0YWRhdGEgPSB0ZXN0RmlsZS5nZXRQYXJ0TWV0YWRhdGEoMCwgZHluYW1pY1BhcnRTaXplKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0Q2h1bmsgPSBhd2FpdCB0ZXN0RmlsZS5nZXRDaHVua0J5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YWRhdGEsIGZpcnN0UGFydE9mZnNldCwgZHluYW1pY1BhcnRTaXplKTtcblxuICAgICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgIG1kNTogZmlyc3RQYXJ0Q2h1bmsubWQ1LFxuICAgICAgICAgIHNpemU6IGZpcnN0UGFydENodW5rLnNpemUsXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBvZmZzZXQ6IGZpcnN0UGFydE9mZnNldCxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCcvZmFrZXMzJywgZXhwZWN0LmFueShPYmplY3QpKTtcblxuICAgICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJy9mYWtlczMnLCBleHBlY3QuYW55KE9iamVjdCkpO1xuXG4gICAgICAgIGV4cGVjdChtb2NrQ29tbWl0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgZmlsZW5hbWU6IHRlc3RGaWxlLm5hbWUsXG4gICAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCB1cGxvYWQgZmlsZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgY2h1bmtTaXplID0gMTAyNCAqIDEwMjQ7XG5cbiAgICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgICAgdS5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpO1xuICAgICAgICB1LnNldEludGVsbGlnZW50Q2h1bmtTaXplKGNodW5rU2l6ZSk7XG4gICAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuICAgICAgICBleHBlY3QocmVzWzBdLmhhbmRsZSkudG9FcXVhbCgndGVzdF9oYW5kbGUnKTtcblxuICAgICAgICBjb25zdCB0ZXN0RmlsZSA9IGdldFNtYWxsVGVzdEZpbGUoKTtcbiAgICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICAgIG1pbWV0eXBlOiB0ZXN0RmlsZS5taW1ldHlwZSxcbiAgICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGZpcnN0UGFydE9mZnNldCA9IDA7XG4gICAgICAgIGNvbnN0IHsgcGFydHNDb3VudCwgY2h1bmtTaXplOiBkeW5hbWljUGFydFNpemUgfSA9IHRlc3RGaWxlLmdldFBhcnRzQ291bnQoSU5URUxMSUdFTlRfQ0hVTktfU0laRSwgdHJ1ZSk7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFydE1ldGFkYXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIGR5bmFtaWNQYXJ0U2l6ZSk7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFydENodW5rID0gYXdhaXQgdGVzdEZpbGUuZ2V0Q2h1bmtCeU1ldGFkYXRhKGZpcnN0UGFydE1ldGFkYXRhLCBmaXJzdFBhcnRPZmZzZXQsIGR5bmFtaWNQYXJ0U2l6ZSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICBtZDU6IGZpcnN0UGFydENodW5rLm1kNSxcbiAgICAgICAgICBzaXplOiBmaXJzdFBhcnRDaHVuay5zaXplLFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgb2Zmc2V0OiBmaXJzdFBhcnRPZmZzZXQsXG4gICAgICAgICAgZmlpOiB0cnVlLFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGV4cGVjdChtb2NrUHV0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnL2Zha2VzMycsIGV4cGVjdC5hbnkoT2JqZWN0KSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCcvZmFrZXMzJywgZXhwZWN0LmFueShPYmplY3QpKTtcblxuICAgICAgICBleHBlY3QobW9ja0NvbW1pdCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICBwYXJ0OiAxLFxuICAgICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICAgIG1pbWV0eXBlOiB0ZXN0RmlsZS5taW1ldHlwZSxcbiAgICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbG93ZXIgY2h1bmsgc2l6ZSBvbiBuZXR3b3JrIGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBwdXRSZXF1ZXN0VGltZW91dCA9IDMwMDtcbiAgICAgICAgbGV0IGRlbGF5QXBwbGllZCA9IGZhbHNlO1xuXG4gICAgICAgIG5vY2sucmVtb3ZlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3JTMyk7XG4gICAgICAgIHNjb3BlLnB1dCgnL2Zha2VzMycpLnJlcGx5KFxuICAgICAgICAgIGZ1bmN0aW9uKHVybCwgXywgY2IpIHtcbiAgICAgICAgICAgIGlmICghZGVsYXlBcHBsaWVkKSB7XG4gICAgICAgICAgICAgIGRlbGF5QXBwbGllZCA9IHRydWU7XG4gICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNiKDUwNCk7XG4gICAgICAgICAgICAgIH0sIDMwMDApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgY2IobnVsbCwgWzIwMSwgbW9ja1B1dCh1cmwsIHRoaXMucmVxLmhlYWRlcnMpLCB7ZXRhZzogJ3Rlc3QnfV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFRpbWVvdXQocHV0UmVxdWVzdFRpbWVvdXQpO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG4gICAgICAgIHUuc2V0SW50ZWxsaWdlbnRDaHVua1NpemUoSU5URUxMSUdFTlRfQ0hVTktfU0laRSk7XG5cbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgICBjb25zdCB0ZXN0RmlsZSA9IGdldFNtYWxsVGVzdEZpbGUoKTtcbiAgICAgICAgY29uc3QgeyBwYXJ0c0NvdW50LCBjaHVua1NpemU6IGR5bmFtaWNQYXJ0U2l6ZSB9ID0gdGVzdEZpbGUuZ2V0UGFydHNDb3VudChJTlRFTExJR0VOVF9DSFVOS19TSVpFLCB0cnVlKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0TWV0YWRhdGEgPSB0ZXN0RmlsZS5nZXRQYXJ0TWV0YWRhdGEoMCwgZHluYW1pY1BhcnRTaXplKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0Q2h1bmsgPSBhd2FpdCB0ZXN0RmlsZS5nZXRDaHVua0J5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YWRhdGEsIDAsIGR5bmFtaWNQYXJ0U2l6ZSk7XG5cbiAgICAgICAgLy8gdGhpcyByZXF1ZXN0IHdpbGwgYmUgYWJvcnRlZCBidXQgY2FsbGVkIG9uIG1vY2sgdXBsb2FkXG4gICAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgxLCB7XG4gICAgICAgICAgbWQ1OiBmaXJzdFBhcnRDaHVuay5tZDUsXG4gICAgICAgICAgc2l6ZTogZmlyc3RQYXJ0Q2h1bmsuc2l6ZSxcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gc3BsaXQgcGFydCBzaXplIGJ5IGEgaGFsZiBhbmQgcmV0cnkgcmVxdWVzdCAodGhhdHMgZ2l2ZSB1cyAyIGNodW5rcyBzbyAyIHVwbG9hZCByZXF1ZXN0cyBuZWVkZWQpXG4gICAgICAgIGxldCB7IGNodW5rU2l6ZSB9ID0gdGVzdEZpbGUuZ2V0UGFydHNDb3VudChJTlRFTExJR0VOVF9DSFVOS19TSVpFLCB0cnVlKTtcbiAgICAgICAgY2h1bmtTaXplID0gY2h1bmtTaXplIC8gMjtcbiAgICAgICAgY29uc3QgdXBkYXRlZEZpcnN0UGFydE1ldGFEYXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIGNodW5rU2l6ZSk7XG4gICAgICAgIGNvbnN0IGNodW5rMSA9IGF3YWl0IHRlc3RGaWxlLmdldENodW5rQnlNZXRhZGF0YSh1cGRhdGVkRmlyc3RQYXJ0TWV0YURhdGEsIDAsIGNodW5rU2l6ZSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoKDIsIHtcbiAgICAgICAgICBtZDU6IGNodW5rMS5tZDUsXG4gICAgICAgICAgc2l6ZTogY2h1bmsxLnNpemUsXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgIH0pO1xuXG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBleGl0IG9uIDR4eCBlcnJvcnMnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBsb2NhdGlvbl91cmw6IHRlc3RIb3N0LFxuICAgICAgICAgIHVwbG9hZF90eXBlOiAnaW50ZWxsaWdlbnRfaW5nZXN0aW9uJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaW50ZXJjZXB0b3JTMy5yZXBseSg0MDAsIHtcbiAgICAgICAgICBtZXNzYWdlOiAnc29tZXRoaW5nIGF3ZnVsIGhhcHBlbmVkJyxcbiAgICAgICAgICBjb2RlOiAnYmFkX3JlcXVlc3QnLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFRpbWVvdXQoMTAwKTtcbiAgICAgICAgdS5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpO1xuXG4gICAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgbm9yIHByb2Nlc3MgdXBsb2FkIG9uIG11bHRpcGFydC91cGxvYWQgbmV0d29yayBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgICAgICAgaW50ZXJjZXB0b3JVcGxvYWQucmVwbHkoNDAwLCB7XG4gICAgICAgICAgbWVzc2FnZTogJ3NvbWV0aGluZyBhd2Z1bCBoYXBwZW5lZCcsXG4gICAgICAgICAgY29kZTogJ2JhZF9yZXF1ZXN0JyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgICAgdS5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuSU5URUxMSUdFTlQpO1xuICAgICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgICBleHBlY3QobW9ja1B1dCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgICAgZXhwZWN0KG1vY2tDb21taXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGRlc2NyaWJlKCdGYWxsYmFjayBtb2RlJywgKCkgPT4ge1xuICAgICAgaXQoJ3Nob3VsZCBzd2l0Y2ggdG8gZmFsbGJhY2sgbW9kZSBpZiByZWd1bGFyIHVwbG9hZCBmYWlscycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QsXG4gICAgICAgICAgdXBsb2FkX3R5cGU6ICdpbnRlbGxpZ2VudF9pbmdlc3Rpb24nLFxuICAgICAgICB9KTtcblxuICAgICAgICBsZXQgbmV0d29ya0ZhaWwgPSB0cnVlO1xuICAgICAgICBub2NrLnJlbW92ZUludGVyY2VwdG9yKGludGVyY2VwdG9yUzMpO1xuICAgICAgICBzY29wZS5wdXQoJy9mYWtlczMnKS5yZXBseShcbiAgICAgICAgICBmdW5jdGlvbih1cmwsIF8sIGNiKSB7XG4gICAgICAgICAgICBpZiAobmV0d29ya0ZhaWwpIHtcbiAgICAgICAgICAgICAgbmV0d29ya0ZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmV0dXJuIGNiKCdFcnJvcicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYihudWxsLCBbMjAxLCBtb2NrUHV0KHVybCwgdGhpcy5yZXEuaGVhZGVycyksIHsgZXRhZzogJ3Rlc3QnfV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5GQUxMQkFDSyk7XG4gICAgICAgIHUuc2V0SW50ZWxsaWdlbnRDaHVua1NpemUoSU5URUxMSUdFTlRfQ0hVTktfU0laRSk7XG4gICAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgICBjb25zdCB0ZXN0RmlsZSA9IGdldFNtYWxsVGVzdEZpbGUoKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0TWV0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgwLCBERUZBVUxUX1BBUlRfU0laRSk7XG4gICAgICAgIGNvbnN0IGZpcnN0UGFydCA9IGF3YWl0IHRlc3RGaWxlLmdldFBhcnRCeU1ldGFkYXRhKGZpcnN0UGFydE1ldGEpO1xuXG4gICAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgxLCB7XG4gICAgICAgICAgbWQ1OiBmaXJzdFBhcnQubWQ1LFxuICAgICAgICAgIHNpemU6IGZpcnN0UGFydC5zaXplLFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoKDIsIHtcbiAgICAgICAgICBtZDU6IGZpcnN0UGFydC5tZDUsXG4gICAgICAgICAgc2l6ZTogZmlyc3RQYXJ0LnNpemUsXG4gICAgICAgICAgZmlpOiB0cnVlLFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgb2Zmc2V0OiAwLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgZXhpdCBpZiBpbnRlbGxpZ2VudCBpbmdlc3Rpb24gaXMgbm90IGVuYWJsZWQgaW4gYWNjb3VudCBzZXR0aW5ncycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBuZXR3b3JrRmFpbCA9IHRydWU7XG4gICAgICAgIGludGVyY2VwdG9yUzMucmVwbHkoXG4gICAgICAgICAgZnVuY3Rpb24odXJsLCBfLCBjYikge1xuICAgICAgICAgICAgaWYgKG5ldHdvcmtGYWlsKSB7XG4gICAgICAgICAgICAgIG5ldHdvcmtGYWlsID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJldHVybiBjYih7XG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0Nvbm5lY3Rpb25FcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ0VUSU1FRE9VVCcsXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYihudWxsLCBbMjAxLCBtb2NrUHV0KHVybCwgdGhpcy5yZXEuaGVhZGVycyksIHtldGFnOiAndGVzdCd9XSk7XG4gICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICAgIHUuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLkZBTExCQUNLKTtcbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuICAgICAgICBleHBlY3QobW9ja0NvbW1pdCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmVndWxhciB1cGxvYWQnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCB1cGxvYWQgZmlsZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcnRTaXplID0gMTAyNCAqIDEwMjQgKiA3O1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LnNldFBhcnRTaXplKHBhcnRTaXplKTtcbiAgICAgIHUuYWRkRmlsZShnZXRUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0VGVzdEZpbGUoKTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICBmaWxlbmFtZTogdGVzdEZpbGUubmFtZSxcbiAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICBzdG9yZToge1xuICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICB9LFxuICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgZmlyc3RQYXJ0TWV0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgwLCBwYXJ0U2l6ZSk7XG4gICAgICBjb25zdCBmaXJzdFBhcnQgPSBhd2FpdCB0ZXN0RmlsZS5nZXRQYXJ0QnlNZXRhZGF0YShmaXJzdFBhcnRNZXRhKTtcblxuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoKDEsIHtcbiAgICAgICAgbWQ1OiBmaXJzdFBhcnQubWQ1LFxuICAgICAgICBzaXplOiBmaXJzdFBhcnQuc2l6ZSxcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgcGFydDogMSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZWNvbmRQYXJ0TWV0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgxLCBwYXJ0U2l6ZSk7XG4gICAgICBjb25zdCBzZWNvbmRQYXJ0ID0gYXdhaXQgdGVzdEZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEoc2Vjb25kUGFydE1ldGEpO1xuXG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMiwge1xuICAgICAgICBtZDU6IHNlY29uZFBhcnQubWQ1LFxuICAgICAgICBzaXplOiBzZWNvbmRQYXJ0LnNpemUsXG4gICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICBzdG9yZToge1xuICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICB9LFxuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIHBhcnQ6IDIsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCcvZmFrZXMzJywgZXhwZWN0LmFueShPYmplY3QpKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICBmaWxlbmFtZTogdGVzdEZpbGUubmFtZSxcbiAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICBwYXJ0czogW3sgcGFydF9udW1iZXI6IDEsIGV0YWc6ICd0ZXN0JyB9LCB7IHBhcnRfbnVtYmVyOiAyLCBldGFnOiAndGVzdCcgfV0sXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHVwbG9hZCBmaWxlIHdpdGggZGlzYWJsZSBpbnRlZ3JpdHkgY2hlY2sgZW5hYmxlZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHBhcnRTaXplID0gMTAyNCAqIDEwMjQgKiA3O1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LnNldFBhcnRTaXplKHBhcnRTaXplKTtcbiAgICAgIHUuYWRkRmlsZShnZXRUZXN0RmlsZSgpKTtcbiAgICAgIHUuc2V0SW50ZWdyaXR5Q2hlY2soZmFsc2UpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgY29uc3QgdGVzdEZpbGUgPSBnZXRUZXN0RmlsZSgpO1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXJzdFBhcnRNZXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIHBhcnRTaXplKTtcbiAgICAgIGNvbnN0IGZpcnN0UGFydCA9IGF3YWl0IHRlc3RGaWxlLmdldFBhcnRCeU1ldGFkYXRhKGZpcnN0UGFydE1ldGEpO1xuXG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMSwge1xuICAgICAgICBzaXplOiBmaXJzdFBhcnQuc2l6ZSxcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgcGFydDogMSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzZWNvbmRQYXJ0TWV0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgxLCBwYXJ0U2l6ZSk7XG4gICAgICBjb25zdCBzZWNvbmRQYXJ0ID0gYXdhaXQgdGVzdEZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEoc2Vjb25kUGFydE1ldGEpO1xuXG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMiwge1xuICAgICAgICBzaXplOiBzZWNvbmRQYXJ0LnNpemUsXG4gICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICBzdG9yZToge1xuICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICB9LFxuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIHBhcnQ6IDIsXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCcvZmFrZXMzJywgZXhwZWN0LmFueShPYmplY3QpKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICBmaWxlbmFtZTogdGVzdEZpbGUubmFtZSxcbiAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICBwYXJ0czogW3sgcGFydF9udW1iZXI6IDEsIGV0YWc6ICd0ZXN0JyB9LCB7IHBhcnRfbnVtYmVyOiAyLCBldGFnOiAndGVzdCcgfV0sXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgfSk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCBwcm9jZXNzIHVwbG9hZCBvbiBtdWx0aXBhcnQvdXBsb2FkIG5ldHdvcmsgZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gICAgICBpbnRlcmNlcHRvclVwbG9hZC5yZXBseSg0MDAsIHtcbiAgICAgICAgbWVzc2FnZTogJ3NvbWV0aGluZyBhd2Z1bCBoYXBwZW5lZCcsXG4gICAgICAgIGNvZGU6ICdiYWRfcmVxdWVzdCcsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrUHV0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tDb21taXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IHJldHJ5IGNvbmZpZycsIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIHNpbXVsYXRlIGZpcnN0IHJlcXVlc3QgbmV0d29yayBmYWlsXG4gICAgICBsZXQgbmV0d29ya0ZhaWwgPSB0cnVlO1xuXG4gICAgICBub2NrLnJlbW92ZUludGVyY2VwdG9yKGludGVyY2VwdG9yUzMpO1xuICAgICAgc2NvcGUucGVyc2lzdChmYWxzZSk7XG5cbiAgICAgIHNjb3BlLnB1dCgnL2Zha2VzMycpLnR3aWNlKCkucmVwbHkoXG4gICAgICAgIGZ1bmN0aW9uKHVybCwgXywgY2IpIHtcbiAgICAgICAgICBpZiAobmV0d29ya0ZhaWwpIHtcbiAgICAgICAgICAgIG5ldHdvcmtGYWlsID0gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gY2IoRXJyb3IoJ2Vycm9yJykpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNiKG51bGwsIFsyMDEsIG1vY2tQdXQodXJsLCB0aGlzLnJlcS5oZWFkZXJzKSwgeyBldGFnOiAndGVzdCd9XSk7XG4gICAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcbiAgICAgIHUuc2V0UmV0cnlDb25maWcoe1xuICAgICAgICByZXRyeTogMSxcbiAgICAgICAgcmV0cnlGYWN0b3I6IDIsXG4gICAgICAgIHJldHJ5TWF4VGltZTogMTAsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ29tbW9uIG5ldHdvcmsgZXJyb3JzJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgbm90IHByb2Nlc3MgdXBsb2FkIG9uIHdyb25nIHN0YXJ0IHJlc3BvbnNlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXNldCgpO1xuICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgIHRlc3Q6IDEyMyxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCdGYWlsZWQnKTtcbiAgICAgIGV4cGVjdChtb2NrUHV0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja0NvbW1pdCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCBwcm9jZXNzIHVwbG9hZCBvbiBzdGFydCBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgICAgIGludGVyY2VwdG9yU3RhcnQucmVwbHkoNDAwLCB7XG4gICAgICAgIG1lc3NhZ2U6ICdzb21ldGhpbmcgYXdmdWwgaGFwcGVuZWQnLFxuICAgICAgICBjb2RlOiAnYmFkX3JlcXVlc3QnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuXG4gICAgICBleHBlY3QobW9ja1B1dCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tDb21taXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3IgcHJvY2VzcyB1cGxvYWQgb24gbXVsdGlwYXJ0L2NvbXBsZXRlIG5ldHdvcmsgZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gICAgICBpbnRlcmNlcHRvckNvbXBsZXRlLnJlcGx5KDQwMCwge1xuICAgICAgICBtZXNzYWdlOiAnc29tZXRoaW5nIGF3ZnVsIGhhcHBlbmVkJyxcbiAgICAgICAgY29kZTogJ2JhZF9yZXF1ZXN0JyxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCdGYWlsZWQnKTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tbWl0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19