1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const ava_1 = require("ava");
|
4 | const uuid_1 = require("uuid");
|
5 | const index_1 = require("../index");
|
6 | const aws_faast_1 = require("../src/aws/aws-faast");
|
7 | const util_aws_1 = require("./fixtures/util-aws");
|
8 | const functions = require("./fixtures/functions");
|
9 | const util_1 = require("./fixtures/util");
|
10 | const assert = require("assert");
|
11 | async 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 | }
|
38 | ava_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 | });
|
101 | ava_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 | });
|
139 | ava_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 |