UNPKG

27 kBJavaScriptView Raw
1"use strict";
2/**
3 * The purpose of this test is to check that the trampoline function on google
4 * can route calls, invoke the wrapper, and return values correctly, without
5 * actually creating a cloud function. However, it does use real cloud queues.
6 */
7Object.defineProperty(exports, "__esModule", { value: true });
8const ava_1 = require("ava");
9const uuid_1 = require("uuid");
10const google_faast_1 = require("../src/google/google-faast");
11const google_queue_1 = require("../src/google/google-queue");
12const google_trampoline_https_1 = require("../src/google/google-trampoline-https");
13const google_trampoline_queue_1 = require("../src/google/google-trampoline-queue");
14const provider_1 = require("../src/provider");
15const serialize_1 = require("../src/serialize");
16const wrapper_1 = require("../src/wrapper");
17const funcs = require("./fixtures/functions");
18const util_1 = require("./fixtures/util");
19const shared_1 = require("../src/shared");
20process.env.FAAST_SILENT = "true";
21async function initGoogleResources() {
22 const services = await (0, google_faast_1.initializeGoogleServices)();
23 const { google } = services;
24 const pubsub = google.pubsub("v1");
25 const project = await google.auth.getProjectId();
26 const FunctionName = `faast-${(0, uuid_1.v4)()}`;
27 const topic = await pubsub.projects.topics.create({
28 name: (0, google_faast_1.getResponseQueueTopic)(project, FunctionName)
29 });
30 const topicName = topic.data.name;
31 const subscriptionName = (0, google_faast_1.getResponseSubscription)(project, FunctionName);
32 await pubsub.projects.subscriptions.create({
33 name: subscriptionName,
34 requestBody: {
35 topic: topicName
36 }
37 });
38 const resources = {
39 topicName,
40 subscriptionName,
41 google
42 };
43 return resources;
44}
45async function cleanupGoogleResources(resources) {
46 const { google, subscriptionName, topicName } = resources;
47 const pubsub = google.pubsub("v1");
48 // Give google a little time to propagate the existence of the queue.
49 await (0, shared_1.sleep)(5000);
50 await pubsub.projects.subscriptions.delete({
51 subscription: subscriptionName
52 });
53 await pubsub.projects.topics.delete({
54 topic: topicName
55 });
56}
57async function getMessages(resources, kind, nExpected) {
58 const { google, subscriptionName } = resources;
59 const pubsub = google.pubsub("v1");
60 const metrics = new google_faast_1.GoogleMetrics();
61 const cancel = new Promise(_ => { });
62 const result = [];
63 while (result.length < nExpected) {
64 const messages = await (0, google_queue_1.receiveMessages)(pubsub, subscriptionName, metrics, cancel);
65 result.push(...(0, provider_1.filterMessages)(messages.Messages, kind));
66 }
67 return result;
68}
69(0, ava_1.default)((0, util_1.title)("google", "trampoline https mode with promise response"), async (t) => {
70 const resources = await initGoogleResources();
71 try {
72 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
73 const { trampoline } = (0, google_trampoline_https_1.makeTrampoline)(wrapper);
74 const arg = "promise with https on google";
75 const name = funcs.identityNum.name;
76 const call = {
77 callId: "42",
78 name,
79 args: (0, serialize_1.serializeFunctionArgs)(name, [arg], true),
80 modulePath: "./fixtures/functions",
81 ResponseQueueId: resources.topicName
82 };
83 const headers = {
84 "function-execution-id": "google-trampoline-test-function-execution-id"
85 };
86 const request = { body: call, headers };
87 const response = { send: (_) => { } };
88 await trampoline(request, response);
89 const [msg] = await getMessages(resources, "promise", 1);
90 (0, util_1.expectMessage)(t, msg, "promise", arg);
91 }
92 finally {
93 await cleanupGoogleResources(resources);
94 }
95});
96(0, ava_1.default)((0, util_1.title)("google", "trampoline https mode with async iterator response"), async (t) => {
97 const resources = await initGoogleResources();
98 try {
99 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
100 const { trampoline } = (0, google_trampoline_https_1.makeTrampoline)(wrapper);
101 const arg = ["async iterator with https on google", "second arg"];
102 const name = funcs.asyncGenerator.name;
103 const call = {
104 callId: "42",
105 name,
106 args: (0, serialize_1.serializeFunctionArgs)(name, [arg], true),
107 modulePath: "./fixtures/functions",
108 ResponseQueueId: resources.topicName
109 };
110 const headers = {
111 "function-execution-id": "google-trampoline-test-function-execution-id"
112 };
113 const request = { body: call, headers };
114 const response = { send: (_) => { } };
115 await trampoline(request, response);
116 const messages = await getMessages(resources, "iterator", arg.length + 1);
117 (0, util_1.checkIteratorMessages)(t, messages, arg);
118 }
119 finally {
120 await cleanupGoogleResources(resources);
121 }
122});
123(0, ava_1.default)((0, util_1.title)("google", "trampoline queue mode with promise response"), async (t) => {
124 const resources = await initGoogleResources();
125 try {
126 const arg = "promise with queue on google";
127 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
128 const { trampoline } = (0, google_trampoline_queue_1.makeTrampoline)(wrapper);
129 const name = funcs.identityNum.name;
130 const call = {
131 callId: "42",
132 name,
133 args: (0, serialize_1.serializeFunctionArgs)(name, [arg], true),
134 modulePath: "./fixtures/functions",
135 ResponseQueueId: resources.topicName
136 };
137 const event = {
138 data: Buffer.from((0, serialize_1.serialize)(call)).toString("base64")
139 };
140 const context = {
141 eventId: "",
142 timestamp: "",
143 eventType: "",
144 resource: {}
145 };
146 await trampoline(event, context);
147 const [msg] = await getMessages(resources, "promise", 1);
148 (0, util_1.expectMessage)(t, msg, "promise", arg);
149 }
150 finally {
151 await cleanupGoogleResources(resources);
152 }
153});
154(0, ava_1.default)((0, util_1.title)("google", "trampoline queue mode with async iterator response"), async (t) => {
155 const resources = await initGoogleResources();
156 try {
157 const wrapper = new wrapper_1.Wrapper(funcs, { childProcess: false, wrapperLog: () => { } });
158 const arg = ["async iterator with queue on google"];
159 const { trampoline } = (0, google_trampoline_queue_1.makeTrampoline)(wrapper);
160 const name = funcs.asyncGenerator.name;
161 const call = {
162 callId: "42",
163 name,
164 args: (0, serialize_1.serializeFunctionArgs)(name, [arg], true),
165 modulePath: "./fixtures/functions",
166 ResponseQueueId: resources.topicName
167 };
168 const event = {
169 data: Buffer.from((0, serialize_1.serialize)(call)).toString("base64")
170 };
171 const context = {
172 eventId: "",
173 timestamp: "",
174 eventType: "",
175 resource: {}
176 };
177 await trampoline(event, context);
178 const messages = await getMessages(resources, "iterator", arg.length + 1);
179 (0, util_1.checkIteratorMessages)(t, messages, arg);
180 }
181 finally {
182 await cleanupGoogleResources(resources);
183 }
184});
185//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29vZ2xlLXRyYW1wb2xpbmUudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3Rlc3QvZ29vZ2xlLXRyYW1wb2xpbmUudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7R0FJRzs7QUFFSCw2QkFBdUI7QUFHdkIsK0JBQW9DO0FBQ3BDLDZEQUtvQztBQUNwQyw2REFBNkQ7QUFDN0QsbUZBQThGO0FBQzlGLG1GQUcrQztBQUMvQyw4Q0FBdUQ7QUFDdkQsZ0RBQW9FO0FBQ3BFLDRDQUF5QztBQUN6Qyw4Q0FBOEM7QUFDOUMsMENBQThFO0FBQzlFLDBDQUFzQztBQUV0QyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUM7QUFRbEMsS0FBSyxVQUFVLG1CQUFtQjtJQUM5QixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsdUNBQXdCLEdBQUUsQ0FBQztJQUNsRCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDO0lBQzVCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ2pELE1BQU0sWUFBWSxHQUFHLFNBQVMsSUFBQSxTQUFNLEdBQUUsRUFBRSxDQUFDO0lBQ3pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQzlDLElBQUksRUFBRSxJQUFBLG9DQUFxQixFQUFDLE9BQU8sRUFBRSxZQUFZLENBQUM7S0FDckQsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFLLENBQUM7SUFFbkMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFBLHNDQUF1QixFQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztJQUN4RSxNQUFNLE1BQU0s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R0FBRyxDQUFDLENBQUM7S0FDM0M7WUFBUztRQUNOLE1BQU0sc0JBQXNCLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDM0M7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHB1cnBvc2Ugb2YgdGhpcyB0ZXN0IGlzIHRvIGNoZWNrIHRoYXQgdGhlIHRyYW1wb2xpbmUgZnVuY3Rpb24gb24gZ29vZ2xlXG4gKiBjYW4gcm91dGUgY2FsbHMsIGludm9rZSB0aGUgd3JhcHBlciwgYW5kIHJldHVybiB2YWx1ZXMgY29ycmVjdGx5LCB3aXRob3V0XG4gKiBhY3R1YWxseSBjcmVhdGluZyBhIGNsb3VkIGZ1bmN0aW9uLiBIb3dldmVyLCBpdCBkb2VzIHVzZSByZWFsIGNsb3VkIHF1ZXVlcy5cbiAqL1xuXG5pbXBvcnQgdGVzdCBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgeyBSZXF1ZXN0LCBSZXNwb25zZSB9IGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQgeyBHb29nbGVBcGlzIH0gZnJvbSBcImdvb2dsZWFwaXNcIjtcbmltcG9ydCB7IHY0IGFzIHV1aWR2NCB9IGZyb20gXCJ1dWlkXCI7XG5pbXBvcnQge1xuICAgIGdldFJlc3BvbnNlUXVldWVUb3BpYyxcbiAgICBnZXRSZXNwb25zZVN1YnNjcmlwdGlvbixcbiAgICBHb29nbGVNZXRyaWNzLFxuICAgIGluaXRpYWxpemVHb29nbGVTZXJ2aWNlc1xufSBmcm9tIFwiLi4vc3JjL2dvb2dsZS9nb29nbGUtZmFhc3RcIjtcbmltcG9ydCB7IHJlY2VpdmVNZXNzYWdlcyB9IGZyb20gXCIuLi9zcmMvZ29vZ2xlL2dvb2dsZS1xdWV1ZVwiO1xuaW1wb3J0IHsgbWFrZVRyYW1wb2xpbmUgYXMgbWFrZVRyYW1wb2xpbmVIdHRwcyB9IGZyb20gXCIuLi9zcmMvZ29vZ2xlL2dvb2dsZS10cmFtcG9saW5lLWh0dHBzXCI7XG5pbXBvcnQge1xuICAgIENsb3VkRnVuY3Rpb25Db250ZXh0LFxuICAgIG1ha2VUcmFtcG9saW5lIGFzIG1ha2VUcmFtcG9saW5lUXVldWVcbn0gZnJvbSBcIi4uL3NyYy9nb29nbGUvZ29vZ2xlLXRyYW1wb2xpbmUtcXVldWVcIjtcbmltcG9ydCB7IGZpbHRlck1lc3NhZ2VzLCBLaW5kIH0gZnJvbSBcIi4uL3NyYy9wcm92aWRlclwiO1xuaW1wb3J0IHsgc2VyaWFsaXplLCBzZXJpYWxpemVGdW5jdGlvbkFyZ3MgfSBmcm9tIFwiLi4vc3JjL3NlcmlhbGl6ZVwiO1xuaW1wb3J0IHsgV3JhcHBlciB9IGZyb20gXCIuLi9zcmMvd3JhcHBlclwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBjaGVja0l0ZXJhdG9yTWVzc2FnZXMsIGV4cGVjdE1lc3NhZ2UsIHRpdGxlIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbFwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi4vc3JjL3NoYXJlZFwiO1xuXG5wcm9jZXNzLmVudi5GQUFTVF9TSUxFTlQgPSBcInRydWVcIjtcblxuaW50ZXJmYWNlIEdvb2dsZVRyYW1wb2xpbmVUZXN0UmVzb3VyY2VzIHtcbiAgICB0b3BpY05hbWU6IHN0cmluZztcbiAgICBzdWJzY3JpcHRpb25OYW1lOiBzdHJpbmc7XG4gICAgZ29vZ2xlOiBHb29nbGVBcGlzO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpbml0R29vZ2xlUmVzb3VyY2VzKCkge1xuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgaW5pdGlhbGl6ZUdvb2dsZVNlcnZpY2VzKCk7XG4gICAgY29uc3QgeyBnb29nbGUgfSA9IHNlcnZpY2VzO1xuICAgIGNvbnN0IHB1YnN1YiA9IGdvb2dsZS5wdWJzdWIoXCJ2MVwiKTtcbiAgICBjb25zdCBwcm9qZWN0ID0gYXdhaXQgZ29vZ2xlLmF1dGguZ2V0UHJvamVjdElkKCk7XG4gICAgY29uc3QgRnVuY3Rpb25OYW1lID0gYGZhYXN0LSR7dXVpZHY0KCl9YDtcbiAgICBjb25zdCB0b3BpYyA9IGF3YWl0IHB1YnN1Yi5wcm9qZWN0cy50b3BpY3MuY3JlYXRlKHtcbiAgICAgICAgbmFtZTogZ2V0UmVzcG9uc2VRdWV1ZVRvcGljKHByb2plY3QsIEZ1bmN0aW9uTmFtZSlcbiAgICB9KTtcbiAgICBjb25zdCB0b3BpY05hbWUgPSB0b3BpYy5kYXRhLm5hbWUhO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uTmFtZSA9IGdldFJlc3BvbnNlU3Vic2NyaXB0aW9uKHByb2plY3QsIEZ1bmN0aW9uTmFtZSk7XG4gICAgYXdhaXQgcHVic3ViLnByb2plY3RzLnN1YnNjcmlwdGlvbnMuY3JlYXRlKHtcbiAgICAgICAgbmFtZTogc3Vic2NyaXB0aW9uTmFtZSxcbiAgICAgICAgcmVxdWVzdEJvZHk6IHtcbiAgICAgICAgICAgIHRvcGljOiB0b3BpY05hbWVcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzb3VyY2VzOiBHb29nbGVUcmFtcG9saW5lVGVzdFJlc291cmNlcyA9IHtcbiAgICAgICAgdG9waWNOYW1lLFxuICAgICAgICBzdWJzY3JpcHRpb25OYW1lLFxuICAgICAgICBnb29nbGVcbiAgICB9O1xuICAgIHJldHVybiByZXNvdXJjZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNsZWFudXBHb29nbGVSZXNvdXJjZXMocmVzb3VyY2VzOiBHb29nbGVUcmFtcG9saW5lVGVzdFJlc291cmNlcykge1xuICAgIGNvbnN0IHsgZ29vZ2xlLCBzdWJzY3JpcHRpb25OYW1lLCB0b3BpY05hbWUgfSA9IHJlc291cmNlcztcbiAgICBjb25zdCBwdWJzdWIgPSBnb29nbGUucHVic3ViKFwidjFcIik7XG4gICAgLy8gR2l2ZSBnb29nbGUgYSBsaXR0bGUgdGltZSB0byBwcm9wYWdhdGUgdGhlIGV4aXN0ZW5jZSBvZiB0aGUgcXVldWUuXG4gICAgYXdhaXQgc2xlZXAoNTAwMCk7XG4gICAgYXdhaXQgcHVic3ViLnByb2plY3RzLnN1YnNjcmlwdGlvbnMuZGVsZXRlKHtcbiAgICAgICAgc3Vic2NyaXB0aW9uOiBzdWJzY3JpcHRpb25OYW1lXG4gICAgfSk7XG4gICAgYXdhaXQgcHVic3ViLnByb2plY3RzLnRvcGljcy5kZWxldGUoe1xuICAgICAgICB0b3BpYzogdG9waWNOYW1lXG4gICAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldE1lc3NhZ2VzPEsgZXh0ZW5kcyBLaW5kPihcbiAgICByZXNvdXJjZXM6IEdvb2dsZVRyYW1wb2xpbmVUZXN0UmVzb3VyY2VzLFxuICAgIGtpbmQ6IEssXG4gICAgbkV4cGVjdGVkOiBudW1iZXJcbikge1xuICAgIGNvbnN0IHsgZ29vZ2xlLCBzdWJzY3JpcHRpb25OYW1lIH0gPSByZXNvdXJjZXM7XG4gICAgY29uc3QgcHVic3ViID0gZ29vZ2xlLnB1YnN1YihcInYxXCIpO1xuICAgIGNvbnN0IG1ldHJpY3MgPSBuZXcgR29vZ2xlTWV0cmljcygpO1xuICAgIGNvbnN0IGNhbmNlbCA9IG5ldyBQcm9taXNlPHZvaWQ+KF8gPT4ge30pO1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgIHdoaWxlIChyZXN1bHQubGVuZ3RoIDwgbkV4cGVjdGVkKSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgcmVjZWl2ZU1lc3NhZ2VzKHB1YnN1Yiwgc3Vic2NyaXB0aW9uTmFtZSwgbWV0cmljcywgY2FuY2VsKTtcbiAgICAgICAgcmVzdWx0LnB1c2goLi4uZmlsdGVyTWVzc2FnZXMobWVzc2FnZXMuTWVzc2FnZXMsIGtpbmQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxudGVzdCh0aXRsZShcImdvb2dsZVwiLCBcInRyYW1wb2xpbmUgaHR0cHMgbW9kZSB3aXRoIHByb21pc2UgcmVzcG9uc2VcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IGluaXRHb29nbGVSZXNvdXJjZXMoKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCB3cmFwcGVyID0gbmV3IFdyYXBwZXIoZnVuY3MsIHsgY2hpbGRQcm9jZXNzOiBmYWxzZSwgd3JhcHBlckxvZzogKCkgPT4ge30gfSk7XG4gICAgICAgIGNvbnN0IHsgdHJhbXBvbGluZSB9ID0gbWFrZVRyYW1wb2xpbmVIdHRwcyh3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgYXJnID0gXCJwcm9taXNlIHdpdGggaHR0cHMgb24gZ29vZ2xlXCI7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBmdW5jcy5pZGVudGl0eU51bS5uYW1lO1xuICAgICAgICBjb25zdCBjYWxsID0ge1xuICAgICAgICAgICAgY2FsbElkOiBcIjQyXCIsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgYXJnczogc2VyaWFsaXplRnVuY3Rpb25BcmdzKG5hbWUsIFthcmddLCB0cnVlKSxcbiAgICAgICAgICAgIG1vZHVsZVBhdGg6IFwiLi9maXh0dXJlcy9mdW5jdGlvbnNcIixcbiAgICAgICAgICAgIFJlc3BvbnNlUXVldWVJZDogcmVzb3VyY2VzLnRvcGljTmFtZVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RbXCJoZWFkZXJzXCJdID0ge1xuICAgICAgICAgICAgXCJmdW5jdGlvbi1leGVjdXRpb24taWRcIjogXCJnb29nbGUtdHJhbXBvbGluZS10ZXN0LWZ1bmN0aW9uLWV4ZWN1dGlvbi1pZFwiXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHsgYm9keTogY2FsbCwgaGVhZGVycyB9IGFzIFJlcXVlc3Q7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0geyBzZW5kOiAoXzogYW55KSA9PiB7fSB9IGFzIFJlc3BvbnNlO1xuXG4gICAgICAgIGF3YWl0IHRyYW1wb2xpbmUocmVxdWVzdCwgcmVzcG9uc2UpO1xuXG4gICAgICAgIGNvbnN0IFttc2ddID0gYXdhaXQgZ2V0TWVzc2FnZXMocmVzb3VyY2VzLCBcInByb21pc2VcIiwgMSk7XG4gICAgICAgIGV4cGVjdE1lc3NhZ2UodCwgbXNnLCBcInByb21pc2VcIiwgYXJnKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBjbGVhbnVwR29vZ2xlUmVzb3VyY2VzKHJlc291cmNlcyk7XG4gICAgfVxufSk7XG5cbnRlc3QodGl0bGUoXCJnb29nbGVcIiwgXCJ0cmFtcG9saW5lIGh0dHBzIG1vZGUgd2l0aCBhc3luYyBpdGVyYXRvciByZXNwb25zZVwiKSwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgaW5pdEdvb2dsZVJlc291cmNlcygpO1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHdyYXBwZXIgPSBuZXcgV3JhcHBlcihmdW5jcywgeyBjaGlsZFByb2Nlc3M6IGZhbHNlLCB3cmFwcGVyTG9nOiAoKSA9PiB7fSB9KTtcbiAgICAgICAgY29uc3QgeyB0cmFtcG9saW5lIH0gPSBtYWtlVHJhbXBvbGluZUh0dHBzKHdyYXBwZXIpO1xuICAgICAgICBjb25zdCBhcmcgPSBbXCJhc3luYyBpdGVyYXRvciB3aXRoIGh0dHBzIG9uIGdvb2dsZVwiLCBcInNlY29uZCBhcmdcIl07XG4gICAgICAgIGNvbnN0IG5hbWUgPSBmdW5jcy5hc3luY0dlbmVyYXRvci5uYW1lO1xuICAgICAgICBjb25zdCBjYWxsID0ge1xuICAgICAgICAgICAgY2FsbElkOiBcIjQyXCIsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgYXJnczogc2VyaWFsaXplRnVuY3Rpb25BcmdzKG5hbWUsIFthcmddLCB0cnVlKSxcbiAgICAgICAgICAgIG1vZHVsZVBhdGg6IFwiLi9maXh0dXJlcy9mdW5jdGlvbnNcIixcbiAgICAgICAgICAgIFJlc3BvbnNlUXVldWVJZDogcmVzb3VyY2VzLnRvcGljTmFtZVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGhlYWRlcnM6IFJlcXVlc3RbXCJoZWFkZXJzXCJdID0ge1xuICAgICAgICAgICAgXCJmdW5jdGlvbi1leGVjdXRpb24taWRcIjogXCJnb29nbGUtdHJhbXBvbGluZS10ZXN0LWZ1bmN0aW9uLWV4ZWN1dGlvbi1pZFwiXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHsgYm9keTogY2FsbCwgaGVhZGVycyB9IGFzIFJlcXVlc3Q7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0geyBzZW5kOiAoXzogYW55KSA9PiB7fSB9IGFzIFJlc3BvbnNlO1xuXG4gICAgICAgIGF3YWl0IHRyYW1wb2xpbmUocmVxdWVzdCwgcmVzcG9uc2UpO1xuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgZ2V0TWVzc2FnZXMocmVzb3VyY2VzLCBcIml0ZXJhdG9yXCIsIGFyZy5sZW5ndGggKyAxKTtcbiAgICAgICAgY2hlY2tJdGVyYXRvck1lc3NhZ2VzKHQsIG1lc3NhZ2VzLCBhcmcpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGNsZWFudXBHb29nbGVSZXNvdXJjZXMocmVzb3VyY2VzKTtcbiAgICB9XG59KTtcblxudGVzdCh0aXRsZShcImdvb2dsZVwiLCBcInRyYW1wb2xpbmUgcXVldWUgbW9kZSB3aXRoIHByb21pc2UgcmVzcG9uc2VcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IGluaXRHb29nbGVSZXNvdXJjZXMoKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBhcmcgPSBcInByb21pc2Ugd2l0aCBxdWV1ZSBvbiBnb29nbGVcIjtcbiAgICAgICAgY29uc3Qgd3JhcHBlciA9IG5ldyBXcmFwcGVyKGZ1bmNzLCB7IGNoaWxkUHJvY2VzczogZmFsc2UsIHdyYXBwZXJMb2c6ICgpID0+IHt9IH0pO1xuICAgICAgICBjb25zdCB7IHRyYW1wb2xpbmUgfSA9IG1ha2VUcmFtcG9saW5lUXVldWUod3JhcHBlcik7XG4gICAgICAgIGNvbnN0IG5hbWUgPSBmdW5jcy5pZGVudGl0eU51bS5uYW1lO1xuICAgICAgICBjb25zdCBjYWxsID0ge1xuICAgICAgICAgICAgY2FsbElkOiBcIjQyXCIsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgYXJnczogc2VyaWFsaXplRnVuY3Rpb25BcmdzKG5hbWUsIFthcmddLCB0cnVlKSxcbiAgICAgICAgICAgIG1vZHVsZVBhdGg6IFwiLi9maXh0dXJlcy9mdW5jdGlvbnNcIixcbiAgICAgICAgICAgIFJlc3BvbnNlUXVldWVJZDogcmVzb3VyY2VzLnRvcGljTmFtZVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBldmVudCA9IHtcbiAgICAgICAgICAgIGRhdGE6IEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZShjYWxsKSkudG9TdHJpbmcoXCJiYXNlNjRcIilcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBjb250ZXh0OiBDbG91ZEZ1bmN0aW9uQ29udGV4dCA9IHtcbiAgICAgICAgICAgIGV2ZW50SWQ6IFwiXCIsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IFwiXCIsXG4gICAgICAgICAgICBldmVudFR5cGU6IFwiXCIsXG4gICAgICAgICAgICByZXNvdXJjZToge31cbiAgICAgICAgfTtcblxuICAgICAgICBhd2FpdCB0cmFtcG9saW5lKGV2ZW50LCBjb250ZXh0KTtcblxuICAgICAgICBjb25zdCBbbXNnXSA9IGF3YWl0IGdldE1lc3NhZ2VzKHJlc291cmNlcywgXCJwcm9taXNlXCIsIDEpO1xuICAgICAgICBleHBlY3RNZXNzYWdlKHQsIG1zZywgXCJwcm9taXNlXCIsIGFyZyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgY2xlYW51cEdvb2dsZVJlc291cmNlcyhyZXNvdXJjZXMpO1xuICAgIH1cbn0pO1xuXG50ZXN0KHRpdGxlKFwiZ29vZ2xlXCIsIFwidHJhbXBvbGluZSBxdWV1ZSBtb2RlIHdpdGggYXN5bmMgaXRlcmF0b3IgcmVzcG9uc2VcIiksIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IGluaXRHb29nbGVSZXNvdXJjZXMoKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCB3cmFwcGVyID0gbmV3IFdyYXBwZXIoZnVuY3MsIHsgY2hpbGRQcm9jZXNzOiBmYWxzZSwgd3JhcHBlckxvZzogKCkgPT4ge30gfSk7XG4gICAgICAgIGNvbnN0IGFyZyA9IFtcImFzeW5jIGl0ZXJhdG9yIHdpdGggcXVldWUgb24gZ29vZ2xlXCJdO1xuXG4gICAgICAgIGNvbnN0IHsgdHJhbXBvbGluZSB9ID0gbWFrZVRyYW1wb2xpbmVRdWV1ZSh3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgbmFtZSA9IGZ1bmNzLmFzeW5jR2VuZXJhdG9yLm5hbWU7XG4gICAgICAgIGNvbnN0IGNhbGwgPSB7XG4gICAgICAgICAgICBjYWxsSWQ6IFwiNDJcIixcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBhcmdzOiBzZXJpYWxpemVGdW5jdGlvbkFyZ3MobmFtZSwgW2FyZ10sIHRydWUpLFxuICAgICAgICAgICAgbW9kdWxlUGF0aDogXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiLFxuICAgICAgICAgICAgUmVzcG9uc2VRdWV1ZUlkOiByZXNvdXJjZXMudG9waWNOYW1lXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGV2ZW50ID0ge1xuICAgICAgICAgICAgZGF0YTogQnVmZmVyLmZyb20oc2VyaWFsaXplKGNhbGwpKS50b1N0cmluZyhcImJhc2U2NFwiKVxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IGNvbnRleHQ6IENsb3VkRnVuY3Rpb25Db250ZXh0ID0ge1xuICAgICAgICAgICAgZXZlbnRJZDogXCJcIixcbiAgICAgICAgICAgIHRpbWVzdGFtcDogXCJcIixcbiAgICAgICAgICAgIGV2ZW50VHlwZTogXCJcIixcbiAgICAgICAgICAgIHJlc291cmNlOiB7fVxuICAgICAgICB9O1xuXG4gICAgICAgIGF3YWl0IHRyYW1wb2xpbmUoZXZlbnQsIGNvbnRleHQpO1xuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgZ2V0TWVzc2FnZXMocmVzb3VyY2VzLCBcIml0ZXJhdG9yXCIsIGFyZy5sZW5ndGggKyAxKTtcbiAgICAgICAgY2hlY2tJdGVyYXRvck1lc3NhZ2VzKHQsIG1lc3NhZ2VzLCBhcmcpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGNsZWFudXBHb29nbGVSZXNvdXJjZXMocmVzb3VyY2VzKTtcbiAgICB9XG59KTtcbiJdfQ==
\No newline at end of file