1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const ava_1 = require("ava");
|
4 | const fs_extra_1 = require("fs-extra");
|
5 | const url_1 = require("url");
|
6 | const util_1 = require("util");
|
7 | const index_1 = require("../index");
|
8 | const funcs = require("./fixtures/functions");
|
9 | const util_2 = require("./fixtures/util");
|
10 | const error_1 = require("../src/error");
|
11 | async function testCleanup(t, options) {
|
12 | const m = await (0, index_1.faastLocal)(funcs, {
|
13 | gc: "off",
|
14 | ...options
|
15 | });
|
16 | let done = 0;
|
17 | m.functions
|
18 | .hello("there")
|
19 | .then(_ => done++)
|
20 | .catch(_ => { });
|
21 | m.functions
|
22 | .sleep(1000)
|
23 | .then(_ => done++)
|
24 | .catch(_ => { });
|
25 | await m.cleanup();
|
26 | t.is(done, 0);
|
27 | }
|
28 | async function testOrder(t, options) {
|
29 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
30 | gc: "off",
|
31 | ...options
|
32 | });
|
33 | t.plan(2);
|
34 | const a = faastModule.functions.emptyReject();
|
35 | const b = faastModule.functions.sleep(0);
|
36 | t.is(await b, undefined);
|
37 | try {
|
38 | await a;
|
39 | }
|
40 | catch (err) {
|
41 | t.is(err, undefined);
|
42 | }
|
43 | finally {
|
44 | await faastModule.cleanup();
|
45 | }
|
46 | }
|
47 | async function testConcurrency(t, { options, maxConcurrency, expectedConcurrency }) {
|
48 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
49 | ...options,
|
50 | gc: "off",
|
51 | concurrency: maxConcurrency
|
52 | });
|
53 | try {
|
54 | const N = maxConcurrency * 2;
|
55 | const promises = [];
|
56 | for (let i = 0; i < N; i++) {
|
57 | promises.push(faastModule.functions.spin(2000));
|
58 | }
|
59 | const timings = await Promise.all(promises);
|
60 | t.is((0, util_2.measureConcurrency)(timings), expectedConcurrency);
|
61 | }
|
62 | finally {
|
63 | await faastModule.cleanup();
|
64 | }
|
65 | }
|
66 | (0, ava_1.default)("local provider cleanup stops executions", testCleanup, {});
|
67 | (0, ava_1.default)("local provider cleanup stops executions with child process", testCleanup, {
|
68 | childProcess: true
|
69 | });
|
70 | const orderConfigs = [
|
71 | { childProcess: false, concurrency: 1, maxRetries: 0 },
|
72 | { childProcess: true, concurrency: 1, maxRetries: 0 },
|
73 | { childProcess: false, concurrency: 2, maxRetries: 0 },
|
74 | { childProcess: true, concurrency: 2, maxRetries: 0 },
|
75 | { childProcess: false, concurrency: 2, maxRetries: 2 },
|
76 | { childProcess: true, concurrency: 2, maxRetries: 2 }
|
77 | ];
|
78 | for (const config of orderConfigs) {
|
79 | (0, ava_1.default)(`out of order await (async catch) with ${(0, util_1.inspect)(config)}`, testOrder, config);
|
80 | }
|
81 | async function readFirstLogfile(logDirectoryUrl) {
|
82 | const url = new url_1.URL(logDirectoryUrl);
|
83 | const buf = await (0, fs_extra_1.readFile)(url.pathname + "/0.log");
|
84 | return buf
|
85 | .toString()
|
86 | .split("\n")
|
87 | .map(m => m.replace(/^\[(\d+)\]/, "[$pid]"));
|
88 | }
|
89 | (0, ava_1.default)("local provider console.log, console.warn, and console.error with child process", async (t) => {
|
90 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
91 | childProcess: true,
|
92 | concurrency: 1,
|
93 | gc: "off"
|
94 | });
|
95 | try {
|
96 | await faastModule.functions.consoleLog("Remote console.log output");
|
97 | await faastModule.functions.consoleWarn("Remote console.warn output");
|
98 | await faastModule.functions.consoleError("Remote console.error output");
|
99 | await (0, util_2.sleep)(1000);
|
100 | await faastModule.cleanup({ deleteResources: false });
|
101 | const messages = await readFirstLogfile(faastModule.logUrl());
|
102 | t.truthy(messages.find(s => s === "[$pid]: Remote console.log output"));
|
103 | t.truthy(messages.find(s => s === "[$pid]: Remote console.warn output"));
|
104 | t.truthy(messages.find(s => s === "[$pid]: Remote console.error output"));
|
105 | }
|
106 | finally {
|
107 | await faastModule.cleanup({ deleteResources: false });
|
108 | }
|
109 | });
|
110 | (0, ava_1.default)("local provider log files should be appended, not truncated, after child process crash", async (t) => {
|
111 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
112 | childProcess: true,
|
113 | concurrency: 1,
|
114 | maxRetries: 1,
|
115 | gc: "off"
|
116 | });
|
117 | try {
|
118 | await faastModule.functions.consoleLog("output 1");
|
119 | try {
|
120 | await faastModule.functions.processExit();
|
121 | }
|
122 | catch (err) { }
|
123 | await faastModule.functions.consoleWarn("output 2");
|
124 | // Wait for flush
|
125 | await (0, util_2.sleep)(500);
|
126 | const messages = await readFirstLogfile(faastModule.logUrl());
|
127 | t.truthy(messages.find(s => s === "[$pid]: output 1"));
|
128 | t.truthy(messages.find(s => s === "[$pid]: output 2"));
|
129 | }
|
130 | finally {
|
131 | await faastModule.cleanup({ deleteResources: false });
|
132 | }
|
133 | });
|
134 | (0, ava_1.default)("local provider child process exceptions should result in errors with logUrl", async (t) => {
|
135 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
136 | childProcess: true,
|
137 | concurrency: 1,
|
138 | maxRetries: 1,
|
139 | gc: "off"
|
140 | });
|
141 | t.plan(1);
|
142 | try {
|
143 | await faastModule.functions.error("synthetic error");
|
144 | }
|
145 | catch (err) {
|
146 | const info = error_1.FaastError.info(err);
|
147 | t.true(typeof info.logUrl === "string" && info.logUrl.startsWith(" file:///"), (0, util_1.inspect)(err));
|
148 | }
|
149 | finally {
|
150 | await faastModule.cleanup();
|
151 | }
|
152 | });
|
153 | (0, ava_1.default)("local provider child process crashes should result in errors with logUrl", async (t) => {
|
154 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
155 | childProcess: true,
|
156 | concurrency: 1,
|
157 | maxRetries: 1,
|
158 | gc: "off"
|
159 | });
|
160 | t.plan(1);
|
161 | try {
|
162 | await faastModule.functions.processExit(-1);
|
163 | }
|
164 | catch (err) {
|
165 | const info = error_1.FaastError.info(err);
|
166 | t.true(typeof info.logUrl === "string" && info.logUrl.startsWith(" file:///"), (0, util_1.inspect)(err));
|
167 | }
|
168 | finally {
|
169 | await faastModule.cleanup();
|
170 | }
|
171 | });
|
172 | (0, ava_1.default)("local provider concurrent executions with child processes", async (t) => {
|
173 | await testConcurrency(t, {
|
174 | options: {
|
175 | childProcess: true
|
176 | },
|
177 | maxConcurrency: 5,
|
178 | expectedConcurrency: 5
|
179 | });
|
180 | });
|
181 | (0, ava_1.default)("local provider no concurrency for cpu bound work without child processes", async (t) => {
|
182 | await testConcurrency(t, {
|
183 | options: {
|
184 | childProcess: false
|
185 | },
|
186 | maxConcurrency: 5,
|
187 | expectedConcurrency: 1
|
188 | });
|
189 | });
|
190 | (0, ava_1.default)("local provider cleanup waits for all child processes to exit", async (t) => {
|
191 | const faastModule = await (0, index_1.faastLocal)(funcs, {
|
192 | childProcess: true,
|
193 | gc: "off"
|
194 | });
|
195 | faastModule.functions.spin(5000).catch(_ => { });
|
196 | while (true) {
|
197 | await (0, util_2.sleep)(100);
|
198 | if (faastModule.state.executors.length > 0) {
|
199 | break;
|
200 | }
|
201 | }
|
202 | t.is(faastModule.state.executors.length, 1, "executor is not running");
|
203 | await faastModule.cleanup({ gcTimeout: 60 });
|
204 | t.is(faastModule.state.executors.length, 0, "executors are running after cleanup");
|
205 | });
|
206 | (0, ava_1.default)("local unresolved module", async (t) => {
|
207 | t.plan(1);
|
208 | try {
|
209 | await (0, index_1.faastLocal)({});
|
210 | }
|
211 | catch (err) {
|
212 | t.regex(err.message, /Could not find file/);
|
213 | }
|
214 | });
|
215 | (0, ava_1.default)("local issue #37", async (t) => {
|
216 | // Previously this code caused an exception about module wrapper not being
|
217 | // re-entrant. The problem was a race condition between wrapper selection
|
218 | // and execution in local provider. Solved by making wrapper selector a
|
219 | // regular function instead of an async function.
|
220 | const m = await (0, index_1.faastLocal)(funcs);
|
221 | try {
|
222 | const { identityString: identity } = m.functions;
|
223 | await identity("a");
|
224 | const b = identity("b");
|
225 | const c = identity("c");
|
226 | await b;
|
227 | await c;
|
228 | // Test succeeds if no exceptions are thrown.
|
229 | t.true(true);
|
230 | }
|
231 | finally {
|
232 | await m.cleanup();
|
233 | }
|
234 | });
|
235 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW5pdC1sb2NhbC50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC91bml0LWxvY2FsLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBNkM7QUFDN0MsdUNBQW9DO0FBQ3BDLDZCQUEwQjtBQUMxQiwrQkFBK0I7QUFDL0Isb0NBQW9EO0FBQ3BELDhDQUE4QztBQUM5QywwQ0FBNEQ7QUFDNUQsd0NBQTBDO0FBRTFDLEtBQUssVUFBVSxXQUFXLENBQUMsQ0FBbUIsRUFBRSxPQUFxQjtJQUNqRSxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUEsa0JBQVUsRUFBQyxLQUFLLEVBQUU7UUFDOUIsRUFBRSxFQUFFLEtBQUs7UUFDVCxHQUFHLE9BQU87S0FDYixDQUFDLENBQUM7SUFDSCxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFFYixDQUFDLENBQUMsU0FBUztTQUNOLEtBQUssQ0FBQyxPQUFPLENBQUM7U0FDZCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztJQUVwQixDQUFDLENBQUMsU0FBUztTQUNOLEtBQUssQ0FBQyxJQUFJLENBQUM7U0FDWCxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRSxDQUFDLENBQUMsQ0FBQztJQUVwQixNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNsQixDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNsQixDQUFDO0FBRUQsS0FBSyxVQUFVLFNBQVMsQ0FBQyxDQUFtQixFQUFFLE9BQXFCO0lBQy9ELE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBQSxrQkFBVSxFQUFDLEtBQUssRUFBRTtRQUN4QyxFQUFF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QSxrQkFBVSxFQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ3hCO0lBQUMsT0FBTyxHQUFRLEVBQUU7UUFDZixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUscUJBQXFCLENBQUMsQ0FBQztLQUMvQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBQSxhQUFJLEVBQUMsaUJBQWlCLEVBQUUsS0FBSyxFQUFDLENBQUMsRUFBQyxFQUFFO0lBQzlCLDBFQUEwRTtJQUMxRSx5RUFBeUU7SUFDekUsdUVBQXVFO0lBQ3ZFLGlEQUFpRDtJQUNqRCxNQUFNLENBQUMsR0FBRyxNQUFNLElBQUEsa0JBQVUsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUNsQyxJQUFJO1FBQ0EsTUFBTSxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQ2pELE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QixNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLENBQUM7UUFDUixNQUFNLENBQUMsQ0FBQztRQUNSLDZDQUE2QztRQUM3QyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ2hCO1lBQVM7UUFDTixNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUNyQjtBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcImZzLWV4dHJhXCI7XG5pbXBvcnQgeyBVUkwgfSBmcm9tIFwidXJsXCI7XG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IGZhYXN0TG9jYWwsIExvY2FsT3B0aW9ucyB9IGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0ICogYXMgZnVuY3MgZnJvbSBcIi4vZml4dHVyZXMvZnVuY3Rpb25zXCI7XG5pbXBvcnQgeyBtZWFzdXJlQ29uY3VycmVuY3ksIHNsZWVwIH0gZnJvbSBcIi4vZml4dHVyZXMvdXRpbFwiO1xuaW1wb3J0IHsgRmFhc3RFcnJvciB9IGZyb20gXCIuLi9zcmMvZXJyb3JcIjtcblxuYXN5bmMgZnVuY3Rpb24gdGVzdENsZWFudXAodDogRXhlY3V0aW9uQ29udGV4dCwgb3B0aW9uczogTG9jYWxPcHRpb25zKSB7XG4gICAgY29uc3QgbSA9IGF3YWl0IGZhYXN0TG9jYWwoZnVuY3MsIHtcbiAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgIC4uLm9wdGlvbnNcbiAgICB9KTtcbiAgICBsZXQgZG9uZSA9IDA7XG5cbiAgICBtLmZ1bmN0aW9uc1xuICAgICAgICAuaGVsbG8oXCJ0aGVyZVwiKVxuICAgICAgICAudGhlbihfID0+IGRvbmUrKylcbiAgICAgICAgLmNhdGNoKF8gPT4ge30pO1xuXG4gICAgbS5mdW5jdGlvbnNcbiAgICAgICAgLnNsZWVwKDEwMDApXG4gICAgICAgIC50aGVuKF8gPT4gZG9uZSsrKVxuICAgICAgICAuY2F0Y2goXyA9PiB7fSk7XG5cbiAgICBhd2FpdCBtLmNsZWFudXAoKTtcbiAgICB0LmlzKGRvbmUsIDApO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0ZXN0T3JkZXIodDogRXhlY3V0aW9uQ29udGV4dCwgb3B0aW9uczogTG9jYWxPcHRpb25zKSB7XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdExvY2FsKGZ1bmNzLCB7XG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICAuLi5vcHRpb25zXG4gICAgfSk7XG4gICAgdC5wbGFuKDIpO1xuXG4gICAgY29uc3QgYSA9IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5lbXB0eVJlamVjdCgpO1xuICAgIGNvbnN0IGIgPSBmYWFzdE1vZHVsZS5mdW5jdGlvbnMuc2xlZXAoMCk7XG4gICAgdC5pcyhhd2FpdCBiLCB1bmRlZmluZWQpO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGE7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgdC5pcyhlcnIsIHVuZGVmaW5lZCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdENvbmN1cnJlbmN5KFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAge1xuICAgICAgICBvcHRpb25zLFxuICAgICAgICBtYXhDb25jdXJyZW5jeSxcbiAgICAgICAgZXhwZWN0ZWRDb25jdXJyZW5jeVxuICAgIH06IHtcbiAgICAgICAgb3B0aW9uczogTG9jYWxPcHRpb25zO1xuICAgICAgICBtYXhDb25jdXJyZW5jeTogbnVtYmVyO1xuICAgICAgICBleHBlY3RlZENvbmN1cnJlbmN5OiBudW1iZXI7XG4gICAgfVxuKSB7XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdExvY2FsKGZ1bmNzLCB7XG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBjb25jdXJyZW5jeTogbWF4Q29uY3VycmVuY3lcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IE4gPSBtYXhDb25jdXJyZW5jeSAqIDI7XG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgTjsgaSsrKSB7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5zcGluKDIwMDApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRpbWluZ3MgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgIHQuaXMobWVhc3VyZUNvbmN1cnJlbmN5KHRpbWluZ3MpLCBleHBlY3RlZENvbmN1cnJlbmN5KTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5jbGVhbnVwKCk7XG4gICAgfVxufVxuXG50ZXN0KFwibG9jYWwgcHJvdmlkZXIgY2xlYW51cCBzdG9wcyBleGVjdXRpb25zXCIsIHRlc3RDbGVhbnVwLCB7fSk7XG50ZXN0KFwibG9jYWwgcHJvdmlkZXIgY2xlYW51cCBzdG9wcyBleGVjdXRpb25zIHdpdGggY2hpbGQgcHJvY2Vzc1wiLCB0ZXN0Q2xlYW51cCwge1xuICAgIGNoaWxkUHJvY2VzczogdHJ1ZVxufSk7XG5cbmNvbnN0IG9yZGVyQ29uZmlncyA9IFtcbiAgICB7IGNoaWxkUHJvY2VzczogZmFsc2UsIGNvbmN1cnJlbmN5OiAxLCBtYXhSZXRyaWVzOiAwIH0sXG4gICAgeyBjaGlsZFByb2Nlc3M6IHRydWUsIGNvbmN1cnJlbmN5OiAxLCBtYXhSZXRyaWVzOiAwIH0sXG4gICAgeyBjaGlsZFByb2Nlc3M6IGZhbHNlLCBjb25jdXJyZW5jeTogMiwgbWF4UmV0cmllczogMCB9LFxuICAgIHsgY2hpbGRQcm9jZXNzOiB0cnVlLCBjb25jdXJyZW5jeTogMiwgbWF4UmV0cmllczogMCB9LFxuICAgIHsgY2hpbGRQcm9jZXNzOiBmYWxzZSwgY29uY3VycmVuY3k6IDIsIG1heFJldHJpZXM6IDIgfSxcbiAgICB7IGNoaWxkUHJvY2VzczogdHJ1ZSwgY29uY3VycmVuY3k6IDIsIG1heFJldHJpZXM6IDIgfVxuXTtcblxuZm9yIChjb25zdCBjb25maWcgb2Ygb3JkZXJDb25maWdzKSB7XG4gICAgdGVzdChgb3V0IG9mIG9yZGVyIGF3YWl0IChhc3luYyBjYXRjaCkgd2l0aCAke2luc3BlY3QoY29uZmlnKX1gLCB0ZXN0T3JkZXIsIGNvbmZpZyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRGaXJzdExvZ2ZpbGUobG9nRGlyZWN0b3J5VXJsOiBzdHJpbmcpIHtcbiAgICBjb25zdCB1cmwgPSBuZXcgVVJMKGxvZ0RpcmVjdG9yeVVybCk7XG4gICAgY29uc3QgYnVmID0gYXdhaXQgcmVhZEZpbGUodXJsLnBhdGhuYW1lICsgXCIvMC5sb2dcIik7XG4gICAgcmV0dXJuIGJ1ZlxuICAgICAgICAudG9TdHJpbmcoKVxuICAgICAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgLm1hcChtID0+IG0ucmVwbGFjZSgvXlxcWyhcXGQrKVxcXS8sIFwiWyRwaWRdXCIpKTtcbn1cblxudGVzdChcImxvY2FsIHByb3ZpZGVyIGNvbnNvbGUubG9nLCBjb25zb2xlLndhcm4sIGFuZCBjb25zb2xlLmVycm9yIHdpdGggY2hpbGQgcHJvY2Vzc1wiLCBhc3luYyB0ID0+IHtcbiAgICBjb25zdCBmYWFzdE1vZHVsZSA9IGF3YWl0IGZhYXN0TG9jYWwoZnVuY3MsIHtcbiAgICAgICAgY2hpbGRQcm9jZXNzOiB0cnVlLFxuICAgICAgICBjb25jdXJyZW5jeTogMSxcbiAgICAgICAgZ2M6IFwib2ZmXCJcbiAgICB9KTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5mdW5jdGlvbnMuY29uc29sZUxvZyhcIlJlbW90ZSBjb25zb2xlLmxvZyBvdXRwdXRcIik7XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5jb25zb2xlV2FybihcIlJlbW90ZSBjb25zb2xlLndhcm4gb3V0cHV0XCIpO1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5mdW5jdGlvbnMuY29uc29sZUVycm9yKFwiUmVtb3RlIGNvbnNvbGUuZXJyb3Igb3V0cHV0XCIpO1xuICAgICAgICBhd2FpdCBzbGVlcCgxMDAwKTtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCh7IGRlbGV0ZVJlc291cmNlczogZmFsc2UgfSk7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgcmVhZEZpcnN0TG9nZmlsZShmYWFzdE1vZHVsZS5sb2dVcmwoKSk7XG4gICAgICAgIHQudHJ1dGh5KG1lc3NhZ2VzLmZpbmQocyA9PiBzID09PSBcIlskcGlkXTogUmVtb3RlIGNvbnNvbGUubG9nIG91dHB1dFwiKSk7XG4gICAgICAgIHQudHJ1dGh5KG1lc3NhZ2VzLmZpbmQocyA9PiBzID09PSBcIlskcGlkXTogUmVtb3RlIGNvbnNvbGUud2FybiBvdXRwdXRcIikpO1xuICAgICAgICB0LnRydXRoeShtZXNzYWdlcy5maW5kKHMgPT4gcyA9PT0gXCJbJHBpZF06IFJlbW90ZSBjb25zb2xlLmVycm9yIG91dHB1dFwiKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCh7IGRlbGV0ZVJlc291cmNlczogZmFsc2UgfSk7XG4gICAgfVxufSk7XG5cbnRlc3QoXCJsb2NhbCBwcm92aWRlciBsb2cgZmlsZXMgc2hvdWxkIGJlIGFwcGVuZGVkLCBub3QgdHJ1bmNhdGVkLCBhZnRlciBjaGlsZCBwcm9jZXNzIGNyYXNoXCIsIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IGZhYXN0TW9kdWxlID0gYXdhaXQgZmFhc3RMb2NhbChmdW5jcywge1xuICAgICAgICBjaGlsZFByb2Nlc3M6IHRydWUsXG4gICAgICAgIGNvbmN1cnJlbmN5OiAxLFxuICAgICAgICBtYXhSZXRyaWVzOiAxLFxuICAgICAgICBnYzogXCJvZmZcIlxuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5jb25zb2xlTG9nKFwib3V0cHV0IDFcIik7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5mdW5jdGlvbnMucHJvY2Vzc0V4aXQoKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHt9XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmZ1bmN0aW9ucy5jb25zb2xlV2FybihcIm91dHB1dCAyXCIpO1xuXG4gICAgICAgIC8vIFdhaXQgZm9yIGZsdXNoXG4gICAgICAgIGF3YWl0IHNsZWVwKDUwMCk7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gYXdhaXQgcmVhZEZpcnN0TG9nZmlsZShmYWFzdE1vZHVsZS5sb2dVcmwoKSk7XG5cbiAgICAgICAgdC50cnV0aHkobWVzc2FnZXMuZmluZChzID0+IHMgPT09IFwiWyRwaWRdOiBvdXRwdXQgMVwiKSk7XG4gICAgICAgIHQudHJ1dGh5KG1lc3NhZ2VzLmZpbmQocyA9PiBzID09PSBcIlskcGlkXTogb3V0cHV0IDJcIikpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmNsZWFudXAoeyBkZWxldGVSZXNvdXJjZXM6IGZhbHNlIH0pO1xuICAgIH1cbn0pO1xuXG50ZXN0KFwibG9jYWwgcHJvdmlkZXIgY2hpbGQgcHJvY2VzcyBleGNlcHRpb25zIHNob3VsZCByZXN1bHQgaW4gZXJyb3JzIHdpdGggbG9nVXJsXCIsIGFzeW5jIHQgPT4ge1xuICAgIGNvbnN0IGZhYXN0TW9kdWxlID0gYXdhaXQgZmFhc3RMb2NhbChmdW5jcywge1xuICAgICAgICBjaGlsZFByb2Nlc3M6IHRydWUsXG4gICAgICAgIGNvbmN1cnJlbmN5OiAxLFxuICAgICAgICBtYXhSZXRyaWVzOiAxLFxuICAgICAgICBnYzogXCJvZmZcIlxuICAgIH0pO1xuICAgIHQucGxhbigxKTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5mdW5jdGlvbnMuZXJyb3IoXCJzeW50aGV0aWMgZXJyb3JcIik7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgY29uc3QgaW5mbyA9IEZhYXN0RXJyb3IuaW5mbyhlcnIpO1xuICAgICAgICB0LnRydWUoXG4gICAgICAgICAgICB0eXBlb2YgaW5mby5sb2dVcmwgPT09IFwic3RyaW5nXCIgJiYgaW5mby5sb2dVcmwuc3RhcnRzV2l0aChcIiBmaWxlOi8vL1wiKSxcbiAgICAgICAgICAgIGluc3BlY3QoZXJyKVxuICAgICAgICApO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmNsZWFudXAoKTtcbiAgICB9XG59KTtcblxudGVzdChcImxvY2FsIHByb3ZpZGVyIGNoaWxkIHByb2Nlc3MgY3Jhc2hlcyBzaG91bGQgcmVzdWx0IGluIGVycm9ycyB3aXRoIGxvZ1VybFwiLCBhc3luYyB0ID0+IHtcbiAgICBjb25zdCBmYWFzdE1vZHVsZSA9IGF3YWl0IGZhYXN0TG9jYWwoZnVuY3MsIHtcbiAgICAgICAgY2hpbGRQcm9jZXNzOiB0cnVlLFxuICAgICAgICBjb25jdXJyZW5jeTogMSxcbiAgICAgICAgbWF4UmV0cmllczogMSxcbiAgICAgICAgZ2M6IFwib2ZmXCJcbiAgICB9KTtcbiAgICB0LnBsYW4oMSk7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuZnVuY3Rpb25zLnByb2Nlc3NFeGl0KC0xKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICBjb25zdCBpbmZvID0gRmFhc3RFcnJvci5pbmZvKGVycik7XG4gICAgICAgIHQudHJ1ZShcbiAgICAgICAgICAgIHR5cGVvZiBpbmZvLmxvZ1VybCA9PT0gXCJzdHJpbmdcIiAmJiBpbmZvLmxvZ1VybC5zdGFydHNXaXRoKFwiIGZpbGU6Ly8vXCIpLFxuICAgICAgICAgICAgaW5zcGVjdChlcnIpXG4gICAgICAgICk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn0pO1xuXG50ZXN0KFwibG9jYWwgcHJvdmlkZXIgY29uY3VycmVudCBleGVjdXRpb25zIHdpdGggY2hpbGQgcHJvY2Vzc2VzXCIsIGFzeW5jIHQgPT4ge1xuICAgIGF3YWl0IHRlc3RDb25jdXJyZW5jeSh0LCB7XG4gICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIGNoaWxkUHJvY2VzczogdHJ1ZVxuICAgICAgICB9LFxuICAgICAgICBtYXhDb25jdXJyZW5jeTogNSxcbiAgICAgICAgZXhwZWN0ZWRDb25jdXJyZW5jeTogNVxuICAgIH0pO1xufSk7XG5cbnRlc3QoXCJsb2NhbCBwcm92aWRlciBubyBjb25jdXJyZW5jeSBmb3IgY3B1IGJvdW5kIHdvcmsgd2l0aG91dCBjaGlsZCBwcm9jZXNzZXNcIiwgYXN5bmMgdCA9PiB7XG4gICAgYXdhaXQgdGVzdENvbmN1cnJlbmN5KHQsIHtcbiAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgY2hpbGRQcm9jZXNzOiBmYWxzZVxuICAgICAgICB9LFxuICAgICAgICBtYXhDb25jdXJyZW5jeTogNSxcbiAgICAgICAgZXhwZWN0ZWRDb25jdXJyZW5jeTogMVxuICAgIH0pO1xufSk7XG5cbnRlc3QoXCJsb2NhbCBwcm92aWRlciBjbGVhbnVwIHdhaXRzIGZvciBhbGwgY2hpbGQgcHJvY2Vzc2VzIHRvIGV4aXRcIiwgYXN5bmMgdCA9PiB7XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdExvY2FsKGZ1bmNzLCB7XG4gICAgICAgIGNoaWxkUHJvY2VzczogdHJ1ZSxcbiAgICAgICAgZ2M6IFwib2ZmXCJcbiAgICB9KTtcbiAgICBmYWFzdE1vZHVsZS5mdW5jdGlvbnMuc3Bpbig1MDAwKS5jYXRjaChfID0+IHt9KTtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBhd2FpdCBzbGVlcCgxMDApO1xuICAgICAgICBpZiAoZmFhc3RNb2R1bGUuc3RhdGUuZXhlY3V0b3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIHQuaXMoZmFhc3RNb2R1bGUuc3RhdGUuZXhlY3V0b3JzLmxlbmd0aCwgMSwgXCJleGVjdXRvciBpcyBub3QgcnVubmluZ1wiKTtcbiAgICBhd2FpdCBmYWFzdE1vZHVsZS5jbGVhbnVwKHsgZ2NUaW1lb3V0OiA2MCB9KTtcbiAgICB0LmlzKGZhYXN0TW9kdWxlLnN0YXRlLmV4ZWN1dG9ycy5sZW5ndGgsIDAsIFwiZXhlY3V0b3JzIGFyZSBydW5uaW5nIGFmdGVyIGNsZWFudXBcIik7XG59KTtcblxudGVzdChcImxvY2FsIHVucmVzb2x2ZWQgbW9kdWxlXCIsIGFzeW5jIHQgPT4ge1xuICAgIHQucGxhbigxKTtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBmYWFzdExvY2FsKHt9KTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0LnJlZ2V4KGVyci5tZXNzYWdlLCAvQ291bGQgbm90IGZpbmQgZmlsZS8pO1xuICAgIH1cbn0pO1xuXG50ZXN0KFwibG9jYWwgaXNzdWUgIzM3XCIsIGFzeW5jIHQgPT4ge1xuICAgIC8vIFByZXZpb3VzbHkgdGhpcyBjb2RlIGNhdXNlZCBhbiBleGNlcHRpb24gYWJvdXQgbW9kdWxlIHdyYXBwZXIgbm90IGJlaW5nXG4gICAgLy8gcmUtZW50cmFudC4gVGhlIHByb2JsZW0gd2FzIGEgcmFjZSBjb25kaXRpb24gYmV0d2VlbiB3cmFwcGVyIHNlbGVjdGlvblxuICAgIC8vIGFuZCBleGVjdXRpb24gaW4gbG9jYWwgcHJvdmlkZXIuIFNvbHZlZCBieSBtYWtpbmcgd3JhcHBlciBzZWxlY3RvciBhXG4gICAgLy8gcmVndWxhciBmdW5jdGlvbiBpbnN0ZWFkIG9mIGFuIGFzeW5jIGZ1bmN0aW9uLlxuICAgIGNvbnN0IG0gPSBhd2FpdCBmYWFzdExvY2FsKGZ1bmNzKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCB7IGlkZW50aXR5U3RyaW5nOiBpZGVudGl0eSB9ID0gbS5mdW5jdGlvbnM7XG4gICAgICAgIGF3YWl0IGlkZW50aXR5KFwiYVwiKTtcbiAgICAgICAgY29uc3QgYiA9IGlkZW50aXR5KFwiYlwiKTtcbiAgICAgICAgY29uc3QgYyA9IGlkZW50aXR5KFwiY1wiKTtcbiAgICAgICAgYXdhaXQgYjtcbiAgICAgICAgYXdhaXQgYztcbiAgICAgICAgLy8gVGVzdCBzdWNjZWVkcyBpZiBubyBleGNlcHRpb25zIGFyZSB0aHJvd24uXG4gICAgICAgIHQudHJ1ZSh0cnVlKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBtLmNsZWFudXAoKTtcbiAgICB9XG59KTtcbiJdfQ== |
\ | No newline at end of file |