UNPKG

faastjs

Version:

Serverless batch computing made simple.

176 lines 25.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const ava_1 = tslib_1.__importDefault(require("ava")); const uuid_1 = require("uuid"); const index_1 = require("../index"); const aws_faast_1 = require("../src/aws/aws-faast"); const functions = tslib_1.__importStar(require("./fixtures/functions")); const util_1 = require("./fixtures/util"); const util_aws_1 = require("./fixtures/util-aws"); const assert_1 = tslib_1.__importDefault(require("assert")); async function waitForLogGroupCreation(cloudwatch, logGroupName, message) { let n = 0; while (true) { await (0, util_1.sleep)(1000); try { n++; const described = await cloudwatch.describeLogGroups({ logGroupNamePrefix: logGroupName }); if (!described.logGroups) { continue; } const retrievedLogGroup = described.logGroups?.[0]?.logGroupName; if (!retrievedLogGroup) { continue; } (0, assert_1.default)(retrievedLogGroup === logGroupName, `Unexpected logGroupName: ${retrievedLogGroup}, expecting ${logGroupName}`); const logResult = await cloudwatch.filterLogEvents({ logGroupName }); const events = logResult.events ?? []; // console.log(`[${n}] Found log group: ${logGroupName}`); let foundMessage = false; for (const event of events) { // console.log( // `[${n}] ${event.logStreamName} ${event.eventId} ${event.timestamp} ${event.message}` // ); if (event.message.includes(message)) { foundMessage = true; } if (foundMessage && event.message.match(/REPORT RequestId/)) { return; } } } catch (err) { console.error(`Transient error waiting for log group creation: ${err}`); } } } ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are called"), async (t) => { // Idea behind this test: create a faast module and make a call. Then // cleanup while leaving the resources in place. Then create another faast // module and set its retention to 0, and use a synthetic gc worker to // observe and verify the garbage collector actually cleans up. const mod = await (0, index_1.faastAws)(functions, { gc: "off", mode: "queue", description: t.title, packageJson: { name: (0, uuid_1.v4)(), dependencies: { tslib: "^1.9.1" } }, maxRetries: 0 }); try { await mod.functions.consoleLog("gc-test-string"); const { cloudwatch } = mod.state.services; const { logGroupName } = mod.state.resources; await waitForLogGroupCreation(cloudwatch, logGroupName, "gc-test-string"); await mod.cleanup({ deleteResources: false, gcTimeout: 0 }); // Create some work for gc to do by removing the log retention policy, gc // should add it back. const deleteRetentionPolicy = (0, index_1.throttle)({ concurrency: 1, retry: 5 }, () => cloudwatch.deleteRetentionPolicy({ logGroupName })); await deleteRetentionPolicy(); let deletedLayer = false; const { layer, FunctionName } = mod.state.resources; // log.gc.enabled = true; const mod2 = await (0, index_1.faastAws)(functions, { gc: "force", retentionInDays: 0, description: t.title, _gcWorker: async (work, services) => { switch (work.type) { case "SetLogRetention": // checkResourcesCleanedUp will verify the log group is // deleted. await (0, aws_faast_1.defaultGcWorker)(work, services); break; case "DeleteLayerVersion": if (work.LayerName === layer.LayerName) { index_1.log.gc(`deleting layer ${work.LayerName}`); await (0, aws_faast_1.defaultGcWorker)(work, services); deletedLayer = true; } break; case "DeleteResources": if (work.resources.FunctionName === FunctionName) { index_1.log.gc(`deleting resources for ${FunctionName}`); await (0, aws_faast_1.defaultGcWorker)(work, services); } } } }); await mod2.cleanup({ gcTimeout: 0 }); t.true(deletedLayer, "Deleted layer is true"); await (0, util_1.checkResourcesCleanedUp)(t, await (0, util_aws_1.getAWSResources)(mod, true)); } finally { index_1.log.gc.enabled = false; await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 }); } }); ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are never called"), async (t) => { const mod = await (0, index_1.faastAws)(functions, { gc: "off", mode: "queue", description: t.title, maxRetries: 0 }); try { await mod.cleanup({ deleteResources: false, gcTimeout: 0 }); const { FunctionName } = mod.state.resources; const mod2 = await (0, index_1.faastAws)(functions, { gc: "force", retentionInDays: 0, description: t.title, _gcWorker: async (work, services) => { switch (work.type) { case "DeleteResources": if (work.resources.FunctionName === FunctionName) { index_1.log.gc(`deleting resources for ${FunctionName}`); await (0, aws_faast_1.defaultGcWorker)(work, services); } } } }); await mod2.cleanup({ gcTimeout: 0 }); // Don't fail if a log group exists because we didn't wait for its // creation; it might be created by AWS after the cleanup occurs. The // reason is that the log group will only be created if there's an // invocation test, which only happens in the special case that the role // was recently created. Which is true for the nightly testsuite but // rarely elsewhere. const { logGroupResult, ...resources } = await (0, util_aws_1.getAWSResources)(mod, true); await (0, util_1.checkResourcesCleanedUp)(t, resources); } finally { await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 }); } }); ava_1.default.skip((0, util_1.title)("aws", "garbage collection caching"), async (t) => { { // Run a real gc so the build account doesn't accumulate garbage. const mod = await (0, index_1.faastAws)(functions, { gc: "force", description: t.title }); await mod.cleanup({ gcTimeout: 0 }); t.is(await mod.state.gcPromise, "done"); } { // Test the in-memory cache that prevents gc from multiple faast.js // instances from running at the same time. const mod = await (0, index_1.faastAws)(functions, { description: t.title }); await mod.cleanup(); t.is(await mod.state.gcPromise, "skipped"); } { // Test the persistent cache that prevents gc from running too often // even across processes. (0, aws_faast_1.clearLastGc)(); const mod = await (0, index_1.faastAws)(functions, { description: t.title }); await mod.cleanup(); t.is(await mod.state.gcPromise, "skipped"); } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWdjLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2F3cy1nYy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHNEQUF1QjtBQUN2QiwrQkFBa0M7QUFDbEMsb0NBQW1EO0FBQ25ELG9EQUFvRTtBQUNwRSx3RUFBa0Q7QUFDbEQsMENBQXdFO0FBQ3hFLGtEQUFzRDtBQUN0RCw0REFBNEI7QUFFNUIsS0FBSyxVQUFVLHVCQUF1QixDQUNsQyxVQUEwQixFQUMxQixZQUFvQixFQUNwQixPQUFlO0lBRWYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsT0FBTyxJQUFJLEVBQUU7UUFDVCxNQUFNLElBQUEsWUFBSyxFQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2xCLElBQUk7WUFDQSxDQUFDLEVBQUUsQ0FBQztZQUNKLE1BQU0sU0FBUyxHQUFHLE1BQU0sVUFBVSxDQUFDLGlCQUFpQixDQUFDO2dCQUNqRCxrQkFBa0IsRUFBRSxZQUFZO2FBQ25DLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFO2dCQUN0QixTQUFTO2FBQ1o7WUFDRCxNQUFNLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLENBQUM7WUFDakUsSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNwQixTQUFTO2FBQ1o7WUFDRCxJQUFBLGdCQUFNLEVBQ0YsaUJBQWlCLEtBQUssWUFBWSxFQUNsQyw0QkFBNEIsaUJBQWlCLGVBQWUsWUFBWSxFQUFFLENBQzdFLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1lBQ3JFLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1lBQ3RDLDBEQUEwRDtZQUMxRCxJQUFJLFlBQVksR0FBRyxLQUFL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QUFFLENBQUM7UUFDZCxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUEsZ0JBQVEsRUFBQyxTQUFTLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDaEUsTUFBTSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0tBQzlDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDbG91ZFdhdGNoTG9ncyB9IGZyb20gXCJAYXdzLXNkay9jbGllbnQtY2xvdWR3YXRjaC1sb2dzXCI7XG5pbXBvcnQgdGVzdCBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB7IGZhYXN0QXdzLCBsb2csIHRocm90dGxlIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgeyBjbGVhckxhc3RHYywgZGVmYXVsdEdjV29ya2VyIH0gZnJvbSBcIi4uL3NyYy9hd3MvYXdzLWZhYXN0XCI7XG5pbXBvcnQgKiBhcyBmdW5jdGlvbnMgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBjaGVja1Jlc291cmNlc0NsZWFuZWRVcCwgc2xlZXAsIHRpdGxlIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbFwiO1xuaW1wb3J0IHsgZ2V0QVdTUmVzb3VyY2VzIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbC1hd3NcIjtcbmltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuXG5hc3luYyBmdW5jdGlvbiB3YWl0Rm9yTG9nR3JvdXBDcmVhdGlvbihcbiAgICBjbG91ZHdhdGNoOiBDbG91ZFdhdGNoTG9ncyxcbiAgICBsb2dHcm91cE5hbWU6IHN0cmluZyxcbiAgICBtZXNzYWdlOiBzdHJpbmdcbikge1xuICAgIGxldCBuID0gMDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBhd2FpdCBzbGVlcCgxMDAwKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG4rKztcbiAgICAgICAgICAgIGNvbnN0IGRlc2NyaWJlZCA9IGF3YWl0IGNsb3Vkd2F0Y2guZGVzY3JpYmVMb2dHcm91cHMoe1xuICAgICAgICAgICAgICAgIGxvZ0dyb3VwTmFtZVByZWZpeDogbG9nR3JvdXBOYW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICghZGVzY3JpYmVkLmxvZ0dyb3Vwcykge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcmV0cmlldmVkTG9nR3JvdXAgPSBkZXNjcmliZWQubG9nR3JvdXBzPy5bMF0/LmxvZ0dyb3VwTmFtZTtcbiAgICAgICAgICAgIGlmICghcmV0cmlldmVkTG9nR3JvdXApIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChcbiAgICAgICAgICAgICAgICByZXRyaWV2ZWRMb2dHcm91cCA9PT0gbG9nR3JvdXBOYW1lLFxuICAgICAgICAgICAgICAgIGBVbmV4cGVjdGVkIGxvZ0dyb3VwTmFtZTogJHtyZXRyaWV2ZWRMb2dHcm91cH0sIGV4cGVjdGluZyAke2xvZ0dyb3VwTmFtZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgbG9nUmVzdWx0ID0gYXdhaXQgY2xvdWR3YXRjaC5maWx0ZXJMb2dFdmVudHMoeyBsb2dHcm91cE5hbWUgfSk7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSBsb2dSZXN1bHQuZXZlbnRzID8/IFtdO1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYFske259XSBGb3VuZCBsb2cgZ3JvdXA6ICR7bG9nR3JvdXBOYW1lfWApO1xuICAgICAgICAgICAgbGV0IGZvdW5kTWVzc2FnZSA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAvLyAgICAgYFske259XSAke2V2ZW50LmxvZ1N0cmVhbU5hbWV9ICR7ZXZlbnQuZXZlbnRJZH0gJHtldmVudC50aW1lc3RhbXB9ICR7ZXZlbnQubWVzc2FnZX1gXG4gICAgICAgICAgICAgICAgLy8gKTtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQubWVzc2FnZSEuaW5jbHVkZXMobWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm91bmRNZXNzYWdlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGZvdW5kTWVzc2FnZSAmJiBldmVudC5tZXNzYWdlIS5tYXRjaCgvUkVQT1JUIFJlcXVlc3RJZC8pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBUcmFuc2llbnQgZXJyb3Igd2FpdGluZyBmb3IgbG9nIGdyb3VwIGNyZWF0aW9uOiAke2Vycn1gKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxudGVzdC5zZXJpYWwodGl0bGUoXCJhd3NcIiwgXCJnYXJiYWdlIGNvbGxlY3RzIGZ1bmN0aW9ucyB0aGF0IGFyZSBjYWxsZWRcIiksIGFzeW5jIHQgPT4ge1xuICAgIC8vIElkZWEgYmVoaW5kIHRoaXMgdGVzdDogY3JlYXRlIGEgZmFhc3QgbW9kdWxlIGFuZCBtYWtlIGEgY2FsbC4gVGhlblxuICAgIC8vIGNsZWFudXAgd2hpbGUgbGVhdmluZyB0aGUgcmVzb3VyY2VzIGluIHBsYWNlLiBUaGVuIGNyZWF0ZSBhbm90aGVyIGZhYXN0XG4gICAgLy8gbW9kdWxlIGFuZCBzZXQgaXRzIHJldGVudGlvbiB0byAwLCBhbmQgdXNlIGEgc3ludGhldGljIGdjIHdvcmtlciB0b1xuICAgIC8vIG9ic2VydmUgYW5kIHZlcmlmeSB0aGUgZ2FyYmFnZSBjb2xsZWN0b3IgYWN0dWFsbHkgY2xlYW5zIHVwLlxuICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywge1xuICAgICAgICBnYzogXCJvZmZcIixcbiAgICAgICAgbW9kZTogXCJxdWV1ZVwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZSxcbiAgICAgICAgcGFja2FnZUpzb246IHtcbiAgICAgICAgICAgIG5hbWU6IHV1aWQoKSxcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczoge1xuICAgICAgICAgICAgICAgIHRzbGliOiBcIl4xLjkuMVwiXG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG1heFJldHJpZXM6IDBcbiAgICB9KTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBtb2QuZnVuY3Rpb25zLmNvbnNvbGVMb2coXCJnYy10ZXN0LXN0cmluZ1wiKTtcbiAgICAgICAgY29uc3QgeyBjbG91ZHdhdGNoIH0gPSBtb2Quc3RhdGUuc2VydmljZXM7XG4gICAgICAgIGNvbnN0IHsgbG9nR3JvdXBOYW1lIH0gPSBtb2Quc3RhdGUucmVzb3VyY2VzO1xuICAgICAgICBhd2FpdCB3YWl0Rm9yTG9nR3JvdXBDcmVhdGlvbihjbG91ZHdhdGNoLCBsb2dHcm91cE5hbWUsIFwiZ2MtdGVzdC1zdHJpbmdcIik7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKHsgZGVsZXRlUmVzb3VyY2VzOiBmYWxzZSwgZ2NUaW1lb3V0OiAwIH0pO1xuXG4gICAgICAgIC8vIENyZWF0ZSBzb21lIHdvcmsgZm9yIGdjIHRvIGRvIGJ5IHJlbW92aW5nIHRoZSBsb2cgcmV0ZW50aW9uIHBvbGljeSwgZ2NcbiAgICAgICAgLy8gc2hvdWxkIGFkZCBpdCBiYWNrLlxuICAgICAgICBjb25zdCBkZWxldGVSZXRlbnRpb25Qb2xpY3kgPSB0aHJvdHRsZSh7IGNvbmN1cnJlbmN5OiAxLCByZXRyeTogNSB9LCAoKSA9PlxuICAgICAgICAgICAgY2xvdWR3YXRjaC5kZWxldGVSZXRlbnRpb25Qb2xpY3koeyBsb2dHcm91cE5hbWUgfSlcbiAgICAgICAgKTtcbiAgICAgICAgYXdhaXQgZGVsZXRlUmV0ZW50aW9uUG9saWN5KCk7XG5cbiAgICAgICAgbGV0IGRlbGV0ZWRMYXllciA9IGZhbHNlO1xuICAgICAgICBjb25zdCB7IGxheWVyLCBGdW5jdGlvbk5hbWUgfSA9IG1vZC5zdGF0ZS5yZXNvdXJjZXM7XG4gICAgICAgIC8vIGxvZy5nYy5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgY29uc3QgbW9kMiA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywge1xuICAgICAgICAgICAgZ2M6IFwiZm9yY2VcIixcbiAgICAgICAgICAgIHJldGVudGlvbkluRGF5czogMCxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICAgICAgX2djV29ya2VyOiBhc3luYyAod29yaywgc2VydmljZXMpID0+IHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHdvcmsudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiU2V0TG9nUmV0ZW50aW9uXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjaGVja1Jlc291cmNlc0NsZWFuZWRVcCB3aWxsIHZlcmlmeSB0aGUgbG9nIGdyb3VwIGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZGVmYXVsdEdjV29ya2VyKHdvcmssIHNlcnZpY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiRGVsZXRlTGF5ZXJWZXJzaW9uXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod29yay5MYXllck5hbWUgPT09IGxheWVyIS5MYXllck5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2cuZ2MoYGRlbGV0aW5nIGxheWVyICR7d29yay5MYXllck5hbWV9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZGVmYXVsdEdjV29ya2VyKHdvcmssIHNlcnZpY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGVkTGF5ZXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJEZWxldGVSZXNvdXJjZXNcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrLnJlc291cmNlcy5GdW5jdGlvbk5hbWUgPT09IEZ1bmN0aW9uTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgZGVsZXRpbmcgcmVzb3VyY2VzIGZvciAke0Z1bmN0aW9uTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgbW9kMi5jbGVhbnVwKHsgZ2NUaW1lb3V0OiAwIH0pO1xuICAgICAgICB0LnRydWUoZGVsZXRlZExheWVyLCBcIkRlbGV0ZWQgbGF5ZXIgaXMgdHJ1ZVwiKTtcbiAgICAgICAgYXdhaXQgY2hlY2tSZXNvdXJjZXNDbGVhbmVkVXAodCwgYXdhaXQgZ2V0QVdTUmVzb3VyY2VzKG1vZCwgdHJ1ZSkpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGxvZy5nYy5lbmFibGVkID0gZmFsc2U7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKHsgZGVsZXRlUmVzb3VyY2VzOiB0cnVlLCBkZWxldGVDYWNoZXM6IHRydWUsIGdjVGltZW91dDogMCB9KTtcbiAgICB9XG59KTtcblxudGVzdC5zZXJpYWwodGl0bGUoXCJhd3NcIiwgXCJnYXJiYWdlIGNvbGxlY3RzIGZ1bmN0aW9ucyB0aGF0IGFyZSBuZXZlciBjYWxsZWRcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywge1xuICAgICAgICBnYzogXCJvZmZcIixcbiAgICAgICAgbW9kZTogXCJxdWV1ZVwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZSxcbiAgICAgICAgbWF4UmV0cmllczogMFxuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKHsgZGVsZXRlUmVzb3VyY2VzOiBmYWxzZSwgZ2NUaW1lb3V0OiAwIH0pO1xuICAgICAgICBjb25zdCB7IEZ1bmN0aW9uTmFtZSB9ID0gbW9kLnN0YXRlLnJlc291cmNlcztcbiAgICAgICAgY29uc3QgbW9kMiA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywge1xuICAgICAgICAgICAgZ2M6IFwiZm9yY2VcIixcbiAgICAgICAgICAgIHJldGVudGlvbkluRGF5czogMCxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICAgICAgX2djV29ya2VyOiBhc3luYyAod29yaywgc2VydmljZXMpID0+IHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHdvcmsudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiRGVsZXRlUmVzb3VyY2VzXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod29yay5yZXNvdXJjZXMuRnVuY3Rpb25OYW1lID09PSBGdW5jdGlvbk5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2cuZ2MoYGRlbGV0aW5nIHJlc291cmNlcyBmb3IgJHtGdW5jdGlvbk5hbWV9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgZGVmYXVsdEdjV29ya2VyKHdvcmssIHNlcnZpY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IG1vZDIuY2xlYW51cCh7IGdjVGltZW91dDogMCB9KTtcbiAgICAgICAgLy8gRG9uJ3QgZmFpbCBpZiBhIGxvZyBncm91cCBleGlzdHMgYmVjYXVzZSB3ZSBkaWRuJ3Qgd2FpdCBmb3IgaXRzXG4gICAgICAgIC8vIGNyZWF0aW9uOyBpdCBtaWdodCBiZSBjcmVhdGVkIGJ5IEFXUyBhZnRlciB0aGUgY2xlYW51cCBvY2N1cnMuIFRoZVxuICAgICAgICAvLyByZWFzb24gaXMgdGhhdCB0aGUgbG9nIGdyb3VwIHdpbGwgb25seSBiZSBjcmVhdGVkIGlmIHRoZXJlJ3MgYW5cbiAgICAgICAgLy8gaW52b2NhdGlvbiB0ZXN0LCB3aGljaCBvbmx5IGhhcHBlbnMgaW4gdGhlIHNwZWNpYWwgY2FzZSB0aGF0IHRoZSByb2xlXG4gICAgICAgIC8vIHdhcyByZWNlbnRseSBjcmVhdGVkLiBXaGljaCBpcyB0cnVlIGZvciB0aGUgbmlnaHRseSB0ZXN0c3VpdGUgYnV0XG4gICAgICAgIC8vIHJhcmVseSBlbHNld2hlcmUuXG4gICAgICAgIGNvbnN0IHsgbG9nR3JvdXBSZXN1bHQsIC4uLnJlc291cmNlcyB9ID0gYXdhaXQgZ2V0QVdTUmVzb3VyY2VzKG1vZCwgdHJ1ZSk7XG4gICAgICAgIGF3YWl0IGNoZWNrUmVzb3VyY2VzQ2xlYW5lZFVwKHQsIHJlc291cmNlcyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IHRydWUsIGRlbGV0ZUNhY2hlczogdHJ1ZSwgZ2NUaW1lb3V0OiAwIH0pO1xuICAgIH1cbn0pO1xuXG50ZXN0LnNraXAodGl0bGUoXCJhd3NcIiwgXCJnYXJiYWdlIGNvbGxlY3Rpb24gY2FjaGluZ1wiKSwgYXN5bmMgdCA9PiB7XG4gICAge1xuICAgICAgICAvLyBSdW4gYSByZWFsIGdjIHNvIHRoZSBidWlsZCBhY2NvdW50IGRvZXNuJ3QgYWNjdW11bGF0ZSBnYXJiYWdlLlxuICAgICAgICBjb25zdCBtb2QgPSBhd2FpdCBmYWFzdEF3cyhmdW5jdGlvbnMsIHsgZ2M6IFwiZm9yY2VcIiwgZGVzY3JpcHRpb246IHQudGl0bGUgfSk7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKHsgZ2NUaW1lb3V0OiAwIH0pO1xuICAgICAgICB0LmlzKGF3YWl0IG1vZC5zdGF0ZS5nY1Byb21pc2UsIFwiZG9uZVwiKTtcbiAgICB9XG5cbiAgICB7XG4gICAgICAgIC8vIFRlc3QgdGhlIGluLW1lbW9yeSBjYWNoZSB0aGF0IHByZXZlbnRzIGdjIGZyb20gbXVsdGlwbGUgZmFhc3QuanNcbiAgICAgICAgLy8gaW5zdGFuY2VzIGZyb20gcnVubmluZyBhdCB0aGUgc2FtZSB0aW1lLlxuICAgICAgICBjb25zdCBtb2QgPSBhd2FpdCBmYWFzdEF3cyhmdW5jdGlvbnMsIHsgZGVzY3JpcHRpb246IHQudGl0bGUgfSk7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKCk7XG4gICAgICAgIHQuaXMoYXdhaXQgbW9kLnN0YXRlLmdjUHJvbWlzZSwgXCJza2lwcGVkXCIpO1xuICAgIH1cblxuICAgIHtcbiAgICAgICAgLy8gVGVzdCB0aGUgcGVyc2lzdGVudCBjYWNoZSB0aGF0IHByZXZlbnRzIGdjIGZyb20gcnVubmluZyB0b28gb2Z0ZW5cbiAgICAgICAgLy8gZXZlbiBhY3Jvc3MgcHJvY2Vzc2VzLlxuICAgICAgICBjbGVhckxhc3RHYygpO1xuICAgICAgICBjb25zdCBtb2QgPSBhd2FpdCBmYWFzdEF3cyhmdW5jdGlvbnMsIHsgZGVzY3JpcHRpb246IHQudGl0bGUgfSk7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKCk7XG4gICAgICAgIHQuaXMoYXdhaXQgbW9kLnN0YXRlLmdjUHJvbWlzZSwgXCJza2lwcGVkXCIpO1xuICAgIH1cbn0pO1xuIl19