UNPKG

blockstack

Version:

The Blockstack Javascript library for authentication, identity, and storage.

372 lines (358 loc) 59.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.runIntegrationTests = runIntegrationTests; var _child_process = require("child_process"); var _tape = _interopRequireDefault(require("tape")); var _src = require("../../../src"); var _utils = require("../../../src/operations/utils"); var BLOCKSTACK_TEST = !!process.env.BLOCKSTACK_TEST; function pExec(cmd) { return new Promise(function (resolve, reject) { (0, _child_process.exec)(cmd, function (err, stdout, stderr) { if (err) { reject(err); } else { resolve(stdout, stderr); } }); }); } function initializeBlockstackCore() { if (BLOCKSTACK_TEST) { // running with an external test suite return Promise.resolve(); } else { return pExec('docker pull quay.io/blockstack/integrationtests:develop').then(function () { console.log('Pulled latest docker image'); return pExec("docker stop test-bsk-core ;\n docker rm test-bsk-core ;\n rm -rf /tmp/.blockstack_int_test").catch(function () { return true; }); }).then(function () { return pExec('docker run --name test-bsk-core -dt ' + '-p 16268:16268 -p 18332:18332 -p 30001:30001 ' + '-e BLOCKSTACK_TEST_CLIENT_RPC_PORT=16268 ' + '-e BLOCKSTACK_TEST_CLIENT_BIND=0.0.0.0 ' + '-e BLOCKSTACK_TEST_BITCOIND_ALLOWIP=172.17.0.0/16 ' + '-e BLOCKSTACK_WEB_TEST_BIND=0.0.0.0 ' + 'quay.io/blockstack/integrationtests:develop ' + 'blockstack-test-scenario --interactive 2 ' + 'blockstack_integration_tests.scenarios.portal_test_env'); }).then(function () { console.log('Started regtest container, waiting until initialized'); return pExec('docker logs -f test-bsk-core | grep -q \'Test finished\''); }).then(function () { // try to avoid race with nextBlock() console.log('Wait 10 seconds for test server to bind'); return new Promise(function (resolve) { return setTimeout(resolve, 10000); }); }); } } function nextBlock(numBlocks) { if (BLOCKSTACK_TEST) { var options = { method: 'POST' }; if (!!numBlocks) { options.body = "numblocks=".concat(numBlocks); } var url = 'http://localhost:30001/nextblock'; return fetch(url, options).then(function (resp) { if (resp.status >= 400) { throw new Error("Bad test framework status: ".concat(resp.status)); } else { return true; } }); } else { return new Promise(function (resolve) { return setTimeout(resolve, 30000); }); } } function shutdownBlockstackCore() { if (BLOCKSTACK_TEST) { return Promise.resolve(); } else { return pExec('docker stop test-bsk-core'); } } function runIntegrationTests() { (0, _tape.default)('registerIdName', function (t) { t.plan(8); _src.config.network = _src.network.defaults.LOCAL_REGTEST; var myNet = _src.config.network; var dest = '19238846ac60fa62f8f8bb8898b03df79bc6112600181f36061835ad8934086001'; var destAddress = (0, _src.hexStringToECPair)(dest).getAddress(); var btcDest = '897f1b92041b798580f96b8be379053f6276f04eb7590a9042a62059d46d6fc301'; var btcDestAddress = (0, _src.hexStringToECPair)(btcDest).getAddress(); var payer = 'bb68eda988e768132bc6c7ca73a87fb9b0918e9a38d3618b74099be25f7cab7d01'; var secondOwner = '54164693e3803223f7fa9a004997bfbf1475f5c44f65593fa45c6783086dafec01'; var transferDestination = (0, _src.hexStringToECPair)(secondOwner).getAddress(); var renewalDestination = 'myPgwEX2ddQxPPqWBRkXNqL3TwuWbY29DJ'; var zfTest = '$ORIGIN aaron.id\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/0/profile.json\""); var zfTest2 = '$ORIGIN aaron.id\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/3/profile.json\""); var renewalZF = '$ORIGIN aaron.id\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/4/profile.json\""); initializeBlockstackCore().then(function () { console.log('Blockstack Core initialized.'); return _src.transactions.makePreorder('aaron.id', destAddress, payer); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('PREORDER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return _src.transactions.makeRegister('aaron.id', destAddress, payer, zfTest); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('REGISTER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(zfTest); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.id")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(myNet.coerceAddress(nameInfo.address), destAddress, "aaron.id should be owned by ".concat(destAddress)); t.equal(nameInfo.zonefile, zfTest, 'zonefile should be properly set'); }).then(function () { return _src.transactions.makeUpdate('aaron.id', dest, payer, zfTest2); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('UPDATE broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(zfTest2); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.id")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(nameInfo.zonefile, zfTest2, 'zonefile should be updated'); }).then(function () { return _src.transactions.makeTransfer('aaron.id', transferDestination, dest, payer); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('TRANSFER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.id")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(myNet.coerceAddress(nameInfo.address), transferDestination, "aaron.id should be owned by ".concat(transferDestination)); }).then(function () { return _src.transactions.makeRenewal('aaron.id', renewalDestination, secondOwner, payer, renewalZF); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('RENEWAL broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(renewalZF); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.id")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(nameInfo.zonefile, renewalZF, 'zonefile should be updated'); t.equal(myNet.coerceAddress(nameInfo.address), renewalDestination, "aaron.id should be owned by ".concat(renewalDestination)); }).then(function () { return _src.transactions.makeBitcoinSpend(btcDestAddress, payer, 500000); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('broadcasted SPEND, waiting 10 seconds.'); return nextBlock(); }).then(function () { return myNet.getUTXOs(btcDestAddress); }).then(function (utxos) { t.equal(utxos.length, 1, "Destination address ".concat(btcDestAddress, " should have 1 UTXO")); var satoshis = utxos.reduce(function (agg, utxo) { return agg + utxo.value; }, 0); console.log("".concat(btcDestAddress, " has ").concat(satoshis, " satoshis")); }).then(function () { return shutdownBlockstackCore(); }).then(function () { return t.pass('Finished test'); }); }); (0, _tape.default)('helloNamespace', function (t) { t.plan(11); _src.config.network = _src.network.defaults.LOCAL_REGTEST; var myNet = _src.config.network; var nsPay = '6e50431b955fe73f079469b24f06480aee44e4519282686433195b3c4b5336ef01'; var nsReveal = 'c244642ce0b4eb68da8e098facfcad889e3063c36a68b7951fb4c085de49df1b01'; var nsRevealAddress = (0, _src.hexStringToECPair)(nsReveal).getAddress(); var dest = '19238846ac60fa62f8f8bb8898b03df79bc6112600181f36061835ad8934086001'; var destAddress = (0, _src.hexStringToECPair)(dest).getAddress(); var btcDest = '3ad9f690cc7694572fe7574526ad260ff2e711d608d3224895efd932b1d47c7201'; var btcDestAddress = (0, _src.hexStringToECPair)(btcDest).getAddress(); var payer = 'bb68eda988e768132bc6c7ca73a87fb9b0918e9a38d3618b74099be25f7cab7d01'; var secondOwner = '54164693e3803223f7fa9a004997bfbf1475f5c44f65593fa45c6783086dafec01'; var transferDestination = (0, _src.hexStringToECPair)(secondOwner).getAddress(); var renewalKey = 'bb68eda988e768132bc6c7ca73a87fb9b0918e9a38d3618b74099be25f7cab7d'; var renewalDestination = (0, _src.hexStringToECPair)(renewalKey).getAddress(); var zfTest = '$ORIGIN aaron.hello\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/0/profile.json\""); var zfTest2 = '$ORIGIN aaron.hello\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/3/profile.json\""); var renewalZF = '$ORIGIN aaron.hello\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/4/profile.json\""); var importZF = '$ORIGIN import.hello\n$TTL 3600\n_http._tcp URI 10 1 ' + "\"https://gaia.blockstacktest.org/hub/".concat(destAddress, "/0/profile.json\""); initializeBlockstackCore().then(function () { console.log('Blockstack Core initialized.'); console.log("Preorder namespace \"hello\" to ".concat(nsRevealAddress)); return _src.transactions.makeNamespacePreorder('hello', nsRevealAddress, nsPay); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('NAMESPACE_PREORDER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { var ns = new _src.transactions.BlockstackNamespace('hello'); ns.setVersion(1); ns.setLifetime(52595); ns.setCoeff(4); ns.setBase(4); ns.setBuckets([6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]); ns.setNonalphaDiscount(10); ns.setNoVowelDiscount(10); console.log("Reveal namespace \"hello\" to ".concat(nsRevealAddress)); return _src.transactions.makeNamespaceReveal(ns, nsRevealAddress, nsPay); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('NAMESPACE_REVEAL broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { console.log('NAME_IMPORT import.hello'); var zfHash = (0, _utils.hash160)(Buffer.from(importZF)).toString('hex'); return _src.transactions.makeNameImport('import.hello', renewalDestination, zfHash, nsReveal); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('NAME_IMPORT broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(importZF); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/import.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(myNet.coerceAddress(nameInfo.address), renewalDestination, "import.hello should be owned by ".concat(renewalDestination)); t.equal(nameInfo.zonefile, importZF, 'zonefile should be properly set for import.hello'); }).then(function () { console.log('Launch namespace "hello"'); return _src.transactions.makeNamespaceReady('hello', nsReveal); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('NAMESPACE_READY broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { console.log('Namespace initialized. Preordering aaron.hello'); return _src.transactions.makePreorder('aaron.hello', destAddress, payer); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('PREORDER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return _src.transactions.makeRegister('aaron.hello', destAddress, payer, zfTest); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('REGISTER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(zfTest); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(myNet.coerceAddress(nameInfo.address), destAddress, "aaron.hello should be owned by ".concat(destAddress)); t.equal(nameInfo.zonefile, zfTest, 'zonefile should be properly set'); }).then(function () { return _src.transactions.makeUpdate('aaron.hello', dest, payer, zfTest2); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('UPDATE broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(zfTest2); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(nameInfo.zonefile, zfTest2, 'zonefile should be updated'); }).then(function () { return _src.transactions.makeTransfer('aaron.hello', transferDestination, dest, payer); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('TRANSFER broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(myNet.coerceAddress(nameInfo.address), transferDestination, "aaron.hello should be owned by ".concat(transferDestination)); }).then(function () { return _src.transactions.makeRenewal('aaron.hello', renewalDestination, secondOwner, payer, renewalZF); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('RENEWAL broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return myNet.broadcastZoneFile(renewalZF); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(nameInfo.zonefile, renewalZF, 'zonefile should be updated'); t.equal(myNet.coerceAddress(nameInfo.address), renewalDestination, "aaron.hello should be owned by ".concat(renewalDestination)); }).then(function () { return _src.transactions.makeRevoke('aaron.hello', renewalKey, payer); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('REVOKE broadcasted, waiting 30 seconds.'); return nextBlock(); }).then(function () { return fetch("".concat(myNet.blockstackAPIUrl, "/v1/names/aaron.hello")); }).then(function (resp) { return resp.json(); }).then(function (nameInfo) { t.equal(nameInfo.status, 'revoked', 'Name should be revoked'); }).then(function () { return _src.transactions.makeBitcoinSpend(btcDestAddress, payer, 500000); }).then(function (rawtx) { return myNet.broadcastTransaction(rawtx); }).then(function () { console.log('broadcasted SPEND, waiting 10 seconds.'); return nextBlock(6); }).then(function () { return myNet.getUTXOs(btcDestAddress); }).then(function (utxos) { t.equal(utxos.length, 1, "Destination address ".concat(btcDestAddress, " should have 1 UTXO")); var satoshis = utxos.reduce(function (agg, utxo) { return agg + utxo.value; }, 0); console.log("".concat(btcDestAddress, " has ").concat(satoshis, " satoshis")); }).then(function () { return shutdownBlockstackCore(); }).then(function () { return t.pass('Finished test'); }).catch(function (err) { console.log(err.stack); console.log(err); }); }); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9vcGVyYXRpb25zVGVzdHMuanMiXSwibmFtZXMiOlsiQkxPQ0tTVEFDS19URVNUIiwicHJvY2VzcyIsImVudiIsInBFeGVjIiwiY21kIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJlcnIiLCJzdGRvdXQiLCJzdGRlcnIiLCJpbml0aWFsaXplQmxvY2tzdGFja0NvcmUiLCJ0aGVuIiwiY29uc29sZSIsImxvZyIsImNhdGNoIiwic2V0VGltZW91dCIsIm5leHRCbG9jayIsIm51bUJsb2NrcyIsIm9wdGlvbnMiLCJtZXRob2QiLCJib2R5IiwidXJsIiwiZmV0Y2giLCJyZXNwIiwic3RhdHVzIiwiRXJyb3IiLCJzaHV0ZG93bkJsb2Nrc3RhY2tDb3JlIiwicnVuSW50ZWdyYXRpb25UZXN0cyIsInQiLCJwbGFuIiwiY29uZmlnIiwibmV0d29yayIsImRlZmF1bHRzIiwiTE9DQUxfUkVHVEVTVCIsIm15TmV0IiwiZGVzdCIsImRlc3RBZGRyZXNzIiwiZ2V0QWRkcmVzcyIsImJ0Y0Rlc3QiLCJidGNEZXN0QWRkcmVzcyIsInBheWVyIiwic2Vjb25kT3duZXIiLCJ0cmFuc2ZlckRlc3RpbmF0aW9uIiwicmVuZXdhbERlc3RpbmF0aW9uIiwiemZUZXN0IiwiemZUZXN0MiIsInJlbmV3YWxaRiIsInRyYW5zYWN0aW9ucyIsIm1ha2VQcmVvcmRlciIsInJhd3R4IiwiYnJvYWRjYXN0VHJhbnNhY3Rpb24iLCJtYWtlUmVnaXN0ZXIiLCJicm9hZGNhc3Rab25lRmlsZSIsImJsb2Nrc3RhY2tBUElVcmwiLCJqc29uIiwibmFtZUluZm8iLCJlcXVhbCIsImNvZXJjZUFkZHJlc3MiLCJhZGRyZXNzIiwiem9uZWZpbGUiLCJtYWtlVXBkYXRlIiwibWFrZVRyYW5zZmVyIiwibWFrZVJlbmV3YWwiLCJtYWtlQml0Y29pblNwZW5kIiwiZ2V0VVRYT3MiLCJ1dHhvcyIsImxlbmd0aCIsInNhdG9zaGlzIiwicmVkdWNlIiwiYWdnIiwidXR4byIsInZhbHVlIiwicGFzcyIsIm5zUGF5IiwibnNSZXZlYWwiLCJuc1JldmVhbEFkZHJlc3MiLCJyZW5ld2FsS2V5IiwiaW1wb3J0WkYiLCJtYWtlTmFtZXNwYWNlUHJlb3JkZXIiLCJucyIsIkJsb2Nrc3RhY2tOYW1lc3BhY2UiLCJzZXRWZXJzaW9uIiwic2V0TGlmZXRpbWUiLCJzZXRDb2VmZiIsInNldEJhc2UiLCJzZXRCdWNrZXRzIiwic2V0Tm9uYWxwaGFEaXNjb3VudCIsInNldE5vVm93ZWxEaXNjb3VudCIsIm1ha2VOYW1lc3BhY2VSZXZlYWwiLCJ6Zkhhc2giLCJCdWZmZXIiLCJmcm9tIiwidG9TdHJpbmciLCJtYWtlTmFtZUltcG9ydCIsIm1ha2VOYW1lc3BhY2VSZWFkeSIsIm1ha2VSZXZva2UiLCJzdGFjayJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBRUE7O0FBR0E7O0FBRUEsSUFBTUEsZUFBZSxHQUFHLENBQUMsQ0FBQ0MsT0FBTyxDQUFDQyxHQUFSLENBQVlGLGVBQXRDOztBQUVBLFNBQVNHLEtBQVQsQ0FBZUMsR0FBZixFQUFvQjtBQUNsQixTQUFPLElBQUlDLE9BQUosQ0FDTCxVQUFDQyxPQUFELEVBQVVDLE1BQVYsRUFBcUI7QUFDbkIsNkJBQUtILEdBQUwsRUFBVSxVQUFDSSxHQUFELEVBQU1DLE1BQU4sRUFBY0MsTUFBZCxFQUF5QjtBQUNqQyxVQUFJRixHQUFKLEVBQVM7QUFDUEQsUUFBQUEsTUFBTSxDQUFDQyxHQUFELENBQU47QUFDRCxPQUZELE1BRU87QUFDTEYsUUFBQUEsT0FBTyxDQUFDRyxNQUFELEVBQVNDLE1BQVQsQ0FBUDtBQUNEO0FBQ0YsS0FORDtBQU9ELEdBVEksQ0FBUDtBQVdEOztBQUVELFNBQVNDLHdCQUFULEdBQW9DO0FBQ2xDLE1BQUlYLGVBQUosRUFBcUI7QUFDbkI7QUFDQSxXQUFPSyxPQUFPLENBQUNDLE9BQVIsRUFBUDtBQUNELEdBSEQsTUFHTztBQUNMLFdBQU9ILEtBQUssQ0FBQyx5REFBRCxDQUFMLENBQ0pTLElBREksQ0FDQyxZQUFNO0FB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OElHeEQsSUE5SUgsQ0E4SVE7QUFBQSxhQUFNZSxzQkFBc0IsRUFBNUI7QUFBQSxLQTlJUixFQStJR2YsSUEvSUgsQ0ErSVE7QUFBQSxhQUFNaUIsQ0FBQyxDQUFDNEMsSUFBRixDQUFPLGVBQVAsQ0FBTjtBQUFBLEtBL0lSLEVBZ0pHMUQsS0FoSkgsQ0FnSlMsVUFBQ1AsR0FBRCxFQUFTO0FBQ2RLLE1BQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZTixHQUFHLENBQUN5RixLQUFoQjtBQUNBcEYsTUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVlOLEdBQVo7QUFDRCxLQW5KSDtBQW9KRCxHQXRMRDtBQXVMRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJ1xuaW1wb3J0IHRlc3QgZnJvbSAndGFwZSdcblxuaW1wb3J0IHtcbiAgdHJhbnNhY3Rpb25zLCBjb25maWcsIG5ldHdvcmssIGhleFN0cmluZ1RvRUNQYWlyIFxufSBmcm9tICcuLi8uLi8uLi9zcmMnXG5pbXBvcnQgeyBoYXNoMTYwIH0gZnJvbSAnLi4vLi4vLi4vc3JjL29wZXJhdGlvbnMvdXRpbHMnXG5cbmNvbnN0IEJMT0NLU1RBQ0tfVEVTVCA9ICEhcHJvY2Vzcy5lbnYuQkxPQ0tTVEFDS19URVNUXG5cbmZ1bmN0aW9uIHBFeGVjKGNtZCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoXG4gICAgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZXhlYyhjbWQsIChlcnIsIHN0ZG91dCwgc3RkZXJyKSA9PiB7XG4gICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICByZWplY3QoZXJyKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUoc3Rkb3V0LCBzdGRlcnIpXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuICApXG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVCbG9ja3N0YWNrQ29yZSgpIHtcbiAgaWYgKEJMT0NLU1RBQ0tfVEVTVCkge1xuICAgIC8vIHJ1bm5pbmcgd2l0aCBhbiBleHRlcm5hbCB0ZXN0IHN1aXRlXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHBFeGVjKCdkb2NrZXIgcHVsbCBxdWF5LmlvL2Jsb2Nrc3RhY2svaW50ZWdyYXRpb250ZXN0czpkZXZlbG9wJylcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1B1bGxlZCBsYXRlc3QgZG9ja2VyIGltYWdlJylcbiAgICAgICAgcmV0dXJuIHBFeGVjKGBkb2NrZXIgc3RvcCB0ZXN0LWJzay1jb3JlIDtcbiAgICAgICAgICBkb2NrZXIgcm0gdGVzdC1ic2stY29yZSA7XG4gICAgICAgICAgcm0gLXJmIC90bXAvLmJsb2Nrc3RhY2tfaW50X3Rlc3RgKVxuICAgICAgICAgIC5jYXRjaCgoKSA9PiB0cnVlKVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHBFeGVjKCdkb2NrZXIgcnVuIC0tbmFtZSB0ZXN0LWJzay1jb3JlIC1kdCAnXG4gICAgICAgICAgICAgICAgICAgICAgICArICctcCAxNjI2ODoxNjI2OCAtcCAxODMzMjoxODMzMiAtcCAzMDAwMTozMDAwMSAnXG4gICAgICAgICAgICAgICAgICAgICAgICArICctZSBCTE9DS1NUQUNLX1RFU1RfQ0xJRU5UX1JQQ19QT1JUPTE2MjY4ICdcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJy1lIEJMT0NLU1RBQ0tfVEVTVF9DTElFTlRfQklORD0wLjAuMC4wICdcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJy1lIEJMT0NLU1RBQ0tfVEVTVF9CSVRDT0lORF9BTExPV0lQPTE3Mi4xNy4wLjAvMTYgJ1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnLWUgQkxPQ0tTVEFDS19XRUJfVEVTVF9CSU5EPTAuMC4wLjAgJ1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAncXVheS5pby9ibG9ja3N0YWNrL2ludGVncmF0aW9udGVzdHM6ZGV2ZWxvcCAnXG4gICAgICAgICAgICAgICAgICAgICAgICArICdibG9ja3N0YWNrLXRlc3Qtc2NlbmFyaW8gLS1pbnRlcmFjdGl2ZSAyICdcbiAgICAgICAgICAgICAgICAgICAgICAgICsgJ2Jsb2Nrc3RhY2tfaW50ZWdyYXRpb25fdGVzdHMuc2NlbmFyaW9zLnBvcnRhbF90ZXN0X2VudicpKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnU3RhcnRlZCByZWd0ZXN0IGNvbnRhaW5lciwgd2FpdGluZyB1bnRpbCBpbml0aWFsaXplZCcpXG4gICAgICAgIHJldHVybiBwRXhlYygnZG9ja2VyIGxvZ3MgLWYgdGVzdC1ic2stY29yZSB8IGdyZXAgLXEgXFwnVGVzdCBmaW5pc2hlZFxcJycpXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyB0cnkgdG8gYXZvaWQgcmFjZSB3aXRoIG5leHRCbG9jaygpXG4gICAgICAgIGNvbnNvbGUubG9nKCdXYWl0IDEwIHNlY29uZHMgZm9yIHRlc3Qgc2VydmVyIHRvIGJpbmQnKVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDAwKSlcbiAgICAgIH0pXG4gIH1cbn1cblxuZnVuY3Rpb24gbmV4dEJsb2NrKG51bUJsb2Nrcykge1xuICBpZiAoQkxPQ0tTVEFDS19URVNUKSB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnXG4gICAgfVxuXG4gICAgaWYgKCEhbnVtQmxvY2tzKSB7XG4gICAgICBvcHRpb25zLmJvZHkgPSBgbnVtYmxvY2tzPSR7bnVtQmxvY2tzfWBcbiAgICB9XG5cbiAgICBjb25zdCB1cmwgPSAnaHR0cDovL2xvY2FsaG9zdDozMDAwMS9uZXh0YmxvY2snXG4gICAgcmV0dXJuIGZldGNoKHVybCwgb3B0aW9ucylcbiAgICAgIC50aGVuKChyZXNwKSA9PiB7XG4gICAgICAgIGlmIChyZXNwLnN0YXR1cyA+PSA0MDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhZCB0ZXN0IGZyYW1ld29yayBzdGF0dXM6ICR7cmVzcC5zdGF0dXN9YClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9KVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMzAwMDApKVxuICB9XG59XG5cbmZ1bmN0aW9uIHNodXRkb3duQmxvY2tzdGFja0NvcmUoKSB7XG4gIGlmIChCTE9DS1NUQUNLX1RFU1QpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcEV4ZWMoJ2RvY2tlciBzdG9wIHRlc3QtYnNrLWNvcmUnKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBydW5JbnRlZ3JhdGlvblRlc3RzKCkge1xuICB0ZXN0KCdyZWdpc3RlcklkTmFtZScsICh0KSA9PiB7XG4gICAgdC5wbGFuKDgpXG5cbiAgICBjb25maWcubmV0d29yayA9IG5ldHdvcmsuZGVmYXVsdHMuTE9DQUxfUkVHVEVTVFxuICAgIGNvbnN0IG15TmV0ID0gY29uZmlnLm5ldHdvcmtcblxuICAgIGNvbnN0IGRlc3QgPSAnMTkyMzg4NDZhYzYwZmE2MmY4ZjhiYjg4OThiMDNkZjc5YmM2MTEyNjAwMTgxZjM2MDYxODM1YWQ4OTM0MDg2MDAxJ1xuICAgIGNvbnN0IGRlc3RBZGRyZXNzID0gaGV4U3RyaW5nVG9FQ1BhaXIoZGVzdCkuZ2V0QWRkcmVzcygpXG5cblxuICAgIGNvbnN0IGJ0Y0Rlc3QgPSAnODk3ZjFiOTIwNDFiNzk4NTgwZjk2YjhiZTM3OTA1M2Y2Mjc2ZjA0ZWI3NTkwYTkwNDJhNjIwNTlkNDZkNmZjMzAxJ1xuICAgIGNvbnN0IGJ0Y0Rlc3RBZGRyZXNzID0gaGV4U3RyaW5nVG9FQ1BhaXIoYnRjRGVzdCkuZ2V0QWRkcmVzcygpXG5cbiAgICBjb25zdCBwYXllciA9ICdiYjY4ZWRhOTg4ZTc2ODEzMmJjNmM3Y2E3M2E4N2ZiOWIwOTE4ZTlhMzhkMzYxOGI3NDA5OWJlMjVmN2NhYjdkMDEnXG5cbiAgICBjb25zdCBzZWNvbmRPd25lciA9ICc1NDE2NDY5M2UzODAzMjIzZjdmYTlhMDA0OTk3YmZiZjE0NzVmNWM0NGY2NTU5M2ZhNDVjNjc4MzA4NmRhZmVjMDEnXG4gICAgY29uc3QgdHJhbnNmZXJEZXN0aW5hdGlvbiA9IGhleFN0cmluZ1RvRUNQYWlyKHNlY29uZE93bmVyKS5nZXRBZGRyZXNzKClcblxuICAgIGNvbnN0IHJlbmV3YWxEZXN0aW5hdGlvbiA9ICdteVBnd0VYMmRkUXhQUHFXQlJrWE5xTDNUd3VXYlkyOURKJ1xuXG4gICAgY29uc3QgemZUZXN0ID0gJyRPUklHSU4gYWFyb24uaWRcXG4kVFRMIDM2MDBcXG5faHR0cC5fdGNwIFVSSSAxMCAxICdcbiAgICAgICAgICArIGBcImh0dHBzOi8vZ2FpYS5ibG9ja3N0YWNrdGVzdC5vcmcvaHViLyR7ZGVzdEFkZHJlc3N9LzAvcHJvZmlsZS5qc29uXCJgXG4gICAgY29uc3QgemZUZXN0MiA9ICckT1JJR0lOIGFhcm9uLmlkXFxuJFRUTCAzNjAwXFxuX2h0dHAuX3RjcCBVUkkgMTAgMSAnXG4gICAgICAgICAgKyBgXCJodHRwczovL2dhaWEuYmxvY2tzdGFja3Rlc3Qub3JnL2h1Yi8ke2Rlc3RBZGRyZXNzfS8zL3Byb2ZpbGUuanNvblwiYFxuICAgIGNvbnN0IHJlbmV3YWxaRiA9ICckT1JJR0lOIGFhcm9uLmlkXFxuJFRUTCAzNjAwXFxuX2h0dHAuX3RjcCBVUkkgMTAgMSAnXG4gICAgICAgICAgKyBgXCJodHRwczovL2dhaWEuYmxvY2tzdGFja3Rlc3Qub3JnL2h1Yi8ke2Rlc3RBZGRyZXNzfS80L3Byb2ZpbGUuanNvblwiYFxuXG4gICAgaW5pdGlhbGl6ZUJsb2Nrc3RhY2tDb3JlKClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ0Jsb2Nrc3RhY2sgQ29yZSBpbml0aWFsaXplZC4nKVxuICAgICAgICByZXR1cm4gdHJhbnNhY3Rpb25zLm1ha2VQcmVvcmRlcignYWFyb24uaWQnLCBkZXN0QWRkcmVzcywgcGF5ZXIpXG4gICAgICB9KVxuICAgICAgLnRoZW4ocmF3dHggPT4gbXlOZXQuYnJvYWRjYXN0VHJhbnNhY3Rpb24ocmF3dHgpKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnUFJFT1JERVIgYnJvYWRjYXN0ZWQsIHdhaXRpbmcgMzAgc2Vjb25kcy4nKVxuICAgICAgICByZXR1cm4gbmV4dEJsb2NrKClcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB0cmFuc2FjdGlvbnMubWFrZVJlZ2lzdGVyKCdhYXJvbi5pZCcsIGRlc3RBZGRyZXNzLCBwYXllciwgemZUZXN0KSlcbiAgICAgIC50aGVuKHJhd3R4ID0+IG15TmV0LmJyb2FkY2FzdFRyYW5zYWN0aW9uKHJhd3R4KSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1JFR0lTVEVSIGJyb2FkY2FzdGVkLCB3YWl0aW5nIDMwIHNlY29uZHMuJylcbiAgICAgICAgcmV0dXJuIG5leHRCbG9jaygpXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gbXlOZXQuYnJvYWRjYXN0Wm9uZUZpbGUoemZUZXN0KSlcbiAgICAgIC50aGVuKCgpID0+IGZldGNoKGAke215TmV0LmJsb2Nrc3RhY2tBUElVcmx9L3YxL25hbWVzL2Fhcm9uLmlkYCkpXG4gICAgICAudGhlbihyZXNwID0+IHJlc3AuanNvbigpKVxuICAgICAgLnRoZW4oKG5hbWVJbmZvKSA9PiB7XG4gICAgICAgIHQuZXF1YWwobXlOZXQuY29lcmNlQWRkcmVzcyhuYW1lSW5mby5hZGRyZXNzKSwgZGVzdEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgYGFhcm9uLmlkIHNob3VsZCBiZSBvd25lZCBieSAke2Rlc3RBZGRyZXNzfWApXG4gICAgICAgIHQuZXF1YWwobmFtZUluZm8uem9uZWZpbGUsIHpmVGVzdCwgJ3pvbmVmaWxlIHNob3VsZCBiZSBwcm9wZXJseSBzZXQnKVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHRyYW5zYWN0aW9ucy5tYWtlVXBkYXRlKCdhYXJvbi5pZCcsIGRlc3QsIHBheWVyLCB6ZlRlc3QyKSlcbiAgICAgIC50aGVuKHJhd3R4ID0+IG15TmV0LmJyb2FkY2FzdFRyYW5zYWN0aW9uKHJhd3R4KSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1VQREFURSBicm9hZGNhc3RlZCwgd2FpdGluZyAzMCBzZWNvbmRzLicpXG4gICAgICAgIHJldHVybiBuZXh0QmxvY2soKVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IG15TmV0LmJyb2FkY2FzdFpvbmVGaWxlKHpmVGVzdDIpKVxuICAgICAgLnRoZW4oKCkgPT4gZmV0Y2goYCR7bXlOZXQuYmxvY2tzdGFja0FQSVVybH0vdjEvbmFtZXMvYWFyb24uaWRgKSlcbiAgICAgIC50aGVuKHJlc3AgPT4gcmVzcC5qc29uKCkpXG4gICAgICAudGhlbigobmFtZUluZm8pID0+IHtcbiAgICAgICAgdC5lcXVhbChuYW1lSW5mby56b25lZmlsZSwgemZUZXN0MiwgJ3pvbmVmaWxlIHNob3VsZCBiZSB1cGRhdGVkJylcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB0cmFuc2FjdGlvbnMubWFrZVRyYW5zZmVyKCdhYXJvbi5pZCcsIHRyYW5zZmVyRGVzdGluYXRpb24sIGRlc3QsIHBheWVyKSlcbiAgICAgIC50aGVuKHJhd3R4ID0+IG15TmV0LmJyb2FkY2FzdFRyYW5zYWN0aW9uKHJhd3R4KSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1RSQU5TRkVSIGJyb2FkY2FzdGVkLCB3YWl0aW5nIDMwIHNlY29uZHMuJylcbiAgICAgICAgcmV0dXJuIG5leHRCbG9jaygpXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gZmV0Y2goYCR7bXlOZXQuYmxvY2tzdGFja0FQSVVybH0vdjEvbmFtZXMvYWFyb24uaWRgKSlcbiAgICAgIC50aGVuKHJlc3AgPT4gcmVzcC5qc29uKCkpXG4gICAgICAudGhlbigobmFtZUluZm8pID0+IHtcbiAgICAgICAgdC5lcXVhbChteU5ldC5jb2VyY2VBZGRyZXNzKG5hbWVJbmZvLmFkZHJlc3MpLCB0cmFuc2ZlckRlc3RpbmF0aW9uLFxuICAgICAgICAgICAgICAgIGBhYXJvbi5pZCBzaG91bGQgYmUgb3duZWQgYnkgJHt0cmFuc2ZlckRlc3RpbmF0aW9ufWApXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gdHJhbnNhY3Rpb25zLm1ha2VSZW5ld2FsKCdhYXJvbi5pZCcsIHJlbmV3YWxEZXN0aW5hdGlvbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWNvbmRPd25lciwgcGF5ZXIsIHJlbmV3YWxaRikpXG4gICAgICAudGhlbihyYXd0eCA9PiBteU5ldC5icm9hZGNhc3RUcmFuc2FjdGlvbihyYXd0eCkpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdSRU5FV0FMIGJyb2FkY2FzdGVkLCB3YWl0aW5nIDMwIHNlY29uZHMuJylcbiAgICAgICAgcmV0dXJuIG5leHRCbG9jaygpXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gbXlOZXQuYnJvYWRjYXN0Wm9uZUZpbGUocmVuZXdhbFpGKSlcbiAgICAgIC50aGVuKCgpID0+IGZldGNoKGAke215TmV0LmJsb2Nrc3RhY2tBUElVcmx9L3YxL25hbWVzL2Fhcm9uLmlkYCkpXG4gICAgICAudGhlbihyZXNwID0+IHJlc3AuanNvbigpKVxuICAgICAgLnRoZW4oKG5hbWVJbmZvKSA9PiB7XG4gICAgICAgIHQuZXF1YWwobmFtZUluZm8uem9uZWZpbGUsIHJlbmV3YWxaRiwgJ3pvbmVmaWxlIHNob3VsZCBiZSB1cGRhdGVkJylcbiAgICAgICAgdC5lcXVhbChteU5ldC5jb2VyY2VBZGRyZXNzKG5hbWVJbmZvLmFkZHJlc3MpLCByZW5ld2FsRGVzdGluYXRpb24sXG4gICAgICAgICAgICAgICAgYGFhcm9uLmlkIHNob3VsZCBiZSBvd25lZCBieSAke3JlbmV3YWxEZXN0aW5hdGlvbn1gKVxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHRyYW5zYWN0aW9ucy5tYWtlQml0Y29pblNwZW5kKGJ0Y0Rlc3RBZGRyZXNzLCBwYXllciwgNTAwMDAwKSlcbiAgICAgIC50aGVuKHJhd3R4ID0+IG15TmV0LmJyb2FkY2FzdFRyYW5zYWN0aW9uKHJhd3R4KSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ2Jyb2FkY2FzdGVkIFNQRU5ELCB3YWl0aW5nIDEwIHNlY29uZHMuJylcbiAgICAgICAgcmV0dXJuIG5leHRCbG9jaygpXG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4gbXlOZXQuZ2V0VVRYT3MoYnRjRGVzdEFkZHJlc3MpKVxuICAgICAgLnRoZW4oKHV0eG9zKSA9PiB7XG4gICAgICAgIHQuZXF1YWwodXR4b3MubGVuZ3RoLCAxLCBgRGVzdGluYXRpb24gYWRkcmVzcyAke2J0Y0Rlc3RBZGRyZXNzfSBzaG91bGQgaGF2ZSAxIFVUWE9gKVxuICAgICAgICBjb25zdCBzYXRvc2hpcyA9IHV0eG9zLnJlZHVjZSgoYWdnLCB1dHhvKSA9PiBhZ2cgKyB1dHhvLnZhbHVlLCAwKVxuICAgICAgICBjb25zb2xlLmxvZyhgJHtidGNEZXN0QWRkcmVzc30gaGFzICR7c2F0b3NoaXN9IHNhdG9zaGlzYClcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiBzaHV0ZG93bkJsb2Nrc3RhY2tDb3JlKCkpXG4gICAgICAudGhlbigoKSA9PiB0LnBhc3MoJ0ZpbmlzaGVkIHRlc3QnKSlcbiAgfSlcblxuICB0ZXN0KCdoZWxsb05hbWVzcGFjZScsICh0KSA9PiB7XG4gICAgdC5wbGFuKDExKVxuXG4gICAgY29uZmlnLm5ldHdvcmsgPSBuZXR3b3JrLmRlZmF1bHRzLkxPQ0FMX1JFR1RFU1RcbiAgICBjb25zdCBteU5ldCA9IGNvbmZpZy5uZXR3b3JrXG5cbiAgICBjb25zdCBuc1BheSA9ICc2ZTUwNDMxYjk1NWZlNzNmMDc5NDY5YjI0ZjA2NDgwYWVlNDRlNDUxOTI4MjY4NjQzMzE5NWIzYzRiNTMzNmVmMDEnXG4gICAgY29uc3QgbnNSZXZlYWwgPSAnYzI0NDY0MmNlMGI0ZWI2OGRhOGUwOThmYWNmY2FkODg5ZTMwNjNjMzZhNjhiNzk1MWZiNGMwODVkZTQ5ZGYxYjAxJ1xuXG4gICAgY29uc3QgbnNSZXZlYWxBZGRyZXNzID0gaGV4U3RyaW5nVG9FQ1BhaXIobnNSZXZlYWwpLmdldEFkZHJlc3MoKVxuXG4gICAgY29uc3QgZGVzdCA9ICcxOTIzODg0NmFjNjBmYTYyZjhmOGJiODg5OGIwM2RmNzliYzYxMTI2MDAxODFmMzYwNjE4MzVhZDg5MzQwODYwMDEnXG4gICAgY29uc3QgZGVzdEFkZHJlc3MgPSBoZXhTdHJpbmdUb0VDUGFpcihkZXN0KS5nZXRBZGRyZXNzKClcblxuICAgIGNvbnN0IGJ0Y0Rlc3QgPSAnM2FkOWY2OTBjYzc2OTQ1NzJmZTc1NzQ1MjZhZDI2MGZmMmU3MTFkNjA4ZDMyMjQ4OTVlZmQ5MzJiMWQ0N2M3MjAxJ1xuICAgIGNvbnN0IGJ0Y0Rlc3RBZGRyZXNzID0gaGV4U3RyaW5nVG9FQ1BhaXIoYnRjRGVzdCkuZ2V0QWRkcmVzcygpXG5cbiAgICBjb25zdCBwYXllciA9ICdiYjY4ZWRhOTg4ZTc2ODEzMmJjNmM3Y2E3M2E4N2ZiOWIwOTE4ZTlhMzhkMzYxOGI3NDA5OWJlMjVmN2NhYjdkMDEnXG5cbiAgICBjb25zdCBzZWNvbmRPd25lciA9ICc1NDE2NDY5M2UzODAzMjIzZjdmYTlhMDA0OTk3YmZiZjE0NzVmNWM0NGY2NTU5M2ZhNDVjNjc4MzA4NmRhZmVjMDEnXG4gICAgY29uc3QgdHJhbnNmZXJEZXN0aW5hdGlvbiA9IGhleFN0cmluZ1RvRUNQYWlyKHNlY29uZE93bmVyKS5nZXRBZGRyZXNzKClcblxuICAgIGNvbnN0IHJlbmV3YWxLZXkgPSAnYmI2OGVkYTk4OGU3NjgxMzJiYzZjN2NhNzNhODdmYjliMDkxOGU5YTM4ZDM2MThiNzQwOTliZTI1ZjdjYWI3ZCdcbiAgICBjb25zdCByZW5ld2FsRGVzdGluYXRpb24gPSBoZXhTdHJpbmdUb0VDUGFpcihyZW5ld2FsS2V5KS5nZXRBZGRyZXNzKClcblxuICAgIGNvbnN0IHpmVGVzdCA9ICckT1JJR0lOIGFhcm9uLmhlbGxvXFxuJFRUTCAzNjAwXFxuX2h0dHAuX3RjcCBVUkkgMTAgMSAnXG4gICAgICAgICAgKyBgXCJodHRwczovL2dhaWEuYmxvY2tzdGFja3Rlc3Qub3JnL2h1Yi8ke2Rlc3RBZGRyZXNzfS8wL3Byb