filestack-js
Version:
Official JavaScript library for Filestack
1,199 lines • 154 kB
JavaScript
/*
* 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.
*/
import { __awaiter, __generator } from "tslib";
import { S3Uploader } from './s3';
import { File } from './../file';
import nock from 'nock';
import { DEFAULT_STORE_LOCATION, INTELLIGENT_CHUNK_SIZE, DEFAULT_PART_SIZE, INTELLIGENT_MOBILE_CHUNK_SIZE } from './abstract';
import * as utils from '../../../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({
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({
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({
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 = nock(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.cleanAll();
nock.enableNetConnect();
jest.clearAllMocks();
});
describe('Standart tests', function () {
it('should initialize class without errors', function () {
expect(function () {
var u = new S3Uploader({});
var uu = new S3Uploader({}, 10);
}).not.toThrowError();
});
it('should allow adding files', function () {
var u = new S3Uploader({});
u.addFile(getTestFile());
});
it('should not allow to set min part size lower than defined', function () {
var u = new S3Uploader({});
expect(function () { return u.setPartSize(10); }).toThrowError();
});
it('should throw an error when setting to small intelligent chunk size', function () {
var u = new 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 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 S3Uploader({});
return expect(u.getIntelligentChunkSize()).toEqual(INTELLIGENT_MOBILE_CHUNK_SIZE);
});
it('should allow to set part size on other mode thant regular', function () {
var u = new S3Uploader({});
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
var partSize = 1024 * 1024;
u.setPartSize(partSize);
expect(u.getPartSize()).toEqual(DEFAULT_PART_SIZE);
});
it('should retry complete request on 202 status code', function () { return __awaiter(void 0, void 0, void 0, function () {
var mock202, u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mock202 = jest
.fn()
.mockName('202 mock')
.mockReturnValue('');
nock.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 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 __awaiter(void 0, void 0, void 0, function () {
var storeOption, u;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
storeOption = {
container: 'test',
location: DEFAULT_STORE_LOCATION,
workflows: [{
id: 'test',
}],
};
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __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 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __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 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 __awaiter(void 0, void 0, void 0, function () {
var u;
return __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 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 __awaiter(void 0, void 0, void 0, function () {
var u, res, testFile, firstPartMetadata, firstPartChunk;
return __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 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, 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: 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new 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 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 __awaiter(void 0, void 0, void 0, function () {
var testSecurity, u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
testSecurity = {
policy: 'test_p',
signature: 'test_s',
};
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res, storageKeyExpect;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, tags, res, tagsExpected;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var chunkSize, u, res, testFile, firstPartOffset, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
chunkSize = 1024 * 1024;
u = new 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: DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
fii: true,
});
firstPartOffset = 0;
_a = testFile.getPartsCount(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: 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: DEFAULT_STORE_LOCATION,
},
});
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
region: mockRegion,
upload_id: mockUploadId,
store: {
location: DEFAULT_STORE_LOCATION,
},
fii: true,
uri: mockedUri,
});
return [2 /*return*/];
}
});
}); });
it('should upload file', function () { return __awaiter(void 0, void 0, void 0, function () {
var chunkSize, u, res, testFile, firstPartOffset, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
chunkSize = 1024 * 1024;
u = new 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: DEFAULT_STORE_LOCATION,
},
apikey: testApikey,
fii: true,
});
firstPartOffset = 0;
_a = testFile.getPartsCount(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: 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: DEFAULT_STORE_LOCATION,
},
});
expect(mockComplete).toHaveBeenCalledWith({
apikey: testApikey,
filename: testFile.name,
mimetype: testFile.mimetype,
size: testFile.size,
region: mockRegion,
upload_id: mockUploadId,
store: {
location: DEFAULT_STORE_LOCATION,
},
fii: true,
uri: mockedUri,
});
return [2 /*return*/];
}
});
}); });
it('should lower chunk size on network error', function () { return __awaiter(void 0, void 0, void 0, function () {
var putRequestTimeout, delayApplied, u, res, testFile, _a, partsCount, dynamicPartSize, firstPartMetadata, firstPartChunk, chunkSize, updatedFirstPartMetaData, chunk1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
putRequestTimeout = 300;
delayApplied = false;
nock.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 S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setTimeout(putRequestTimeout);
u.setUploadMode("intelligent" /* UploadMode.INTELLIGENT */);
u.setIntelligentChunkSize(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(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: DEFAULT_STORE_LOCATION,
},
uri: mockedUri,
upload_id: mockUploadId,
offset: 0,
part: 1,
});
chunkSize = testFile.getPartsCount(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: 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __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 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorUpload.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res, testFile, firstPartMeta, firstPart;
return __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.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 S3Uploader({});
u.setUrl(testHost);
u.setApikey(testApikey);
u.setUploadMode("fallback" /* UploadMode.FALLBACK */);
u.setIntelligentChunkSize(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, 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: 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: 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 __awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res;
return __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 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 __awaiter(void 0, void 0, void 0, function () {
var partSize, u, res, testFile, firstPartMeta, firstPart, secondPartMeta, secondPart;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
partSize = 1024 * 1024 * 7;
u = new 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: 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: 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: 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: 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 __awaiter(void 0, void 0, void 0, function () {
var partSize, u, res, testFile, firstPartMeta, firstPart, secondPartMeta, secondPart;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
partSize = 1024 * 1024 * 7;
u = new 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: 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: 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: 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: 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorUpload.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var networkFail, u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
networkFail = true;
nock.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 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStart.mockReset();
mockStart.mockReturnValue({
test: 123,
});
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorStart.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new 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 __awaiter(void 0, void 0, void 0, function () {
var u, res;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
interceptorComplete.reply(400, {
message: 'something awful happened',
code: 'bad_request',
});
u = new 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYXBpL3VwbG9hZC91cGxvYWRlcnMvczMuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7O0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNsQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQWMsc0JBQXNCLEVBQUUsc0JBQXNCLEVBQUUsaUJBQWlCLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDMUksT0FBTyxLQUFLLEtBQUssTUFBTSwyQkFBMkIsQ0FBQztBQUVuRCxJQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQztBQUN2QyxJQUFNLG1CQUFtQixHQUFHLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBQzVDLElBQUksUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDekUsSUFBSSxhQUFhLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLG1CQUFtQixDQUFDLENBQUM7QUFFeEYsSUFBSSxLQUFLLENBQUM7QUFDVixJQUFJLGFBQWEsQ0FBQztBQUNsQixJQUFJLGdCQUFnQixDQUFDO0FBQ3JCLElBQUksaUJBQWlCLENBQUM7QUFDdEIsSUFBSSxpQkFBaUIsQ0FBQztBQUN0QixJQUFJLG1CQUFtQixDQUFDO0FBRXhCLElBQU0sV0FBVyxHQUFHO0lBQ2xCLE9BQUEsSUFBSSxJQUFJLENBQUM7UUFDUCxLQUFLLEVBQUUsVUFBQyxLQUFLLEVBQUUsR0FBRyxJQUFLLE9BQUEsT0FBTyxDQUFDLE9BQU8s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QkFDN0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQzt3QkFDbkIsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQzt3QkFDeEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7d0JBRWxCLHFCQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBQTs7d0JBQXZCLEdBQUcsR0FBRyxTQUFpQjt3QkFFN0IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7d0JBRXhDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO3dCQUNyQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQzt3QkFDbkMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDOzs7O2FBQzNDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJmaWxlIjoibGliL2FwaS91cGxvYWQvdXBsb2FkZXJzL3MzLnNwZWMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE5IGJ5IEZpbGVzdGFjay5cbiAqIFNvbWUgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBTM1VwbG9hZGVyIH0gZnJvbSAnLi9zMyc7XG5pbXBvcnQgeyBGaWxlIH0gZnJvbSAnLi8uLi9maWxlJztcbmltcG9ydCBub2NrIGZyb20gJ25vY2snO1xuaW1wb3J0IHsgVXBsb2FkTW9kZSwgREVGQVVMVF9TVE9SRV9MT0NBVElPTiwgSU5URUxMSUdFTlRfQ0hVTktfU0laRSwgREVGQVVMVF9QQVJUX1NJWkUsIElOVEVMTElHRU5UX01PQklMRV9DSFVOS19TSVpFIH0gZnJvbSAnLi9hYnN0cmFjdCc7XG5pbXBvcnQgKiBhcyB1dGlscyBmcm9tICcuLi8uLi8uLi91dGlscy9pbmRleC5ub2RlJztcblxuY29uc3QgdGVzdEJ1ZmZlclNpemUgPSAxMDI0ICogMTAyNCAqIDk7XG5jb25zdCB0ZXN0U21hbGxCdWZmZXJTaXplID0gMTAyNCAqIDEwMjQgKiAyO1xubGV0IHRlc3RCdWZmID0gQnVmZmVyLmFsbG9jKHRlc3RCdWZmZXJTaXplKS5maWxsKCd0JywgMCwgdGVzdEJ1ZmZlclNpemUpO1xubGV0IHNtYWxsVGVzdEJ1ZmYgPSBCdWZmZXIuYWxsb2ModGVzdFNtYWxsQnVmZmVyU2l6ZSkuZmlsbCgndCcsIDAsIHRlc3RTbWFsbEJ1ZmZlclNpemUpO1xuXG5sZXQgc2NvcGU7XG5sZXQgaW50ZXJjZXB0b3JTMztcbmxldCBpbnRlcmNlcHRvclN0YXJ0O1xubGV0IGludGVyY2VwdG9yQ29tbWl0O1xubGV0IGludGVyY2VwdG9yVXBsb2FkO1xubGV0IGludGVyY2VwdG9yQ29tcGxldGU7XG5cbmNvbnN0IGdldFRlc3RGaWxlID0gKCkgPT5cbiAgbmV3IEZpbGUoe1xuICAgIHNsaWNlOiAoc3RhcnQsIGVuZCkgPT4gUHJvbWlzZS5yZXNvbHZlKHRlc3RCdWZmLnNsaWNlKHN0YXJ0LCBlbmQpKSxcbiAgICB0eXBlOiAndGV4dC9wbGFpbicsXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHNpemU6IHRlc3RCdWZmLmxlbmd0aCxcbiAgICBuYW1lOiAndGVzdC50eHQnLFxuICB9KTtcblxuY29uc3QgZ2V0U21hbGxUZXN0RmlsZSA9ICgpID0+XG4gIG5ldyBGaWxlKHtcbiAgICBzbGljZTogKHN0YXJ0LCBlbmQpID0+IFByb21pc2UucmVzb2x2ZSh0ZXN0QnVmZi5zbGljZShzdGFydCwgZW5kKSksXG4gICAgdHlwZTogJ3RleHQvcGxhaW4nLFxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBzaXplOiBzbWFsbFRlc3RCdWZmLmxlbmd0aCxcbiAgICBuYW1lOiAndGVzdC50eHQnLFxuICB9KTtcblxuY29uc3QgZ2V0TnVsbFNpemVGaWxlID0gKCkgPT5cbiAgbmV3IEZpbGUoe1xuICAgIHNsaWNlOiAoc3RhcnQsIGVuZCkgPT4gUHJvbWlzZS5yZXNvbHZlKHRlc3RCdWZmLnNsaWNlKHN0YXJ0LCBlbmQpKSxcbiAgICB0eXBlOiAndGV4dC9wbGFpbicsXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHNpemU6IDAsXG4gICAgbmFtZTogJ3Rlc3QudHh0JyxcbiAgfSk7XG5cbmNvbnN0IHRlc3RBcGlrZXkgPSAndGVzdGFwaWtleSc7XG5jb25zdCB0ZXN0SG9zdCA9ICdodHRwczovL2ZpbGVzdGFjay10ZXN0LmNvbSc7XG5jb25zdCBtb2NrVXBsb2FkSWQgPSAnMTIzMTMyMTIzJztcbmNvbnN0IG1vY2tSZWdpb24gPSAndGVzdC1yZWdpb24nO1xuY29uc3QgbW9ja2VkVXJpID0gJy9zb21ldGVzdCc7XG5jb25zdCBzM1VybCA9IHRlc3RIb3N0ICsgJy9mYWtlczMnO1xuXG5jb25zdCBtb2NrU3RhcnQgPSBqZXN0LmZuKCkubW9ja05hbWUoJ211bHRpcGFydC9zdGFydCcpO1xuY29uc3QgbW9ja1VwbG9hZCA9IGplc3QuZm4oKS5tb2NrTmFtZSgnbXVsdGlwYXJ0L3VwbG9hZCcpO1xuY29uc3QgbW9ja1B1dCA9IGplc3QuZm4oKS5tb2NrTmFtZSgnczMvcHV0Jyk7XG5jb25zdCBtb2NrQ29tbWl0ID0gamVzdC5mbigpLm1vY2tOYW1lKCdtdWx0aXBhcnQvY29tbWl0Jyk7XG5jb25zdCBtb2NrQ29tcGxldGUgPSBqZXN0LmZuKCkubW9ja05hbWUoJ211bHRpcGFydC9jb21wbGV0ZScpO1xuXG5jb25zdCBzM0NhbGxiYWNrID0gZnVuY3Rpb24odXJsKSB7XG4gIHJldHVybiBtb2NrUHV0KHVybCwgdGhpcy5yZXEuaGVhZGVycyk7XG59O1xuXG5kZXNjcmliZSgnQXBpL1VwbG9hZC9VcGxvYWRlcnMvUzMnLCAoKSA9PiB7XG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHNjb3BlID0gbm9jayh0ZXN0SG9zdCk7XG4gICAgLy8gc2NvcGUuZGVmYXVsdFJlcGx5SGVhZGVycyh7ICdhY2Nlc3MtY29udHJvbC1hbGxvdy1vcmlnaW4nOiAnKicsICdjb250ZW50LXR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gICAgc2NvcGUucGVyc2lzdCgpO1xuXG4gICAgaW50ZXJjZXB0b3JTdGFydCA9IHNjb3BlLnBvc3QoJy9tdWx0aXBhcnQvc3RhcnQnKTtcbiAgICBpbnRlcmNlcHRvclVwbG9hZCA9IHNjb3BlLnBvc3QoJy9tdWx0aXBhcnQvdXBsb2FkJyk7XG4gICAgaW50ZXJjZXB0b3JDb21taXQgPSBzY29wZS5wb3N0KCcvbXVsdGlwYXJ0L2NvbW1pdCcpO1xuICAgIGludGVyY2VwdG9yQ29tcGxldGUgPSBzY29wZS5wb3N0KCcvbXVsdGlwYXJ0L2NvbXBsZXRlJyk7XG4gICAgaW50ZXJjZXB0b3JTMyA9IHNjb3BlLnB1dCgnL2Zha2VzMycpO1xuXG4gICAgaW50ZXJjZXB0b3JTdGFydC5yZXBseSgyMDAsIChfLCBkYXRhKSA9PiBtb2NrU3RhcnQoZGF0YSkpO1xuICAgIGludGVyY2VwdG9yVXBsb2FkLnR3aWNlKCkucmVwbHkoMjAwLCAoXywgZGF0YSkgPT4gbW9ja1VwbG9hZChkYXRhKSk7XG4gICAgaW50ZXJjZXB0b3JDb21taXQucmVwbHkoMjAwLCAoXywgZGF0YSkgPT4gbW9ja0NvbW1pdChkYXRhKSk7XG4gICAgaW50ZXJjZXB0b3JDb21wbGV0ZS5yZXBseSgyMDAsIChfLCBkYXRhKSA9PiBtb2NrQ29tcGxldGUoZGF0YSkpO1xuICAgIGludGVyY2VwdG9yUzMudHdpY2UoKS5yZXBseSgyMDEsIHMzQ2FsbGJhY2ssIHsgZXRhZzogJ3Rlc3QnIH0pO1xuXG4gICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdCxcbiAgICB9KTtcblxuICAgIG1vY2tVcGxvYWQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgIHVybDogczNVcmwsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIHRlc3Q6ICd0ZXN0JyxcbiAgICAgIH0sXG4gICAgICBsb2NhdGlvbl91cmw6IHRlc3RIb3N0LFxuICAgIH0pO1xuXG4gICAgbW9ja1B1dC5tb2NrUmV0dXJuVmFsdWUoe30pO1xuICAgIG1vY2tDb21taXQubW9ja1JldHVyblZhbHVlKHt9KTtcblxuICAgIG1vY2tDb21wbGV0ZS5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgaGFuZGxlOiAndGVzdF9oYW5kbGUnLFxuICAgICAgdXJsOiAndGVzdF91cmwnLFxuICAgICAgZmlsZW5hbWU6ICd0ZXN0X2ZpbGVuYW1lJyxcbiAgICAgIHNpemU6IDEyMyxcbiAgICAgIG1pbWV0eXBlOiAndGVzdF9taW1ldHlwZScsXG4gICAgICBzdGF0dXM6ICd0ZXN0X3N0YXR1cycsXG4gICAgICB1cGxvYWRfdGFnczogeyB0ZXN0OiAxMjMgfSxcbiAgICB9KTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgbm9jay5lbmFibGVOZXRDb25uZWN0KCk7XG4gICAgamVzdC5jbGVhckFsbE1vY2tzKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTdGFuZGFydCB0ZXN0cycsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIGluaXRpYWxpemUgY2xhc3Mgd2l0aG91dCBlcnJvcnMnLCAoKSA9PiB7XG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICBjb25zdCB1dSA9IG5ldyBTM1VwbG9hZGVyKHt9LCAxMCk7XG4gICAgICB9KS5ub3QudG9UaHJvd0Vycm9yKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFsbG93IGFkZGluZyBmaWxlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0VGVzdEZpbGUoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vdCBhbGxvdyB0byBzZXQgbWluIHBhcnQgc2l6ZSBsb3dlciB0aGFuIGRlZmluZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgZXhwZWN0KCgpID0+IHUuc2V0UGFydFNpemUoMTApKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3Igd2hlbiBzZXR0aW5nIHRvIHNtYWxsIGludGVsbGlnZW50IGNodW5rIHNpemUnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgZXhwZWN0KCgpID0+IHUuc2V0SW50ZWxsaWdlbnRDaHVua1NpemUoMTApKS50b1Rocm93RXJyb3IoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3Igd2hlbiB0cnlpbmcgdG8gZ2V0IGhvc3Qgd2hlbiBpdCBpcyB1bmRlZmluZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgZXhwZWN0KCgpID0+IHUuZ2V0VXJsKCkpLnRvVGhyb3dFcnJvcigpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZXQgaW50ZWxsaWdlbnQgbW9iaWxlIGNodW5rIHNpemUgb24gbW9iaWxlIGRldmljZXMnLCAoKSA9PiB7XG4gICAgICBqZXN0LnNweU9uKHV0aWxzLCAnaXNNb2JpbGUnKS5tb2NrUmV0dXJuVmFsdWUodHJ1ZSk7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgcmV0dXJuIGV4cGVjdCh1LmdldEludGVsbGlnZW50Q2h1bmtTaXplKCkpLnRvRXF1YWwoSU5URUxMSUdFTlRfTU9CSUxFX0NIVU5LX1NJWkUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhbGxvdyB0byBzZXQgcGFydCBzaXplIG9uIG90aGVyIG1vZGUgdGhhbnQgcmVndWxhcicsICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG5cbiAgICAgIGNvbnN0IHBhcnRTaXplID0gMTAyNCAqIDEwMjQ7XG4gICAgICB1LnNldFBhcnRTaXplKHBhcnRTaXplKTtcblxuICAgICAgZXhwZWN0KHUuZ2V0UGFydFNpemUoKSkudG9FcXVhbChERUZBVUxUX1BBUlRfU0laRSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHJ5IGNvbXBsZXRlIHJlcXVlc3Qgb24gMjAyIHN0YXR1cyBjb2RlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbW9jazIwMiA9IGplc3RcbiAgICAgICAgLmZuKClcbiAgICAgICAgLm1vY2tOYW1lKCcyMDIgbW9jaycpXG4gICAgICAgIC5tb2NrUmV0dXJuVmFsdWUoJycpO1xuXG4gICAgICBub2NrLnJlbW92ZUludGVyY2VwdG9yKGludGVyY2VwdG9yQ29tcGxldGUpO1xuICAgICAgc2NvcGUucGVyc2lzdChmYWxzZSk7XG4gICAgICBzY29wZS5wb3N0KCcvbXVsdGlwYXJ0L2NvbXBsZXRlJykucmVwbHkoMjAyLCAoKSA9PiBtb2NrMjAyKCkpO1xuICAgICAgc2NvcGUucG9zdCgnL211bHRpcGFydC9jb21wbGV0ZScpLnJlcGx5KDIwMCwgKF8sIGRhdGEpID0+IG1vY2tDb21wbGV0ZShkYXRhKSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrMjAyKS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMSk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgcHJvdmlkZWQgc3RvcmUgb3B0aW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHN0b3JlT3B0aW9uID0ge1xuICAgICAgICBjb250YWluZXI6ICd0ZXN0JyxcbiAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIHdvcmtmbG93czogW3tcbiAgICAgICAgICBpZDogJ3Rlc3QnLFxuICAgICAgICB9XSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcihzdG9yZU9wdGlvbik7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgc3RvcmU6IHN0b3JlT3B0aW9uIH0pKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHsgc3RvcmU6IHN0b3JlT3B0aW9uIH0pKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYWRkIGh0dHBzIHByb3RvY29sIHRvIGxvY2F0aW9uX3VybCcsIGFzeW5jICgpID0+IHtcbiAgICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdC5yZXBsYWNlKCdodHRwczovLycsICcnKSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrUHV0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIG9uIGZpbGUgc2l6ZSAwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICBsb2NhdGlvbl91cmw6IHRlc3RIb3N0LnJlcGxhY2UoJ2h0dHBzOi8vJywgJycpLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXROdWxsU2l6ZUZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBvbiB3cm9uZyBldGFnIGZpZWxkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICBsb2NhdGlvbl91cmw6IHRlc3RIb3N0LnJlcGxhY2UoJ2h0dHBzOi8vJywgJycpLFxuICAgICAgfSk7XG5cbiAgICAgIGludGVyY2VwdG9yUzMub25jZSgpLnJlcGx5KDIwMCwgczNDYWxsYmFjaywge30pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuXG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICB1Lm9uKCdlcnJvcicsIChlcnIpID0+IHtcbiAgICAgICAgZXhwZWN0KGVyci5tZXNzYWdlKS50b0VxdWFsKCdDYW5ub3QgdXBsb2FkIGZpbGUsIGNoZWNrIFMzIGJ1Y2tldCBzZXR0aW5ncycpO1xuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHUuZXhlY3V0ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBhZGQgRmlsZXN0YWNrLVVwbG9hZC1SZWdpb24gaGVhZGVyIG9uIGxvY2F0aW9uX3JlZ2lvbiBwYXJhbScsIGFzeW5jICgpID0+IHtcbiAgICAgIG1vY2tTdGFydC5tb2NrUmV0dXJuVmFsdWUoe1xuICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgbG9jYXRpb25fcmVnaW9uOiAndGVzdCcsXG4gICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QucmVwbGFjZSgnaHR0cHM6Ly8nLCAnJyksXG4gICAgICB9KTtcblxuICAgICAgaW50ZXJjZXB0b3JVcGxvYWQucmVwbHkoMjAwLCBmdW5jdGlvbihfLCBkYXRhKSB7XG4gICAgICAgIHJldHVybiBtb2NrVXBsb2FkKGRhdGEsIHRoaXMucmVxLmhlYWRlcnMpO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgY29uc3QgdGVzdEZpbGUgPSBnZXRTbWFsbFRlc3RGaWxlKCk7XG5cbiAgICAgIGNvbnN0IGZpcnN0UGFydE1ldGFkYXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIERFRkFVTFRfUEFSVF9TSVpFKTtcbiAgICAgIGNvbnN0IGZpcnN0UGFydENodW5rID0gYXdhaXQgdGVzdEZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YWRhdGEpO1xuXG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoXG4gICAgICAgIHtcbiAgICAgICAgICBtZDU6IGZpcnN0UGFydENodW5rLm1kNSxcbiAgICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSxcbiAgICAgICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoeyAnZmlsZXN0YWNrLXVwbG9hZC1yZWdpb24nOiAndGVzdCcgfSlcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChtb2NrUHV0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgcGF1c2UoKSBhbmQgcmVzdW1lKCkgY29tbWFuZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRUZXN0RmlsZSgpKTtcblxuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHUucGF1c2UoKSk7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHUucmVzdW1lKCksIDEwKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgYWJvcnQoKSBjb21tYW5kJywgKGRvbmUpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRUZXN0RmlsZSgpKTtcblxuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHUuYWJvcnQoKSk7XG4gICAgICB1LmV4ZWN1dGUoKS50aGVuKChyZXMpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KS5jYXRjaCgoKSA9PiB7XG4gICAgICAgIGRvbmUoJ0V4ZWN1dGlvbiBmYWlsZWQnKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBzZW5kIGNvcnJlY3Qgc2VjdXJpdHknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0U2VjdXJpdHkgPSB7XG4gICAgICAgIHBvbGljeTogJ3Rlc3RfcCcsXG4gICAgICAgIHNpZ25hdHVyZTogJ3Rlc3RfcycsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LnNldFNlY3VyaXR5KHRlc3RTZWN1cml0eSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcodGVzdFNlY3VyaXR5KSk7XG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcodGVzdFNlY3VyaXR5KSk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyh0ZXN0U2VjdXJpdHkpKTtcblxuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZXNwZWN0IGRpc2FibGVTdG9yYWdlS2V5IG9wdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7XG4gICAgICAgIGRpc2FibGVTdG9yYWdlS2V5OiB0cnVlLFxuICAgICAgICBwYXRoOiAnL3Rlc3QvJyxcbiAgICAgIH0pO1xuXG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICBjb25zdCBzdG9yYWdlS2V5RXhwZWN0ID0ge1xuICAgICAgICBzdG9yZToge1xuICAgICAgICAgIGxvY2F0aW9uOiAnczMnLFxuICAgICAgICAgIHBhdGg6ICcvdGVzdC90ZXN0LnR4dCcsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyhzdG9yYWdlS2V5RXhwZWN0KSk7XG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuXG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgZGlzYWJsZVN0b3JhZ2VLZXkgb3B0aW9uIHdoZW4gcGF0aCBpcyBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHtcbiAgICAgICAgZGlzYWJsZVN0b3JhZ2VLZXk6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcblxuICAgICAgY29uc3Qgc3RvcmFnZUtleUV4cGVjdCA9IHtcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogJ3MzJyxcbiAgICAgICAgICBwYXRoOiAnL3Rlc3QudHh0JyxcbiAgICAgICAgfSxcbiAgICAgIH07XG5cbiAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKGV4cGVjdC5vYmplY3RDb250YWluaW5nKHN0b3JhZ2VLZXlFeHBlY3QpKTtcbiAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyhzdG9yYWdlS2V5RXhwZWN0KSk7XG4gICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyhzdG9yYWdlS2V5RXhwZWN0KSk7XG5cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVzcGVjdCBkaXNhYmxlU3RvcmFnZUtleSBvcHRpb24gd2hlbiBwYXRoIGhhcyBtaXNzaW5nIC8nLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe1xuICAgICAgICBkaXNhYmxlU3RvcmFnZUtleTogdHJ1ZSxcbiAgICAgICAgcGF0aDogJy90ZXN0JyxcbiAgICAgIH0pO1xuXG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICBjb25zdCBzdG9yYWdlS2V5RXhwZWN0ID0ge1xuICAgICAgICBzdG9yZToge1xuICAgICAgICAgIGxvY2F0aW9uOiAnczMnLFxuICAgICAgICAgIHBhdGg6ICcvdGVzdC90ZXN0LnR4dCcsXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aChleHBlY3Qub2JqZWN0Q29udGFpbmluZyhzdG9yYWdlS2V5RXhwZWN0KSk7XG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoc3RvcmFnZUtleUV4cGVjdCkpO1xuICAgIH0pO1xuXG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUYWdzJywgKCkgPT4ge1xuICAgIGl0KCdNYWtlIGNvcnJlY3QgcmVxdWVzdCB3aXRoIHVwbG9hZCB0YWdzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHtcbiAgICAgICAgZGlzYWJsZVN0b3JhZ2VLZXk6IHRydWUsXG4gICAgICAgIHBhdGg6ICcvdGVzdCcsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGFncyA9IHtcbiAgICAgICAgdGVzdDogJzEyMycsXG4gICAgICAgIHRlc3QyOiAndGVzdCcsXG4gICAgICB9O1xuXG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuICAgICAgdS5zZXRVcGxvYWRUYWdzKHRhZ3MpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICBjb25zdCB0YWdzRXhwZWN0ZWQgPSB7XG4gICAgICAgIHVwbG9hZF90YWdzOiB0YWdzLFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KHJlc1swXS51cGxvYWRUYWdzKS50b0VxdWFsKHsgdGVzdDogMTIzIH0pO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcodGFnc0V4cGVjdGVkKSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdVcGxvYWQgbW9kZXMnLCAoKSA9PiB7XG4gICAgZGVzY3JpYmUoJ0ludGVsbGlnZW50IGluZ2Vzc2lvbicsICgpID0+IHtcbiAgICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdCxcbiAgICAgICAgICB1cGxvYWRfdHlwZTogJ2ludGVsbGlnZW50X2luZ2VzdGlvbicsXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgdXBsb2FkIGZpbGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNodW5rU2l6ZSA9IDEwMjQgKiAxMDI0O1xuXG4gICAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICAgIHUuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLklOVEVMTElHRU5UKTtcbiAgICAgICAgdS5zZXRJbnRlbGxpZ2VudENodW5rU2l6ZShjaHVua1NpemUpO1xuICAgICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcbiAgICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG5cbiAgICAgICAgY29uc3QgdGVzdEZpbGUgPSBnZXRTbWFsbFRlc3RGaWxlKCk7XG4gICAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICBmaWxlbmFtZTogdGVzdEZpbGUubmFtZSxcbiAgICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgZmlpOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBmaXJzdFBhcnRPZmZzZXQgPSAwO1xuICAgICAgICBjb25zdCB7IHBhcnRzQ291bnQsIGNodW5rU2l6ZTogZHluYW1pY1BhcnRTaXplIH0gPSB0ZXN0RmlsZS5nZXRQYXJ0c0NvdW50KElOVEVMTElHRU5UX0NIVU5LX1NJWkUsIHRydWUpO1xuICAgICAgICBjb25zdCBmaXJzdFBhcnRNZXRhZGF0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgwLCBkeW5hbWljUGFydFNpemUpO1xuICAgICAgICBjb25zdCBmaXJzdFBhcnRDaHVuayA9IGF3YWl0IHRlc3RGaWxlLmdldENodW5rQnlNZXRhZGF0YShmaXJzdFBhcnRNZXRhZGF0YSwgZmlyc3RQYXJ0T2Zmc2V0LCBkeW5hbWljUGFydFNpemUpO1xuXG4gICAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgbWQ1OiBmaXJzdFBhcnRDaHVuay5tZDUsXG4gICAgICAgICAgc2l6ZTogZmlyc3RQYXJ0Q2h1bmsuc2l6ZSxcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIG9mZnNldDogZmlyc3RQYXJ0T2Zmc2V0LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgICBwYXJ0OiAxLFxuICAgICAgICB9KTtcblxuICAgICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJy9mYWtlczMnLCBleHBlY3QuYW55KE9iamVjdCkpO1xuXG4gICAgICAgIGV4cGVjdChtb2NrUHV0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCgnL2Zha2VzMycsIGV4cGVjdC5hbnkoT2JqZWN0KSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tDb21taXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgICBzaXplOiB0ZXN0RmlsZS5zaXplLFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICBmaWxlbmFtZTogdGVzdEZpbGUubmFtZSxcbiAgICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZmlpOiB0cnVlLFxuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHVwbG9hZCBmaWxlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBjaHVua1NpemUgPSAxMDI0ICogMTAyNDtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG4gICAgICAgIHUuc2V0SW50ZWxsaWdlbnRDaHVua1NpemUoY2h1bmtTaXplKTtcbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG4gICAgICAgIGV4cGVjdChyZXNbMF0uaGFuZGxlKS50b0VxdWFsKCd0ZXN0X2hhbmRsZScpO1xuXG4gICAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0U21hbGxUZXN0RmlsZSgpO1xuICAgICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgZmlsZW5hbWU6IHRlc3RGaWxlLm5hbWUsXG4gICAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0T2Zmc2V0ID0gMDtcbiAgICAgICAgY29uc3QgeyBwYXJ0c0NvdW50LCBjaHVua1NpemU6IGR5bmFtaWNQYXJ0U2l6ZSB9ID0gdGVzdEZpbGUuZ2V0UGFydHNDb3VudChJTlRFTExJR0VOVF9DSFVOS19TSVpFLCB0cnVlKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0TWV0YWRhdGEgPSB0ZXN0RmlsZS5nZXRQYXJ0TWV0YWRhdGEoMCwgZHluYW1pY1BhcnRTaXplKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0Q2h1bmsgPSBhd2FpdCB0ZXN0RmlsZS5nZXRDaHVua0J5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YWRhdGEsIGZpcnN0UGFydE9mZnNldCwgZHluYW1pY1BhcnRTaXplKTtcblxuICAgICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICAgIG1kNTogZmlyc3RQYXJ0Q2h1bmsubWQ1LFxuICAgICAgICAgIHNpemU6IGZpcnN0UGFydENodW5rLnNpemUsXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBvZmZzZXQ6IGZpcnN0UGFydE9mZnNldCxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tQdXQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKCcvZmFrZXMzJywgZXhwZWN0LmFueShPYmplY3QpKTtcblxuICAgICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJy9mYWtlczMnLCBleHBlY3QuYW55KE9iamVjdCkpO1xuXG4gICAgICAgIGV4cGVjdChtb2NrQ29tbWl0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHBhcnQ6IDEsXG4gICAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICAgIGxvY2F0aW9uOiBERUZBVUxUX1NUT1JFX0xPQ0FUSU9OLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgZmlsZW5hbWU6IHRlc3RGaWxlLm5hbWUsXG4gICAgICAgICAgbWltZXR5cGU6IHRlc3RGaWxlLm1pbWV0eXBlLFxuICAgICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBsb3dlciBjaHVuayBzaXplIG9uIG5ldHdvcmsgZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHB1dFJlcXVlc3RUaW1lb3V0ID0gMzAwO1xuICAgICAgICBsZXQgZGVsYXlBcHBsaWVkID0gZmFsc2U7XG5cbiAgICAgICAgbm9jay5yZW1vdmVJbnRlcmNlcHRvcihpbnRlcmNlcHRvclMzKTtcbiAgICAgICAgc2NvcGUucHV0KCcvZmFrZXMzJykucmVwbHkoXG4gICAgICAgICAgZnVuY3Rpb24odXJsLCBfLCBjYikge1xuICAgICAgICAgICAgaWYgKCFkZWxheUFwcGxpZWQpIHtcbiAgICAgICAgICAgICAgZGVsYXlBcHBsaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2IoNTA0KTtcbiAgICAgICAgICAgICAgfSwgMzAwMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjYihudWxsLCBbMjAxLCBtb2NrUHV0KHVybCwgdGhpcy5yZXEuaGVhZGVycyksIHtldGFnOiAndGVzdCd9XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICAgIHUuc2V0VGltZW91dChwdXRSZXF1ZXN0VGltZW91dCk7XG4gICAgICAgIHUuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLklOVEVMTElHRU5UKTtcbiAgICAgICAgdS5zZXRJbnRlbGxpZ2VudENodW5rU2l6ZShJTlRFTExJR0VOVF9DSFVOS19TSVpFKTtcblxuICAgICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG4gICAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0U21hbGxUZXN0RmlsZSgpO1xuICAgICAgICBjb25zdCB7IHBhcnRzQ291bnQsIGNodW5rU2l6ZTogZHluYW1pY1BhcnRTaXplIH0gPSB0ZXN0RmlsZS5nZXRQYXJ0c0NvdW50KElOVEVMTElHRU5UX0NIVU5LX1NJWkUsIHRydWUpO1xuICAgICAgICBjb25zdCBmaXJzdFBhcnRNZXRhZGF0YSA9IHRlc3RGaWxlLmdldFBhcnRNZXRhZGF0YSgwLCBkeW5hbWljUGFydFNpemUpO1xuICAgICAgICBjb25zdCBmaXJzdFBhcnRDaHVuayA9IGF3YWl0IHRlc3RGaWxlLmdldENodW5rQnlNZXRhZGF0YShmaXJzdFBhcnRNZXRhZGF0YSwgMCwgZHluYW1pY1BhcnRTaXplKTtcblxuICAgICAgICAvLyB0aGlzIHJlcXVlc3Qgd2lsbCBiZSBhYm9ydGVkIGJ1dCBjYWxsZWQgb24gbW9jayB1cGxvYWRcbiAgICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoKDEsIHtcbiAgICAgICAgICBtZDU6IGZpcnN0UGFydENodW5rLm1kNSxcbiAgICAgICAgICBzaXplOiBmaXJzdFBhcnRDaHVuay5zaXplLFxuICAgICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgZmlpOiB0cnVlLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIG9mZnNldDogMCxcbiAgICAgICAgICBwYXJ0OiAxLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBzcGxpdCBwYXJ0IHNpemUgYnkgYSBoYWxmIGFuZCByZXRyeSByZXF1ZXN0ICh0aGF0cyBnaXZlIHVzIDIgY2h1bmtzIHNvIDIgdXBsb2FkIHJlcXVlc3RzIG5lZWRlZClcbiAgICAgICAgbGV0IHsgY2h1bmtTaXplIH0gPSB0ZXN0RmlsZS5nZXRQYXJ0c0NvdW50KElOVEVMTElHRU5UX0NIVU5LX1NJWkUsIHRydWUpO1xuICAgICAgICBjaHVua1NpemUgPSBjaHVua1NpemUgLyAyO1xuICAgICAgICBjb25zdCB1cGRhdGVkRmlyc3RQYXJ0TWV0YURhdGEgPSB0ZXN0RmlsZS5nZXRQYXJ0TWV0YWRhdGEoMCwgY2h1bmtTaXplKTtcbiAgICAgICAgY29uc3QgY2h1bmsxID0gYXdhaXQgdGVzdEZpbGUuZ2V0Q2h1bmtCeU1ldGFkYXRhKHVwZGF0ZWRGaXJzdFBhcnRNZXRhRGF0YSwgMCwgY2h1bmtTaXplKTtcblxuICAgICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMiwge1xuICAgICAgICAgIG1kNTogY2h1bmsxLm1kNSxcbiAgICAgICAgICBzaXplOiBjaHVuazEuc2l6ZSxcbiAgICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZpaTogdHJ1ZSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG5cbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGV4aXQgb24gNHh4IGVycm9ycycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbW9ja1N0YXJ0Lm1vY2tSZXR1cm5WYWx1ZSh7XG4gICAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICAgIGxvY2F0aW9uX3VybDogdGVzdEhvc3QsXG4gICAgICAgICAgdXBsb2FkX3R5cGU6ICdpbnRlbGxpZ2VudF9pbmdlc3Rpb24nLFxuICAgICAgICB9KTtcblxuICAgICAgICBpbnRlcmNlcHRvclMzLnJlcGx5KDQwMCwge1xuICAgICAgICAgIG1lc3NhZ2U6ICdzb21ldGhpbmcgYXdmdWwgaGFwcGVuZWQnLFxuICAgICAgICAgIGNvZGU6ICdiYWRfcmVxdWVzdCcsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICAgIHUuc2V0VGltZW91dCgxMDApO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG5cbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuICAgICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBub3IgcHJvY2VzcyB1cGxvYWQgb24gbXVsdGlwYXJ0L3VwbG9hZCBuZXR3b3JrIGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBpbnRlcmNlcHRvclVwbG9hZC5yZXBseSg0MDAsIHtcbiAgICAgICAgICBtZXNzYWdlOiAnc29tZXRoaW5nIGF3ZnVsIGhhcHBlbmVkJyxcbiAgICAgICAgICBjb2RlOiAnYmFkX3JlcXVlc3QnLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgICB1LnNldFVwbG9hZE1vZGUoVXBsb2FkTW9kZS5JTlRFTExJR0VOVCk7XG4gICAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCdGYWlsZWQnKTtcblxuICAgICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICAgIGV4cGVjdChtb2NrUHV0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgICBleHBlY3QobW9ja0NvbW1pdCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ0ZhbGxiYWNrIG1vZGUnLCAoKSA9PiB7XG4gICAgICBpdCgnc2hvdWxkIHN3aXRjaCB0byBmYWxsYmFjayBtb2RlIGlmIHJlZ3VsYXIgdXBsb2FkIGZhaWxzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdCxcbiAgICAgICAgICB1cGxvYWRfdHlwZTogJ2ludGVsbGlnZW50X2luZ2VzdGlvbicsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBuZXR3b3JrRmFpbCA9IHRydWU7XG4gICAgICAgIG5vY2sucmVtb3ZlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3JTMyk7XG4gICAgICAgIHNjb3BlLnB1dCgnL2Zha2VzMycpLnJlcGx5KFxuICAgICAgICAgIGZ1bmN0aW9uKHVybCwgXywgY2IpIHtcbiAgICAgICAgICAgIGlmIChuZXR3b3JrRmFpbCkge1xuICAgICAgICAgICAgICBuZXR3b3JrRmFpbCA9IGZhbHNlO1xuICAgICAgICAgICAgICByZXR1cm4gY2IoJ0Vycm9yJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNiKG51bGwsIFsyMDEsIG1vY2tQdXQodXJsLCB0aGlzLnJlcS5oZWFkZXJzKSwgeyBldGFnOiAndGVzdCd9XSk7XG4gICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICAgIHUuc2V0VXBsb2FkTW9kZShVcGxvYWRNb2RlLkZBTExCQUNLKTtcbiAgICAgICAgdS5zZXRJbnRlbGxpZ2VudENodW5rU2l6ZShJTlRFTExJR0VOVF9DSFVOS19TSVpFKTtcbiAgICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG4gICAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCd0ZXN0X3N0YXR1cycpO1xuXG4gICAgICAgIGNvbnN0IHRlc3RGaWxlID0gZ2V0U21hbGxUZXN0RmlsZSgpO1xuICAgICAgICBjb25zdCBmaXJzdFBhcnRNZXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIERFRkFVTFRfUEFSVF9TSVpFKTtcbiAgICAgICAgY29uc3QgZmlyc3RQYXJ0ID0gYXdhaXQgdGVzdEZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YSk7XG5cbiAgICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLnRvSGF2ZUJlZW5OdGhDYWxsZWRXaXRoKDEsIHtcbiAgICAgICAgICBtZDU6IGZpcnN0UGFydC5tZDUsXG4gICAgICAgICAgc2l6ZTogZmlyc3RQYXJ0LnNpemUsXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgICBwYXJ0OiAxLFxuICAgICAgICB9KTtcblxuICAgICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMiwge1xuICAgICAgICAgIG1kNTogZmlyc3RQYXJ0Lm1kNSxcbiAgICAgICAgICBzaXplOiBmaXJzdFBhcnQuc2l6ZSxcbiAgICAgICAgICBmaWk6IHRydWUsXG4gICAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgICBzdG9yZToge1xuICAgICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICBvZmZzZXQ6IDAsXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgcGFydDogMSxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBleGl0IGlmIGludGVsbGlnZW50IGluZ2VzdGlvbiBpcyBub3QgZW5hYmxlZCBpbiBhY2NvdW50IHNldHRpbmdzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgICB1cmk6IG1vY2tlZFVyaSxcbiAgICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgICAgdXBsb2FkX2lkOiBtb2NrVXBsb2FkSWQsXG4gICAgICAgICAgbG9jYXRpb25fdXJsOiB0ZXN0SG9zdCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IG5ldHdvcmtGYWlsID0gdHJ1ZTtcbiAgICAgICAgaW50ZXJjZXB0b3JTMy5yZXBseShcbiAgICAgICAgICBmdW5jdGlvbih1cmwsIF8sIGNiKSB7XG4gICAgICAgICAgICBpZiAobmV0d29ya0ZhaWwpIHtcbiAgICAgICAgICAgICAgbmV0d29ya0ZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgICAgcmV0dXJuIGNiKHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiAnQ29ubmVjdGlvbkVycm9yJyxcbiAgICAgICAgICAgICAgICBjb2RlOiAnRVRJTUVET1VUJyxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNiKG51bGwsIFsyMDEsIG1vY2tQdXQodXJsLCB0aGlzLnJlcS5oZWFkZXJzKSwge2V0YWc6ICd0ZXN0J31dKTtcbiAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgICAgdS5zZXRVcGxvYWRNb2RlKFVwbG9hZE1vZGUuRkFMTEJBQ0spO1xuICAgICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG4gICAgICAgIGV4cGVjdChtb2NrQ29tbWl0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgICBleHBlY3QobW9ja0NvbXBsZXRlKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdSZWd1bGFyIHVwbG9hZCcsICgpID0+IHtcbiAgICBpdCgnc2hvdWxkIHVwbG9hZCBmaWxlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGFydFNpemUgPSAxMDI0ICogMTAyNCAqIDc7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuc2V0UGFydFNpemUocGFydFNpemUpO1xuICAgICAgdS5hZGRGaWxlKGdldFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgY29uc3QgdGVzdEZpbGUgPSBnZXRUZXN0RmlsZSgpO1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkV2l0aCh7XG4gICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIGFwaWtleTogdGVzdEFwaWtleSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBmaXJzdFBhcnRNZXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDAsIHBhcnRTaXplKTtcbiAgICAgIGNvbnN0IGZpcnN0UGFydCA9IGF3YWl0IHRlc3RGaWxlLmdldFBhcnRCeU1ldGFkYXRhKGZpcnN0UGFydE1ldGEpO1xuXG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkudG9IYXZlQmVlbk50aENhbGxlZFdpdGgoMSwge1xuICAgICAgICBtZDU6IGZpcnN0UGFydC5tZDUsXG4gICAgICAgIHNpemU6IGZpcnN0UGFydC5zaXplLFxuICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgfSxcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICBwYXJ0OiAxLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNlY29uZFBhcnRNZXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDEsIHBhcnRTaXplKTtcbiAgICAgIGNvbnN0IHNlY29uZFBhcnQgPSBhd2FpdCB0ZXN0RmlsZS5nZXRQYXJ0QnlNZXRhZGF0YShzZWNvbmRQYXJ0TWV0YSk7XG5cbiAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgyLCB7XG4gICAgICAgIG1kNTogc2Vjb25kUGFydC5tZDUsXG4gICAgICAgIHNpemU6IHNlY29uZFBhcnQuc2l6ZSxcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgcGFydDogMixcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJy9mYWtlczMnLCBleHBlY3QuYW55KE9iamVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgIHBhcnRzOiBbeyBwYXJ0X251bWJlcjogMSwgZXRhZzogJ3Rlc3QnIH0sIHsgcGFydF9udW1iZXI6IDIsIGV0YWc6ICd0ZXN0JyB9XSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgfSxcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdXBsb2FkIGZpbGUgd2l0aCBkaXNhYmxlIGludGVncml0eSBjaGVjayBlbmFibGVkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcGFydFNpemUgPSAxMDI0ICogMTAyNCAqIDc7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuc2V0UGFydFNpemUocGFydFNpemUpO1xuICAgICAgdS5hZGRGaWxlKGdldFRlc3RGaWxlKCkpO1xuICAgICAgdS5zZXRJbnRlZ3JpdHlDaGVjayhmYWxzZSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBjb25zdCB0ZXN0RmlsZSA9IGdldFRlc3RGaWxlKCk7XG5cbiAgICAgIGV4cGVjdChtb2NrU3RhcnQpLnRvSGF2ZUJlZW5DYWxsZWRXaXRoKHtcbiAgICAgICAgZmlsZW5hbWU6IHRlc3RGaWxlLm5hbWUsXG4gICAgICAgIG1pbWV0eXBlOiB0ZXN0RmlsZS5taW1ldHlwZSxcbiAgICAgICAgc2l6ZTogdGVzdEZpbGUuc2l6ZSxcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgfSxcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGZpcnN0UGFydE1ldGEgPSB0ZXN0RmlsZS5nZXRQYXJ0TWV0YWRhdGEoMCwgcGFydFNpemUpO1xuICAgICAgY29uc3QgZmlyc3RQYXJ0ID0gYXdhaXQgdGVzdEZpbGUuZ2V0UGFydEJ5TWV0YWRhdGEoZmlyc3RQYXJ0TWV0YSk7XG5cbiAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgxLCB7XG4gICAgICAgIHNpemU6IGZpcnN0UGFydC5zaXplLFxuICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgIHJlZ2lvbjogbW9ja1JlZ2lvbixcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgfSxcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICAgIHVwbG9hZF9pZDogbW9ja1VwbG9hZElkLFxuICAgICAgICBwYXJ0OiAxLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNlY29uZFBhcnRNZXRhID0gdGVzdEZpbGUuZ2V0UGFydE1ldGFkYXRhKDEsIHBhcnRTaXplKTtcbiAgICAgIGNvbnN0IHNlY29uZFBhcnQgPSBhd2FpdCB0ZXN0RmlsZS5nZXRQYXJ0QnlNZXRhZGF0YShzZWNvbmRQYXJ0TWV0YSk7XG5cbiAgICAgIGV4cGVjdChtb2NrVXBsb2FkKS50b0hhdmVCZWVuTnRoQ2FsbGVkV2l0aCgyLCB7XG4gICAgICAgIHNpemU6IHNlY29uZFBhcnQuc2l6ZSxcbiAgICAgICAgYXBpa2V5OiB0ZXN0QXBpa2V5LFxuICAgICAgICByZWdpb246IG1vY2tSZWdpb24sXG4gICAgICAgIHN0b3JlOiB7XG4gICAgICAgICAgbG9jYXRpb246IERFRkFVTFRfU1RPUkVfTE9DQVRJT04sXG4gICAgICAgIH0sXG4gICAgICAgIHVyaTogbW9ja2VkVXJpLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgcGFydDogMixcbiAgICAgIH0pO1xuXG4gICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZFdpdGgoJy9mYWtlczMnLCBleHBlY3QuYW55KE9iamVjdCkpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkudG9IYXZlQmVlbkNhbGxlZFdpdGgoe1xuICAgICAgICBhcGlrZXk6IHRlc3RBcGlrZXksXG4gICAgICAgIGZpbGVuYW1lOiB0ZXN0RmlsZS5uYW1lLFxuICAgICAgICBtaW1ldHlwZTogdGVzdEZpbGUubWltZXR5cGUsXG4gICAgICAgIHNpemU6IHRlc3RGaWxlLnNpemUsXG4gICAgICAgIHBhcnRzOiBbeyBwYXJ0X251bWJlcjogMSwgZXRhZzogJ3Rlc3QnIH0sIHsgcGFydF9udW1iZXI6IDIsIGV0YWc6ICd0ZXN0JyB9XSxcbiAgICAgICAgcmVnaW9uOiBtb2NrUmVnaW9uLFxuICAgICAgICB1cGxvYWRfaWQ6IG1vY2tVcGxvYWRJZCxcbiAgICAgICAgc3RvcmU6IHtcbiAgICAgICAgICBsb2NhdGlvbjogREVGQVVMVF9TVE9SRV9MT0NBVElPTixcbiAgICAgICAgfSxcbiAgICAgICAgdXJpOiBtb2NrZWRVcmksXG4gICAgICB9KTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5oYW5kbGUpLnRvRXF1YWwoJ3Rlc3RfaGFuZGxlJyk7XG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgndGVzdF9zdGF0dXMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHByb2Nlc3MgdXBsb2FkIG9uIG11bHRpcGFydC91cGxvYWQgbmV0d29yayBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgICAgIGludGVyY2VwdG9yVXBsb2FkLnJlcGx5KDQwMCwge1xuICAgICAgICBtZXNzYWdlOiAnc29tZXRoaW5nIGF3ZnVsIGhhcHBlbmVkJyxcbiAgICAgICAgY29kZTogJ2JhZF9yZXF1ZXN0JyxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB1ID0gbmV3IFMzVXBsb2FkZXIoe30pO1xuICAgICAgdS5zZXRVcmwodGVzdEhvc3QpO1xuICAgICAgdS5zZXRBcGlrZXkodGVzdEFwaWtleSk7XG4gICAgICB1LmFkZEZpbGUoZ2V0U21hbGxUZXN0RmlsZSgpKTtcblxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgdS5leGVjdXRlKCk7XG5cbiAgICAgIGV4cGVjdChyZXNbMF0uc3RhdHVzKS50b0VxdWFsKCdGYWlsZWQnKTtcblxuICAgICAgZXhwZWN0KG1vY2tTdGFydCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tQdXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja0NvbW1pdCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlc3BlY3QgcmV0cnkgY29uZmlnJywgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gc2ltdWxhdGUgZmlyc3QgcmVxdWVzdCBuZXR3b3JrIGZhaWxcbiAgICAgIGxldCBuZXR3b3JrRmFpbCA9IHRydWU7XG5cbiAgICAgIG5vY2sucmVtb3ZlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3JTMyk7XG4gICAgICBzY29wZS5wZXJzaXN0KGZhbHNlKTtcblxuICAgICAgc2NvcGUucHV0KCcvZmFrZXMzJykudHdpY2UoKS5yZXBseShcbiAgICAgICAgZnVuY3Rpb24odXJsLCBfLCBjYikge1xuICAgICAgICAgIGlmIChuZXR3b3JrRmFpbCkge1xuICAgICAgICAgICAgbmV0d29ya0ZhaWwgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiBjYihFcnJvcignZXJyb3InKSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY2IobnVsbCwgWzIwMSwgbW9ja1B1dCh1cmwsIHRoaXMucmVxLmhlYWRlcnMpLCB7IGV0YWc6ICd0ZXN0J31dKTtcbiAgICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuICAgICAgdS5zZXRSZXRyeUNvbmZpZyh7XG4gICAgICAgIHJldHJ5OiAxLFxuICAgICAgICByZXRyeUZhY3RvcjogMixcbiAgICAgICAgcmV0cnlNYXhUaW1lOiAxMCxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ3Rlc3Rfc3RhdHVzJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDb21tb24gbmV0d29yayBlcnJvcnMnLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCBub3QgcHJvY2VzcyB1cGxvYWQgb24gd3Jvbmcgc3RhcnQgcmVzcG9uc2UnLCBhc3luYyAoKSA9PiB7XG4gICAgICBtb2NrU3RhcnQubW9ja1Jlc2V0KCk7XG4gICAgICBtb2NrU3RhcnQubW9ja1JldHVyblZhbHVlKHtcbiAgICAgICAgdGVzdDogMTIzLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuICAgICAgZXhwZWN0KG1vY2tQdXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja1VwbG9hZCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tbWl0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tDb21wbGV0ZSkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgbm90IHByb2Nlc3MgdXBsb2FkIG9uIHN0YXJ0IGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgaW50ZXJjZXB0b3JTdGFydC5yZXBseSg0MDAsIHtcbiAgICAgICAgbWVzc2FnZTogJ3NvbWV0aGluZyBhd2Z1bCBoYXBwZW5lZCcsXG4gICAgICAgIGNvZGU6ICdiYWRfcmVxdWVzdCcsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdSA9IG5ldyBTM1VwbG9hZGVyKHt9KTtcbiAgICAgIHUuc2V0VXJsKHRlc3RIb3N0KTtcbiAgICAgIHUuc2V0QXBpa2V5KHRlc3RBcGlrZXkpO1xuICAgICAgdS5hZGRGaWxlKGdldFNtYWxsVGVzdEZpbGUoKSk7XG5cbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHUuZXhlY3V0ZSgpO1xuXG4gICAgICBleHBlY3QocmVzWzBdLnN0YXR1cykudG9FcXVhbCgnRmFpbGVkJyk7XG5cbiAgICAgIGV4cGVjdChtb2NrUHV0KS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tVcGxvYWQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja0NvbW1pdCkubm90LnRvSGF2ZUJlZW5DYWxsZWQoKTtcbiAgICAgIGV4cGVjdChtb2NrQ29tcGxldGUpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIG5vciBwcm9jZXNzIHVwbG9hZCBvbiBtdWx0aXBhcnQvY29tcGxldGUgbmV0d29yayBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgICAgIGludGVyY2VwdG9yQ29tcGxldGUucmVwbHkoNDAwLCB7XG4gICAgICAgIG1lc3NhZ2U6ICdzb21ldGhpbmcgYXdmdWwgaGFwcGVuZWQnLFxuICAgICAgICBjb2RlOiAnYmFkX3JlcXVlc3QnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHUgPSBuZXcgUzNVcGxvYWRlcih7fSk7XG4gICAgICB1LnNldFVybCh0ZXN0SG9zdCk7XG4gICAgICB1LnNldEFwaWtleSh0ZXN0QXBpa2V5KTtcbiAgICAgIHUuYWRkRmlsZShnZXRTbWFsbFRlc3RGaWxlKCkpO1xuXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCB1LmV4ZWN1dGUoKTtcblxuICAgICAgZXhwZWN0KHJlc1swXS5zdGF0dXMpLnRvRXF1YWwoJ0ZhaWxlZCcpO1xuXG4gICAgICBleHBlY3QobW9ja1N0YXJ0KS50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgICBleHBlY3QobW9ja1B1dCkudG9IYXZlQmVlbkNhbGxlZCgpO1xuICAgICAgZXhwZWN0KG1vY2tDb21taXQpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=