UNPKG

23.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const ava_1 = require("ava");
4const uuid_1 = require("uuid");
5const index_1 = require("../index");
6const aws_faast_1 = require("../src/aws/aws-faast");
7const util_aws_1 = require("./fixtures/util-aws");
8const functions = require("./fixtures/functions");
9const util_1 = require("./fixtures/util");
10const assert = require("assert");
11async function waitForLogGroupCreation(cloudwatch, logGroupName) {
12 while (true) {
13 await (0, util_1.sleep)(1000);
14 try {
15 const described = await cloudwatch
16 .describeLogGroups({ logGroupNamePrefix: logGroupName })
17 .promise();
18 if (!described.logGroups) {
19 continue;
20 }
21 const retrievedLogGroup = described.logGroups[0].logGroupName;
22 assert(retrievedLogGroup === logGroupName, `Unexpected logGroupName: ${retrievedLogGroup}, expecting ${logGroupName}`);
23 const logResult = await cloudwatch
24 .filterLogEvents({ logGroupName })
25 .promise();
26 const events = logResult.events ?? [];
27 for (const event of events) {
28 if (event.message.match(/REPORT RequestId/)) {
29 return;
30 }
31 }
32 }
33 catch (err) {
34 console.error(err);
35 }
36 }
37}
38ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are called"), async (t) => {
39 // Idea behind this test: create a faast module and make a call. Then
40 // cleanup while leaving the resources in place. Then create another faast
41 // module and set its retention to 0, and use a synthetic gc worker to
42 // observe and verify the garbage collector actually cleans up.
43 const mod = await (0, index_1.faastAws)(functions, {
44 gc: "off",
45 mode: "queue",
46 description: t.title,
47 packageJson: {
48 name: (0, uuid_1.v4)(),
49 dependencies: {
50 tslib: "^1.9.1"
51 }
52 },
53 maxRetries: 0
54 });
55 try {
56 await mod.functions.hello("gc-test");
57 const { cloudwatch } = mod.state.services;
58 const { logGroupName } = mod.state.resources;
59 await waitForLogGroupCreation(cloudwatch, logGroupName);
60 await mod.cleanup({ deleteResources: false, gcTimeout: 0 });
61 // Create some work for gc to do by removing the log retention policy, gc
62 // should add it back.
63 const deleteRetentionPolicy = (0, index_1.throttle)({ concurrency: 1, retry: 5 }, () => cloudwatch.deleteRetentionPolicy({ logGroupName }).promise());
64 await deleteRetentionPolicy();
65 let deletedLayer = false;
66 const { layer, FunctionName } = mod.state.resources;
67 const mod2 = await (0, index_1.faastAws)(functions, {
68 gc: "force",
69 retentionInDays: 0,
70 description: t.title,
71 _gcWorker: async (work, services) => {
72 switch (work.type) {
73 case "SetLogRetention":
74 // checkResourcesCleanedUp will verify the log group is
75 // deleted.
76 await (0, aws_faast_1.defaultGcWorker)(work, services);
77 break;
78 case "DeleteLayerVersion":
79 if (work.LayerName === layer.LayerName) {
80 index_1.log.gc(`deleting layer ${work.LayerName}`);
81 await (0, aws_faast_1.defaultGcWorker)(work, services);
82 deletedLayer = true;
83 }
84 break;
85 case "DeleteResources":
86 if (work.resources.FunctionName === FunctionName) {
87 index_1.log.gc(`deleting resources for ${FunctionName}`);
88 await (0, aws_faast_1.defaultGcWorker)(work, services);
89 }
90 }
91 }
92 });
93 await mod2.cleanup({ gcTimeout: 0 });
94 t.true(deletedLayer, "Deleted layer is true");
95 await (0, util_1.checkResourcesCleanedUp)(t, await (0, util_aws_1.getAWSResources)(mod, true));
96 }
97 finally {
98 await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 });
99 }
100});
101ava_1.default.serial((0, util_1.title)("aws", "garbage collects functions that are never called"), async (t) => {
102 const mod = await (0, index_1.faastAws)(functions, {
103 gc: "off",
104 mode: "queue",
105 description: t.title,
106 maxRetries: 0
107 });
108 try {
109 await mod.cleanup({ deleteResources: false, gcTimeout: 0 });
110 const { FunctionName } = mod.state.resources;
111 const mod2 = await (0, index_1.faastAws)(functions, {
112 gc: "force",
113 retentionInDays: 0,
114 description: t.title,
115 _gcWorker: async (work, services) => {
116 switch (work.type) {
117 case "DeleteResources":
118 if (work.resources.FunctionName === FunctionName) {
119 index_1.log.gc(`deleting resources for ${FunctionName}`);
120 await (0, aws_faast_1.defaultGcWorker)(work, services);
121 }
122 }
123 }
124 });
125 await mod2.cleanup({ gcTimeout: 0 });
126 // Don't fail if a log group exists because we didn't wait for its
127 // creation; it might be created by AWS after the cleanup occurs. The
128 // reason is that the log group will only be created if there's an
129 // invocation test, which only happens in the special case that the role
130 // was recently created. Which is true for the nightly testsuite but
131 // rarely elsewhere.
132 const { logGroupResult, ...resources } = await (0, util_aws_1.getAWSResources)(mod, true);
133 await (0, util_1.checkResourcesCleanedUp)(t, resources);
134 }
135 finally {
136 await mod.cleanup({ deleteResources: true, deleteCaches: true, gcTimeout: 0 });
137 }
138});
139ava_1.default.skip((0, util_1.title)("aws", "garbage collection caching"), async (t) => {
140 {
141 // Run a real gc so the build account doesn't accumulate garbage.
142 const mod = await (0, index_1.faastAws)(functions, { gc: "force", description: t.title });
143 await mod.cleanup({ gcTimeout: 0 });
144 t.is(await mod.state.gcPromise, "done");
145 }
146 {
147 // Test the in-memory cache that prevents gc from multiple faast.js
148 // instances from running at the same time.
149 const mod = await (0, index_1.faastAws)(functions, { description: t.title });
150 await mod.cleanup();
151 t.is(await mod.state.gcPromise, "skipped");
152 }
153 {
154 // Test the persistent cache that prevents gc from running too often
155 // even across processes.
156 (0, aws_faast_1.clearLastGc)();
157 const mod = await (0, index_1.faastAws)(functions, { description: t.title });
158 await mod.cleanup();
159 t.is(await mod.state.gcPromise, "skipped");
160 }
161});
162//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWdjLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2F3cy1nYy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQXVCO0FBRXZCLCtCQUFrQztBQUNsQyxvQ0FBbUQ7QUFDbkQsb0RBQW9FO0FBQ3BFLGtEQUFzRDtBQUN0RCxrREFBa0Q7QUFDbEQsMENBQXdFO0FBQ3hFLGlDQUFpQztBQUVqQyxLQUFLLFVBQVUsdUJBQXVCLENBQUMsVUFBMEIsRUFBRSxZQUFvQjtJQUNuRixPQUFPLElBQUksRUFBRTtRQUNULE1BQU0sSUFBQSxZQUFLLEVBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEIsSUFBSTtZQUNBLE1BQU0sU0FBUyxHQUFHLE1BQU0sVUFBVTtpQkFDN0IsaUJBQWlCLENBQUMsRUFBRSxrQkFBa0IsRUFBRSxZQUFZLEVBQUUsQ0FBQztpQkFDdkQsT0FBTyxFQUFFLENBQUM7WUFDZixJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRTtnQkFDdEIsU0FBUzthQUNaO1lBQ0QsTUFBTSxpQkFBaUIsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQztZQUM5RCxNQUFNLENBQ0YsaUJBQWlCLEtBQUssWUFBWSxFQUNsQyw0QkFBNEIsaUJBQWlCLGVBQWUsWUFBWSxFQUFFLENBQzdFLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxNQUFNLFVBQVU7aUJBQzdCLGVBQWUsQ0FBQyxFQUFFLFlBQVksRUFBRSxDQUFDO2lCQUNqQyxPQUFPLEVBQUUsQ0FBQztZQUNmLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1lBQ3RDLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFO2dCQUN4QixJQUFJLEtBQUssQ0FBQyxPQUFRLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLEVBQUU7b0JBQzFDLE9BQU87aUJBQ1Y7YUFDSjtTQUNK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LGlFQUFpRTtRQUNqRSxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUEsZ0JBQVEsRUFBQyxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUM3RSxNQUFNLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNwQyxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7S0FDM0M7SUFFRDtRQUNJLG1FQUFtRTtRQUNuRSwyQ0FBMkM7UUFDM0MsTUFBTSxHQUFHLEdBQUcsTUFBTSxJQUFBLGdCQUFRLEVBQUMsU0FBUyxFQUFFLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztLQUM5QztJQUVEO1FBQ0ksb0VBQW9FO1FBQ3BFLHlCQUF5QjtRQUN6QixJQUFBLHVCQUFXLEdBQUUsQ0FBQztRQUNkLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBQSxnQkFBUSxFQUFDLFNBQVMsRUFBRSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNoRSxNQUFNLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7S0FDOUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0ZXN0IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IENsb3VkV2F0Y2hMb2dzIH0gZnJvbSBcImF3cy1zZGtcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWQgfSBmcm9tIFwidXVpZFwiO1xuaW1wb3J0IHsgZmFhc3RBd3MsIGxvZywgdGhyb3R0bGUgfSBmcm9tIFwiLi4vaW5kZXhcIjtcbmltcG9ydCB7IGRlZmF1bHRHY1dvcmtlciwgY2xlYXJMYXN0R2MgfSBmcm9tIFwiLi4vc3JjL2F3cy9hd3MtZmFhc3RcIjtcbmltcG9ydCB7IGdldEFXU1Jlc291cmNlcyB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWwtYXdzXCI7XG5pbXBvcnQgKiBhcyBmdW5jdGlvbnMgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBjaGVja1Jlc291cmNlc0NsZWFuZWRVcCwgc2xlZXAsIHRpdGxlIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbFwiO1xuaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gXCJhc3NlcnRcIjtcblxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvckxvZ0dyb3VwQ3JlYXRpb24oY2xvdWR3YXRjaDogQ2xvdWRXYXRjaExvZ3MsIGxvZ0dyb3VwTmFtZTogc3RyaW5nKSB7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgYXdhaXQgc2xlZXAoMTAwMCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBkZXNjcmliZWQgPSBhd2FpdCBjbG91ZHdhdGNoXG4gICAgICAgICAgICAgICAgLmRlc2NyaWJlTG9nR3JvdXBzKHsgbG9nR3JvdXBOYW1lUHJlZml4OiBsb2dHcm91cE5hbWUgfSlcbiAgICAgICAgICAgICAgICAucHJvbWlzZSgpO1xuICAgICAgICAgICAgaWYgKCFkZXNjcmliZWQubG9nR3JvdXBzKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXRyaWV2ZWRMb2dHcm91cCA9IGRlc2NyaWJlZC5sb2dHcm91cHNbMF0ubG9nR3JvdXBOYW1lO1xuICAgICAgICAgICAgYXNzZXJ0KFxuICAgICAgICAgICAgICAgIHJldHJpZXZlZExvZ0dyb3VwID09PSBsb2dHcm91cE5hbWUsXG4gICAgICAgICAgICAgICAgYFVuZXhwZWN0ZWQgbG9nR3JvdXBOYW1lOiAke3JldHJpZXZlZExvZ0dyb3VwfSwgZXhwZWN0aW5nICR7bG9nR3JvdXBOYW1lfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBsb2dSZXN1bHQgPSBhd2FpdCBjbG91ZHdhdGNoXG4gICAgICAgICAgICAgICAgLmZpbHRlckxvZ0V2ZW50cyh7IGxvZ0dyb3VwTmFtZSB9KVxuICAgICAgICAgICAgICAgIC5wcm9taXNlKCk7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSBsb2dSZXN1bHQuZXZlbnRzID8/IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQubWVzc2FnZSEubWF0Y2goL1JFUE9SVCBSZXF1ZXN0SWQvKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG50ZXN0LnNlcmlhbCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdHMgZnVuY3Rpb25zIHRoYXQgYXJlIGNhbGxlZFwiKSwgYXN5bmMgdCA9PiB7XG4gICAgLy8gSWRlYSBiZWhpbmQgdGhpcyB0ZXN0OiBjcmVhdGUgYSBmYWFzdCBtb2R1bGUgYW5kIG1ha2UgYSBjYWxsLiBUaGVuXG4gICAgLy8gY2xlYW51cCB3aGlsZSBsZWF2aW5nIHRoZSByZXNvdXJjZXMgaW4gcGxhY2UuIFRoZW4gY3JlYXRlIGFub3RoZXIgZmFhc3RcbiAgICAvLyBtb2R1bGUgYW5kIHNldCBpdHMgcmV0ZW50aW9uIHRvIDAsIGFuZCB1c2UgYSBzeW50aGV0aWMgZ2Mgd29ya2VyIHRvXG4gICAgLy8gb2JzZXJ2ZSBhbmQgdmVyaWZ5IHRoZSBnYXJiYWdlIGNvbGxlY3RvciBhY3R1YWxseSBjbGVhbnMgdXAuXG4gICAgY29uc3QgbW9kID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICBwYWNrYWdlSnNvbjoge1xuICAgICAgICAgICAgbmFtZTogdXVpZCgpLFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiB7XG4gICAgICAgICAgICAgICAgdHNsaWI6IFwiXjEuOS4xXCJcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbWF4UmV0cmllczogMFxuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IG1vZC5mdW5jdGlvbnMuaGVsbG8oXCJnYy10ZXN0XCIpO1xuICAgICAgICBjb25zdCB7IGNsb3Vkd2F0Y2ggfSA9IG1vZC5zdGF0ZS5zZXJ2aWNlcztcbiAgICAgICAgY29uc3QgeyBsb2dHcm91cE5hbWUgfSA9IG1vZC5zdGF0ZS5yZXNvdXJjZXM7XG4gICAgICAgIGF3YWl0IHdhaXRGb3JMb2dHcm91cENyZWF0aW9uKGNsb3Vkd2F0Y2gsIGxvZ0dyb3VwTmFtZSk7XG4gICAgICAgIGF3YWl0IG1vZC5jbGVhbnVwKHsgZGVsZXRlUmVzb3VyY2VzOiBmYWxzZSwgZ2NUaW1lb3V0OiAwIH0pO1xuXG4gICAgICAgIC8vIENyZWF0ZSBzb21lIHdvcmsgZm9yIGdjIHRvIGRvIGJ5IHJlbW92aW5nIHRoZSBsb2cgcmV0ZW50aW9uIHBvbGljeSwgZ2NcbiAgICAgICAgLy8gc2hvdWxkIGFkZCBpdCBiYWNrLlxuICAgICAgICBjb25zdCBkZWxldGVSZXRlbnRpb25Qb2xpY3kgPSB0aHJvdHRsZSh7IGNvbmN1cnJlbmN5OiAxLCByZXRyeTogNSB9LCAoKSA9PlxuICAgICAgICAgICAgY2xvdWR3YXRjaC5kZWxldGVSZXRlbnRpb25Qb2xpY3koeyBsb2dHcm91cE5hbWUgfSkucHJvbWlzZSgpXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IGRlbGV0ZVJldGVudGlvblBvbGljeSgpO1xuXG4gICAgICAgIGxldCBkZWxldGVkTGF5ZXIgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgeyBsYXllciwgRnVuY3Rpb25OYW1lIH0gPSBtb2Quc3RhdGUucmVzb3VyY2VzO1xuICAgICAgICBjb25zdCBtb2QyID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgICAgICBnYzogXCJmb3JjZVwiLFxuICAgICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiAwLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGUsXG4gICAgICAgICAgICBfZ2NXb3JrZXI6IGFzeW5jICh3b3JrLCBzZXJ2aWNlcykgPT4ge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAod29yay50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJTZXRMb2dSZXRlbnRpb25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrUmVzb3VyY2VzQ2xlYW5lZFVwIHdpbGwgdmVyaWZ5IHRoZSBsb2cgZ3JvdXAgaXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJEZWxldGVMYXllclZlcnNpb25cIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrLkxheWVyTmFtZSA9PT0gbGF5ZXIhLkxheWVyTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgZGVsZXRpbmcgbGF5ZXIgJHt3b3JrLkxheWVyTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZWRMYXllciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcIkRlbGV0ZVJlc291cmNlc1wiOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdvcmsucmVzb3VyY2VzLkZ1bmN0aW9uTmFtZSA9PT0gRnVuY3Rpb25OYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nLmdjKGBkZWxldGluZyByZXNvdXJjZXMgZm9yICR7RnVuY3Rpb25OYW1lfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IGRlZmF1bHRHY1dvcmtlcih3b3JrLCBzZXJ2aWNlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCBtb2QyLmNsZWFudXAoeyBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIHQudHJ1ZShkZWxldGVkTGF5ZXIsIFwiRGVsZXRlZCBsYXllciBpcyB0cnVlXCIpO1xuICAgICAgICBhd2FpdCBjaGVja1Jlc291cmNlc0NsZWFuZWRVcCh0LCBhd2FpdCBnZXRBV1NSZXNvdXJjZXMobW9kLCB0cnVlKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IHRydWUsIGRlbGV0ZUNhY2hlczogdHJ1ZSwgZ2NUaW1lb3V0OiAwIH0pO1xuICAgIH1cbn0pO1xuXG50ZXN0LnNlcmlhbCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdHMgZnVuY3Rpb25zIHRoYXQgYXJlIG5ldmVyIGNhbGxlZFwiKSwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3QgbW9kID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBtb2RlOiBcInF1ZXVlXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICBtYXhSZXRyaWVzOiAwXG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IGZhbHNlLCBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIGNvbnN0IHsgRnVuY3Rpb25OYW1lIH0gPSBtb2Quc3RhdGUucmVzb3VyY2VzO1xuICAgICAgICBjb25zdCBtb2QyID0gYXdhaXQgZmFhc3RBd3MoZnVuY3Rpb25zLCB7XG4gICAgICAgICAgICBnYzogXCJmb3JjZVwiLFxuICAgICAgICAgICAgcmV0ZW50aW9uSW5EYXlzOiAwLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGUsXG4gICAgICAgICAgICBfZ2NXb3JrZXI6IGFzeW5jICh3b3JrLCBzZXJ2aWNlcykgPT4ge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAod29yay50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJEZWxldGVSZXNvdXJjZXNcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3b3JrLnJlc291cmNlcy5GdW5jdGlvbk5hbWUgPT09IEZ1bmN0aW9uTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy5nYyhgZGVsZXRpbmcgcmVzb3VyY2VzIGZvciAke0Z1bmN0aW9uTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBkZWZhdWx0R2NXb3JrZXIod29yaywgc2VydmljZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgbW9kMi5jbGVhbnVwKHsgZ2NUaW1lb3V0OiAwIH0pO1xuICAgICAgICAvLyBEb24ndCBmYWlsIGlmIGEgbG9nIGdyb3VwIGV4aXN0cyBiZWNhdXNlIHdlIGRpZG4ndCB3YWl0IGZvciBpdHNcbiAgICAgICAgLy8gY3JlYXRpb247IGl0IG1pZ2h0IGJlIGNyZWF0ZWQgYnkgQVdTIGFmdGVyIHRoZSBjbGVhbnVwIG9jY3Vycy4gVGhlXG4gICAgICAgIC8vIHJlYXNvbiBpcyB0aGF0IHRoZSBsb2cgZ3JvdXAgd2lsbCBvbmx5IGJlIGNyZWF0ZWQgaWYgdGhlcmUncyBhblxuICAgICAgICAvLyBpbnZvY2F0aW9uIHRlc3QsIHdoaWNoIG9ubHkgaGFwcGVucyBpbiB0aGUgc3BlY2lhbCBjYXNlIHRoYXQgdGhlIHJvbGVcbiAgICAgICAgLy8gd2FzIHJlY2VudGx5IGNyZWF0ZWQuIFdoaWNoIGlzIHRydWUgZm9yIHRoZSBuaWdodGx5IHRlc3RzdWl0ZSBidXRcbiAgICAgICAgLy8gcmFyZWx5IGVsc2V3aGVyZS5cbiAgICAgICAgY29uc3QgeyBsb2dHcm91cFJlc3VsdCwgLi4ucmVzb3VyY2VzIH0gPSBhd2FpdCBnZXRBV1NSZXNvdXJjZXMobW9kLCB0cnVlKTtcbiAgICAgICAgYXdhaXQgY2hlY2tSZXNvdXJjZXNDbGVhbmVkVXAodCwgcmVzb3VyY2VzKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBtb2QuY2xlYW51cCh7IGRlbGV0ZVJlc291cmNlczogdHJ1ZSwgZGVsZXRlQ2FjaGVzOiB0cnVlLCBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgfVxufSk7XG5cbnRlc3Quc2tpcCh0aXRsZShcImF3c1wiLCBcImdhcmJhZ2UgY29sbGVjdGlvbiBjYWNoaW5nXCIpLCBhc3luYyB0ID0+IHtcbiAgICB7XG4gICAgICAgIC8vIFJ1biBhIHJlYWwgZ2Mgc28gdGhlIGJ1aWxkIGFjY291bnQgZG9lc24ndCBhY2N1bXVsYXRlIGdhcmJhZ2UuXG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBnYzogXCJmb3JjZVwiLCBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoeyBnY1RpbWVvdXQ6IDAgfSk7XG4gICAgICAgIHQuaXMoYXdhaXQgbW9kLnN0YXRlLmdjUHJvbWlzZSwgXCJkb25lXCIpO1xuICAgIH1cblxuICAgIHtcbiAgICAgICAgLy8gVGVzdCB0aGUgaW4tbWVtb3J5IGNhY2hlIHRoYXQgcHJldmVudHMgZ2MgZnJvbSBtdWx0aXBsZSBmYWFzdC5qc1xuICAgICAgICAvLyBpbnN0YW5jZXMgZnJvbSBydW5uaW5nIGF0IHRoZSBzYW1lIHRpbWUuXG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoKTtcbiAgICAgICAgdC5pcyhhd2FpdCBtb2Quc3RhdGUuZ2NQcm9taXNlLCBcInNraXBwZWRcIik7XG4gICAgfVxuXG4gICAge1xuICAgICAgICAvLyBUZXN0IHRoZSBwZXJzaXN0ZW50IGNhY2hlIHRoYXQgcHJldmVudHMgZ2MgZnJvbSBydW5uaW5nIHRvbyBvZnRlblxuICAgICAgICAvLyBldmVuIGFjcm9zcyBwcm9jZXNzZXMuXG4gICAgICAgIGNsZWFyTGFzdEdjKCk7XG4gICAgICAgIGNvbnN0IG1vZCA9IGF3YWl0IGZhYXN0QXdzKGZ1bmN0aW9ucywgeyBkZXNjcmlwdGlvbjogdC50aXRsZSB9KTtcbiAgICAgICAgYXdhaXQgbW9kLmNsZWFudXAoKTtcbiAgICAgICAgdC5pcyhhd2FpdCBtb2Quc3RhdGUuZ2NQcm9taXNlLCBcInNraXBwZWRcIik7XG4gICAgfVxufSk7XG4iXX0=
\No newline at end of file