UNPKG

23 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3/**
4 * The purpose of this test is to check that the trampoline function on AWS can
5 * route calls, invoke the wrapper, and return values correctly, without
6 * actually creating a cloud function. However, it does use real cloud queues.
7 */
8const ava_1 = require("ava");
9const aws_sdk_1 = require("aws-sdk");
10const uuid_1 = require("uuid");
11const aws_faast_1 = require("../src/aws/aws-faast");
12const aws_queue_1 = require("../src/aws/aws-queue");
13const aws_trampoline_1 = require("../src/aws/aws-trampoline");
14const provider_1 = require("../src/provider");
15const serialize_1 = require("../src/serialize");
16const shared_1 = require("../src/shared");
17const wrapper_1 = require("../src/wrapper");
18const funcs = require("./fixtures/functions");
19const util_1 = require("./fixtures/util");
20const sqs = new aws_sdk_1.SQS({ apiVersion: "2012-11-05", region: "us-west-2" });
21process.env.AWS_REGION = "us-west-2";
22process.env.FAAST_SILENT = "true";
23const lambdaContext = {
24 callbackWaitsForEmptyEventLoop: true,
25 awsRequestId: "aws-trampoline-test-awsRequestId",
26 logGroupName: "aws-trampoline-test-logGroupName",
27 logStreamName: "aws-trampoline-test-logStreamName",
28 getRemainingTimeInMillis: () => 1000,
29 functionName: "aws-trampoline-test-functionName",
30 functionVersion: "aws-trampoline-test-functionVersion",
31 invokedFunctionArn: "aws-trampoline-test-invokedFunctionArn",
32 memoryLimitInMB: "1728",
33 done: () => { },
34 fail: _ => { },
35 succeed: (_) => { }
36};
37async function makeResponseQueue() {
38 const QueueName = `faast-${uuid_1.v4()}-test`;
39 const { QueueUrl } = await sqs.createQueue({ QueueName }).promise();
40 return QueueUrl;
41}
42async function deleteResponseQueue(QueueUrl) {
43 try {
44 // Sometimes AWS needs time to propagate the existence of a queue before
45 // deleting it. This manifests as a NonExistentQueue error. Waiting
46 // a short while seems to make this less common.
47 await shared_1.sleep(5000);
48 return await sqs.deleteQueue({ QueueUrl }).promise();
49 }
50 catch (err) {
51 console.error(`Could not delete response queue: ${err}`);
52 throw err;
53 }
54}
55async function getMessages(QueueUrl, kind, nExpected) {
56 const metrics = new aws_faast_1.AwsMetrics();
57 const cancel = new Promise(_ => { });
58 const result = [];
59 while (result.length < nExpected) {
60 const messages = await aws_queue_1.receiveMessages(sqs, QueueUrl, metrics, cancel);
61 result.push(...provider_1.filterMessages(messages.Messages, kind));
62 }
63 return result;
64}
65ava_1.default(util_1.title("aws", "trampoline https mode with promise response"), async (t) => {
66 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
67 const { trampoline } = aws_trampoline_1.makeTrampoline(wrapper);
68 const arg = "promise with https on aws";
69 const name = funcs.identityString.name;
70 const QueueUrl = await makeResponseQueue();
71 try {
72 await trampoline({
73 callId: "42",
74 name,
75 args: serialize_1.serializeFunctionArgs(name, [arg], true),
76 modulePath: "./fixtures/functions",
77 ResponseQueueId: QueueUrl
78 }, lambdaContext);
79 const [msg] = await getMessages(QueueUrl, "promise", 1);
80 util_1.expectMessage(t, msg, "promise", arg);
81 }
82 finally {
83 deleteResponseQueue(QueueUrl);
84 }
85});
86ava_1.default(util_1.title("aws", "trampoline queue mode with promise response"), async (t) => {
87 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
88 const arg = "promise with queue on aws";
89 const QueueUrl = await makeResponseQueue();
90 try {
91 const { trampoline } = aws_trampoline_1.makeTrampoline(wrapper);
92 const name = funcs.identityString.name;
93 const call = {
94 callId: "43",
95 name,
96 args: serialize_1.serializeFunctionArgs(name, [arg], true),
97 modulePath: "./fixtures/functions",
98 ResponseQueueId: QueueUrl
99 };
100 const event = {
101 Records: [
102 {
103 Sns: {
104 Message: serialize_1.serialize(call)
105 }
106 }
107 ]
108 };
109 await trampoline(event, lambdaContext);
110 const [msg] = await getMessages(QueueUrl, "promise", 1);
111 util_1.expectMessage(t, msg, "promise", arg);
112 }
113 finally {
114 await deleteResponseQueue(QueueUrl);
115 }
116});
117ava_1.default(util_1.title("aws", "trampoline https mode with async iterator response"), async (t) => {
118 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
119 const { trampoline } = aws_trampoline_1.makeTrampoline(wrapper);
120 const name = funcs.asyncGenerator.name;
121 const arg = ["async generator with https on aws", "second arg"];
122 const QueueUrl = await makeResponseQueue();
123 try {
124 await trampoline({
125 callId: "44",
126 name,
127 args: serialize_1.serializeFunctionArgs(name, [arg], true),
128 modulePath: "./fixtures/functions",
129 ResponseQueueId: QueueUrl
130 }, lambdaContext);
131 const messages = await getMessages(QueueUrl, "iterator", arg.length + 1);
132 util_1.checkIteratorMessages(t, messages, arg);
133 }
134 finally {
135 await deleteResponseQueue(QueueUrl);
136 }
137});
138ava_1.default(util_1.title("aws", "trampoline queue mode with async iterator response"), async (t) => {
139 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
140 const QueueUrl = await makeResponseQueue();
141 const arg = ["async generator with queue on aws", "second arg"];
142 try {
143 const { trampoline } = aws_trampoline_1.makeTrampoline(wrapper);
144 const name = funcs.asyncGenerator.name;
145 const call = {
146 callId: "45",
147 name,
148 args: serialize_1.serializeFunctionArgs(name, [arg], true),
149 modulePath: "./fixtures/functions",
150 ResponseQueueId: QueueUrl
151 };
152 const event = {
153 Records: [
154 {
155 Sns: {
156 Message: serialize_1.serialize(call)
157 }
158 }
159 ]
160 };
161 await trampoline(event, lambdaContext);
162 const messages = await getMessages(QueueUrl, "iterator", arg.length + 1);
163 util_1.checkIteratorMessages(t, messages, arg);
164 }
165 finally {
166 await deleteResponseQueue(QueueUrl);
167 }
168});
169//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLXRyYW1wb2xpbmUudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3Rlc3QvYXdzLXRyYW1wb2xpbmUudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOzs7O0dBSUc7QUFDSCw2QkFBdUI7QUFFdkIscUNBQThCO0FBQzlCLCtCQUFvQztBQUNwQyxvREFBa0Q7QUFDbEQsb0RBQXVEO0FBQ3ZELDhEQUEyRDtBQUMzRCw4Q0FBdUQ7QUFDdkQsZ0RBQW9FO0FBQ3BFLDBDQUFzQztBQUN0Qyw0Q0FBeUM7QUFDekMsOENBQThDO0FBQzlDLDBDQUE4RTtBQUU5RSxNQUFNLEdBQUcsR0FBRyxJQUFJLGFBQUcsQ0FBQyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFDdkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsV0FBVyxDQUFDO0FBQ3JDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQztBQUVsQyxNQUFNLGFBQWEsR0FBWTtJQUMzQiw4QkFBOEIsRUFBRSxJQUFJO0lBQ3BDLFlBQVksRUFBRSxrQ0FBa0M7SUFDaEQsWUFBWSxFQUFFLGtDQUFrQztJQUNoRCxhQUFhLEVBQUUsbUNBQW1DO0lBQ2xELHdCQUF3QixFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUk7SUFDcEMsWUFBWSxFQUFFLGtDQUFrQztJQUNoRCxlQUFlLEVBQUUscUNBQXFDO0lBQ3RELGtCQUFrQixFQUFFLHdDQUF3QztJQUM1RCxlQUFlLEVBQUUsTUFBTTtJQUN2QixJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUUsQ0FBQztJQUNkLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFFLENBQUM7SUFDYixPQUFPLEVBQUUsQ0FBQyxDQUFTLEVBQUUsRUFBRSxHQUFFLENBQUM7Q0FDN0IsQ0FBQztBQUVGLEtBQUssVUFBVSxpQkFBaUI7SUFDNUIsTUFBTSxTQUFTLEdB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VUFBVSxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEYsTUFBTSxRQUFRLEdBQUcsTUFBTSxpQkFBaUIsRUFBRSxDQUFDO0lBQzNDLE1BQU0sR0FBRyxHQUFHLENBQUMsbUNBQW1DLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFFaEUsSUFBSTtRQUNBLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRywrQkFBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxHQUFHO1lBQ1QsTUFBTSxFQUFFLElBQUk7WUFDWixJQUFJO1lBQ0osSUFBSSxFQUFFLGlDQUFxQixDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQztZQUM5QyxVQUFVLEVBQUUsc0JBQXNCO1lBQ2xDLGVBQWUsRUFBRSxRQUFRO1NBQzVCLENBQUM7UUFDRixNQUFNLEtBQUssR0FBRztZQUNWLE9BQU8sRUFBRTtnQkFDTDtvQkFDSSxHQUFHLEVBQUU7d0JBQ0QsT0FBTyxFQUFFLHFCQUFTLENBQUMsSUFBSSxDQUFDO3FCQUMzQjtpQkFDSjthQUNKO1NBQ0osQ0FBQztRQUVGLE1BQU0sVUFBVSxDQUFDLEtBQWlCLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFFbkQsTUFBTSxRQUFRLEdBQUcsTUFBTSxXQUFXLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3pFLDRCQUFxQixDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7S0FDM0M7WUFBUztRQUNOLE1BQU0sbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7S0FDdkM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHB1cnBvc2Ugb2YgdGhpcyB0ZXN0IGlzIHRvIGNoZWNrIHRoYXQgdGhlIHRyYW1wb2xpbmUgZnVuY3Rpb24gb24gQVdTIGNhblxuICogcm91dGUgY2FsbHMsIGludm9rZSB0aGUgd3JhcHBlciwgYW5kIHJldHVybiB2YWx1ZXMgY29ycmVjdGx5LCB3aXRob3V0XG4gKiBhY3R1YWxseSBjcmVhdGluZyBhIGNsb3VkIGZ1bmN0aW9uLiBIb3dldmVyLCBpdCBkb2VzIHVzZSByZWFsIGNsb3VkIHF1ZXVlcy5cbiAqL1xuaW1wb3J0IHRlc3QgZnJvbSBcImF2YVwiO1xuaW1wb3J0IHsgQ29udGV4dCwgU05TRXZlbnQgfSBmcm9tIFwiYXdzLWxhbWJkYVwiO1xuaW1wb3J0IHsgU1FTIH0gZnJvbSBcImF3cy1zZGtcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWR2NCB9IGZyb20gXCJ1dWlkXCI7XG5pbXBvcnQgeyBBd3NNZXRyaWNzIH0gZnJvbSBcIi4uL3NyYy9hd3MvYXdzLWZhYXN0XCI7XG5pbXBvcnQgeyByZWNlaXZlTWVzc2FnZXMgfSBmcm9tIFwiLi4vc3JjL2F3cy9hd3MtcXVldWVcIjtcbmltcG9ydCB7IG1ha2VUcmFtcG9saW5lIH0gZnJvbSBcIi4uL3NyYy9hd3MvYXdzLXRyYW1wb2xpbmVcIjtcbmltcG9ydCB7IGZpbHRlck1lc3NhZ2VzLCBLaW5kIH0gZnJvbSBcIi4uL3NyYy9wcm92aWRlclwiO1xuaW1wb3J0IHsgc2VyaWFsaXplLCBzZXJpYWxpemVGdW5jdGlvbkFyZ3MgfSBmcm9tIFwiLi4vc3JjL3NlcmlhbGl6ZVwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi4vc3JjL3NoYXJlZFwiO1xuaW1wb3J0IHsgV3JhcHBlciB9IGZyb20gXCIuLi9zcmMvd3JhcHBlclwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBjaGVja0l0ZXJhdG9yTWVzc2FnZXMsIGV4cGVjdE1lc3NhZ2UsIHRpdGxlIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbFwiO1xuXG5jb25zdCBzcXMgPSBuZXcgU1FTKHsgYXBpVmVyc2lvbjogXCIyMDEyLTExLTA1XCIsIHJlZ2lvbjogXCJ1cy13ZXN0LTJcIiB9KTtcbnByb2Nlc3MuZW52LkFXU19SRUdJT04gPSBcInVzLXdlc3QtMlwiO1xucHJvY2Vzcy5lbnYuRkFBU1RfU0lMRU5UID0gXCJ0cnVlXCI7XG5cbmNvbnN0IGxhbWJkYUNvbnRleHQ6IENvbnRleHQgPSB7XG4gICAgY2FsbGJhY2tXYWl0c0ZvckVtcHR5RXZlbnRMb29wOiB0cnVlLFxuICAgIGF3c1JlcXVlc3RJZDogXCJhd3MtdHJhbXBvbGluZS10ZXN0LWF3c1JlcXVlc3RJZFwiLFxuICAgIGxvZ0dyb3VwTmFtZTogXCJhd3MtdHJhbXBvbGluZS10ZXN0LWxvZ0dyb3VwTmFtZVwiLFxuICAgIGxvZ1N0cmVhbU5hbWU6IFwiYXdzLXRyYW1wb2xpbmUtdGVzdC1sb2dTdHJlYW1OYW1lXCIsXG4gICAgZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzOiAoKSA9PiAxMDAwLFxuICAgIGZ1bmN0aW9uTmFtZTogXCJhd3MtdHJhbXBvbGluZS10ZXN0LWZ1bmN0aW9uTmFtZVwiLFxuICAgIGZ1bmN0aW9uVmVyc2lvbjogXCJhd3MtdHJhbXBvbGluZS10ZXN0LWZ1bmN0aW9uVmVyc2lvblwiLFxuICAgIGludm9rZWRGdW5jdGlvbkFybjogXCJhd3MtdHJhbXBvbGluZS10ZXN0LWludm9rZWRGdW5jdGlvbkFyblwiLFxuICAgIG1lbW9yeUxpbWl0SW5NQjogXCIxNzI4XCIsXG4gICAgZG9uZTogKCkgPT4ge30sXG4gICAgZmFpbDogXyA9PiB7fSxcbiAgICBzdWNjZWVkOiAoXzogc3RyaW5nKSA9PiB7fVxufTtcblxuYXN5bmMgZnVuY3Rpb24gbWFrZVJlc3BvbnNlUXVldWUoKSB7XG4gICAgY29uc3QgUXVldWVOYW1lID0gYGZhYXN0LSR7dXVpZHY0KCl9LXRlc3RgO1xuICAgIGNvbnN0IHsgUXVldWVVcmwgfSA9IGF3YWl0IHNxcy5jcmVhdGVRdWV1ZSh7IFF1ZXVlTmFtZSB9KS5wcm9taXNlKCk7XG4gICAgcmV0dXJuIFF1ZXVlVXJsITtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVsZXRlUmVzcG9uc2VRdWV1ZShRdWV1ZVVybDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gU29tZXRpbWVzIEFXUyBuZWVkcyB0aW1lIHRvIHByb3BhZ2F0ZSB0aGUgZXhpc3RlbmNlIG9mIGEgcXVldWUgYmVmb3JlXG4gICAgICAgIC8vIGRlbGV0aW5nIGl0LiBUaGlzIG1hbmlmZXN0cyBhcyBhIE5vbkV4aXN0ZW50UXVldWUgZXJyb3IuIFdhaXRpbmdcbiAgICAgICAgLy8gYSBzaG9ydCB3aGlsZSBzZWVtcyB0byBtYWtlIHRoaXMgbGVzcyBjb21tb24uXG4gICAgICAgIGF3YWl0IHNsZWVwKDUwMDApO1xuICAgICAgICByZXR1cm4gYXdhaXQgc3FzLmRlbGV0ZVF1ZXVlKHsgUXVldWVVcmwgfSkucHJvbWlzZSgpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBDb3VsZCBub3QgZGVsZXRlIHJlc3BvbnNlIHF1ZXVlOiAke2Vycn1gKTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0TWVzc2FnZXM8SyBleHRlbmRzIEtpbmQ+KFF1ZXVlVXJsOiBzdHJpbmcsIGtpbmQ6IEssIG5FeHBlY3RlZDogbnVtYmVyKSB7XG4gICAgY29uc3QgbWV0cmljcyA9IG5ldyBBd3NNZXRyaWNzKCk7XG4gICAgY29uc3QgY2FuY2VsID0gbmV3IFByb21pc2U8dm9pZD4oXyA9PiB7fSk7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgd2hpbGUgKHJlc3VsdC5sZW5ndGggPCBuRXhwZWN0ZWQpIHtcbiAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBhd2FpdCByZWNlaXZlTWVzc2FnZXMoc3FzLCBRdWV1ZVVybCwgbWV0cmljcywgY2FuY2VsKTtcbiAgICAgICAgcmVzdWx0LnB1c2goLi4uZmlsdGVyTWVzc2FnZXMobWVzc2FnZXMuTWVzc2FnZXMsIGtpbmQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxudGVzdCh0aXRsZShcImF3c1wiLCBcInRyYW1wb2xpbmUgaHR0cHMgbW9kZSB3aXRoIHByb21pc2UgcmVzcG9uc2VcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IHdyYXBwZXIgPSBuZXcgV3JhcHBlcihmdW5jcywgeyBjaGlsZFByb2Nlc3M6IGZhbHNlLCB3cmFwcGVyTG9nOiAoKSA9PiB7fSB9KTtcbiAgICBjb25zdCB7IHRyYW1wb2xpbmUgfSA9IG1ha2VUcmFtcG9saW5lKHdyYXBwZXIpO1xuICAgIGNvbnN0IGFyZyA9IFwicHJvbWlzZSB3aXRoIGh0dHBzIG9uIGF3c1wiO1xuICAgIGNvbnN0IG5hbWUgPSBmdW5jcy5pZGVudGl0eVN0cmluZy5uYW1lO1xuICAgIGNvbnN0IFF1ZXVlVXJsID0gYXdhaXQgbWFrZVJlc3BvbnNlUXVldWUoKTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCB0cmFtcG9saW5lKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNhbGxJZDogXCI0MlwiLFxuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgYXJnczogc2VyaWFsaXplRnVuY3Rpb25BcmdzKG5hbWUsIFthcmddLCB0cnVlKSxcbiAgICAgICAgICAgICAgICBtb2R1bGVQYXRoOiBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCIsXG4gICAgICAgICAgICAgICAgUmVzcG9uc2VRdWV1ZUlkOiBRdWV1ZVVybFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxhbWJkYUNvbnRleHRcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBbbXNnXSA9IGF3YWl0IGdldE1lc3NhZ2VzKFF1ZXVlVXJsLCBcInByb21pc2VcIiwgMSk7XG4gICAgICAgIGV4cGVjdE1lc3NhZ2UodCwgbXNnLCBcInByb21pc2VcIiwgYXJnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBkZWxldGVSZXNwb25zZVF1ZXVlKFF1ZXVlVXJsKTtcbiAgICB9XG59KTtcblxudGVzdCh0aXRsZShcImF3c1wiLCBcInRyYW1wb2xpbmUgcXVldWUgbW9kZSB3aXRoIHByb21pc2UgcmVzcG9uc2VcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IHdyYXBwZXIgPSBuZXcgV3JhcHBlcihmdW5jcywgeyBjaGlsZFByb2Nlc3M6IGZhbHNlLCB3cmFwcGVyTG9nOiAoKSA9PiB7fSB9KTtcbiAgICBjb25zdCBhcmcgPSBcInByb21pc2Ugd2l0aCBxdWV1ZSBvbiBhd3NcIjtcbiAgICBjb25zdCBRdWV1ZVVybCA9IGF3YWl0IG1ha2VSZXNwb25zZVF1ZXVlKCk7XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyB0cmFtcG9saW5lIH0gPSBtYWtlVHJhbXBvbGluZSh3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgbmFtZSA9IGZ1bmNzLmlkZW50aXR5U3RyaW5nLm5hbWU7XG4gICAgICAgIGNvbnN0IGNhbGwgPSB7XG4gICAgICAgICAgICBjYWxsSWQ6IFwiNDNcIixcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBhcmdzOiBzZXJpYWxpemVGdW5jdGlvbkFyZ3MobmFtZSwgW2FyZ10sIHRydWUpLFxuICAgICAgICAgICAgbW9kdWxlUGF0aDogXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiLFxuICAgICAgICAgICAgUmVzcG9uc2VRdWV1ZUlkOiBRdWV1ZVVybFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgIFJlY29yZHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIFNuczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWVzc2FnZTogc2VyaWFsaXplKGNhbGwpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgdHJhbXBvbGluZShldmVudCBhcyBTTlNFdmVudCwgbGFtYmRhQ29udGV4dCk7XG5cbiAgICAgICAgY29uc3QgW21zZ10gPSBhd2FpdCBnZXRNZXNzYWdlcyhRdWV1ZVVybCwgXCJwcm9taXNlXCIsIDEpO1xuICAgICAgICBleHBlY3RNZXNzYWdlKHQsIG1zZywgXCJwcm9taXNlXCIsIGFyZyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZGVsZXRlUmVzcG9uc2VRdWV1ZShRdWV1ZVVybCk7XG4gICAgfVxufSk7XG5cbnRlc3QodGl0bGUoXCJhd3NcIiwgXCJ0cmFtcG9saW5lIGh0dHBzIG1vZGUgd2l0aCBhc3luYyBpdGVyYXRvciByZXNwb25zZVwiKSwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3Qgd3JhcHBlciA9IG5ldyBXcmFwcGVyKGZ1bmNzLCB7IGNoaWxkUHJvY2VzczogZmFsc2UsIHdyYXBwZXJMb2c6ICgpID0+IHt9IH0pO1xuICAgIGNvbnN0IHsgdHJhbXBvbGluZSB9ID0gbWFrZVRyYW1wb2xpbmUod3JhcHBlcik7XG4gICAgY29uc3QgbmFtZSA9IGZ1bmNzLmFzeW5jR2VuZXJhdG9yLm5hbWU7XG4gICAgY29uc3QgYXJnID0gW1wiYXN5bmMgZ2VuZXJhdG9yIHdpdGggaHR0cHMgb24gYXdzXCIsIFwic2Vjb25kIGFyZ1wiXTtcbiAgICBjb25zdCBRdWV1ZVVybCA9IGF3YWl0IG1ha2VSZXNwb25zZVF1ZXVlKCk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdHJhbXBvbGluZShcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjYWxsSWQ6IFwiNDRcIixcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIGFyZ3M6IHNlcmlhbGl6ZUZ1bmN0aW9uQXJncyhuYW1lLCBbYXJnXSwgdHJ1ZSksXG4gICAgICAgICAgICAgICAgbW9kdWxlUGF0aDogXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiLFxuICAgICAgICAgICAgICAgIFJlc3BvbnNlUXVldWVJZDogUXVldWVVcmxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsYW1iZGFDb250ZXh0XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgZ2V0TWVzc2FnZXMoUXVldWVVcmwsIFwiaXRlcmF0b3JcIiwgYXJnLmxlbmd0aCArIDEpO1xuICAgICAgICBjaGVja0l0ZXJhdG9yTWVzc2FnZXModCwgbWVzc2FnZXMsIGFyZyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZGVsZXRlUmVzcG9uc2VRdWV1ZShRdWV1ZVVybCk7XG4gICAgfVxufSk7XG5cbnRlc3QodGl0bGUoXCJhd3NcIiwgXCJ0cmFtcG9saW5lIHF1ZXVlIG1vZGUgd2l0aCBhc3luYyBpdGVyYXRvciByZXNwb25zZVwiKSwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3Qgd3JhcHBlciA9IG5ldyBXcmFwcGVyKGZ1bmNzLCB7IGNoaWxkUHJvY2VzczogZmFsc2UsIHdyYXBwZXJMb2c6ICgpID0+IHt9IH0pO1xuICAgIGNvbnN0IFF1ZXVlVXJsID0gYXdhaXQgbWFrZVJlc3BvbnNlUXVldWUoKTtcbiAgICBjb25zdCBhcmcgPSBbXCJhc3luYyBnZW5lcmF0b3Igd2l0aCBxdWV1ZSBvbiBhd3NcIiwgXCJzZWNvbmQgYXJnXCJdO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgeyB0cmFtcG9saW5lIH0gPSBtYWtlVHJhbXBvbGluZSh3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgbmFtZSA9IGZ1bmNzLmFzeW5jR2VuZXJhdG9yLm5hbWU7XG4gICAgICAgIGNvbnN0IGNhbGwgPSB7XG4gICAgICAgICAgICBjYWxsSWQ6IFwiNDVcIixcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBhcmdzOiBzZXJpYWxpemVGdW5jdGlvbkFyZ3MobmFtZSwgW2FyZ10sIHRydWUpLFxuICAgICAgICAgICAgbW9kdWxlUGF0aDogXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiLFxuICAgICAgICAgICAgUmVzcG9uc2VRdWV1ZUlkOiBRdWV1ZVVybFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgIFJlY29yZHM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIFNuczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWVzc2FnZTogc2VyaWFsaXplKGNhbGwpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICBdXG4gICAgICAgIH07XG5cbiAgICAgICAgYXdhaXQgdHJhbXBvbGluZShldmVudCBhcyBTTlNFdmVudCwgbGFtYmRhQ29udGV4dCk7XG5cbiAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBhd2FpdCBnZXRNZXNzYWdlcyhRdWV1ZVVybCwgXCJpdGVyYXRvclwiLCBhcmcubGVuZ3RoICsgMSk7XG4gICAgICAgIGNoZWNrSXRlcmF0b3JNZXNzYWdlcyh0LCBtZXNzYWdlcywgYXJnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBkZWxldGVSZXNwb25zZVF1ZXVlKFF1ZXVlVXJsKTtcbiAgICB9XG59KTtcbiJdfQ==
\No newline at end of file