1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const ava_1 = require("ava");
|
4 | const util_1 = require("util");
|
5 | const index_1 = require("../index");
|
6 | const funcs = require("./fixtures/functions");
|
7 | const util_2 = require("./fixtures/util");
|
8 | /**
|
9 | * Note that there is an AWS Lambda bug where timeouts are not delivered if the
|
10 | * function has a timeout >= 300s, and the function is invoked directly with the
|
11 | * Invoke API (e.g. in faast.js' "https" mode, which is the default.). In this
|
12 | * case if faast.js has childProcess mode on (the default), then it will set its
|
13 | * own timeout. This situation is not explicitly tested here because it would
|
14 | * make the entire testsuite slower for just one test. To test this situation
|
15 | * manually, change the timeout to 300 or more, and run one of these tests:
|
16 | *
|
17 | * $ ava --timeout=10m -m="remote aws generator timeout { mode: 'https', childProcess: true }"
|
18 | * $ ava --timeout=10m -m="remote aws timeout { mode: 'https', childProcess: true }"
|
19 | */
|
20 | async function testTimeout(t, provider, options) {
|
21 | const lambda = await (0, index_1.faast)(provider, funcs, {
|
22 | ...options,
|
23 | timeout: 5,
|
24 | maxRetries: 0,
|
25 | gc: "off",
|
26 | description: t.title
|
27 | });
|
28 | t.plan(1);
|
29 | // t.log(`${lambda.logUrl()}`);
|
30 | try {
|
31 | try {
|
32 | await lambda.functions.infiniteLoop();
|
33 | }
|
34 | catch (err) {
|
35 | const isTimeout = index_1.FaastError.hasCauseWithName(err, index_1.FaastErrorNames.ETIMEOUT);
|
36 | t.is(isTimeout, true, `${(0, util_1.inspect)(err)}`);
|
37 | }
|
38 | }
|
39 | finally {
|
40 | await lambda.cleanup();
|
41 | }
|
42 | }
|
43 | /**
|
44 | * The purpose of this test is to verify that a CPU hogging async generator
|
45 | * function won't starve the sending logic, so yield messages prior to the CPU
|
46 | * intensive work are delivered.
|
47 | */
|
48 | async function testGenerator(t, provider, options) {
|
49 | t.plan(2);
|
50 | const lambda = await (0, index_1.faast)(provider, funcs, {
|
51 | ...options,
|
52 | timeout: 5,
|
53 | maxRetries: 0,
|
54 | gc: "off",
|
55 | description: t.title
|
56 | });
|
57 | // t.log(`${lambda.logUrl()}`);
|
58 | try {
|
59 | const arg = "hello, generator!";
|
60 | for await (const result of lambda.functions.generateThenInfiniteLoop(arg)) {
|
61 | t.is(result, arg);
|
62 | }
|
63 | t.fail("Did not timeout");
|
64 | }
|
65 | catch (err) {
|
66 | t.is(index_1.FaastError.hasCauseWithName(err, index_1.FaastErrorNames.ETIMEOUT), true);
|
67 | }
|
68 | finally {
|
69 | await lambda.cleanup();
|
70 | }
|
71 | }
|
72 | async function memoryLimitOk(t, provider, options) {
|
73 | const lambda = await (0, index_1.faast)(provider, funcs, {
|
74 | ...options,
|
75 | timeout: 200,
|
76 | memorySize: 512,
|
77 | maxRetries: 0,
|
78 | gc: "off",
|
79 | description: t.title
|
80 | });
|
81 | try {
|
82 | const bytes = 64 * 1024 * 1024;
|
83 | const rv = await lambda.functions.allocate(bytes);
|
84 | t.is(rv.elems, bytes / 8);
|
85 | }
|
86 | finally {
|
87 | await lambda.cleanup();
|
88 | }
|
89 | }
|
90 | async function memoryLimitFail(t, provider, options) {
|
91 | const lambda = await (0, index_1.faast)(provider, funcs, {
|
92 | ...options,
|
93 | timeout: 200,
|
94 | memorySize: 512,
|
95 | maxRetries: 0,
|
96 | gc: "off",
|
97 | description: t.title
|
98 | });
|
99 | try {
|
100 | const bytes = 512 * 1024 * 1024;
|
101 | await t.throwsAsync(lambda.functions.allocate(bytes), { message: /memory/i });
|
102 | }
|
103 | finally {
|
104 | lambda && (await lambda.cleanup());
|
105 | }
|
106 | }
|
107 | // Note that this test takes 180s by default. Set the ava timeout to 2m or
|
108 | // longer otherwise it will fail with a timeout error.
|
109 | async function testLongInvoke(t, provider, options) {
|
110 | // The http timeout is 120s in awssdk by default. Uncomment the following
|
111 | // line to shorten it to 20s for focused testing. Note that shortening it
|
112 | // below 20s causes (harmless) timeout error messages from SQS on the long
|
113 | // polling response queue. If faast.js is working correctly, the shortened
|
114 | // timeout should not cause a test failure.
|
115 | //
|
116 | // config.update({ httpOptions: { timeout: 20000 } });
|
117 | const opts = {
|
118 | timeout: 500,
|
119 | gc: "off",
|
120 | description: t.title,
|
121 | ...options
|
122 | };
|
123 | const faastModule = await (0, index_1.faast)(provider, funcs, opts);
|
124 | const remote = faastModule.functions;
|
125 | try {
|
126 | let i = 0;
|
127 | const args = ["a", "b", "c"];
|
128 | // The use of an async generator is to mimick a real use case from a
|
129 | // client of faast.js. The presence of an error should also be revealed
|
130 | // with a regular remote function call.
|
131 | for await (const arg of remote.asyncGeneratorDelay(args, 60000)) {
|
132 | t.is(arg, args[i++]);
|
133 | }
|
134 | }
|
135 | finally {
|
136 | await faastModule.cleanup();
|
137 | }
|
138 | }
|
139 | const allLimits = ["memory", "timeout", "long", "generator"];
|
140 | const configurations = [
|
141 | ["aws", { mode: "https", childProcess: true }, allLimits],
|
142 | ["aws", { mode: "queue", childProcess: true }, allLimits],
|
143 | ["aws", { mode: "https", childProcess: false }, ["memory", "timeout", "generator"]],
|
144 | ["aws", { mode: "queue", childProcess: false }, ["memory", "timeout", "generator"]],
|
145 | ["google", { mode: "https", childProcess: true }, ["memory", "timeout", "long"]],
|
146 | ["google", { mode: "queue", childProcess: true }, []],
|
147 | ["local", {}, ["timeout"]]
|
148 | ];
|
149 | for (const [provider, config, limitTypes] of configurations) {
|
150 | const opts = (0, util_1.inspect)(config);
|
151 | if (limitTypes.find(t => t === "memory")) {
|
152 | (0, ava_1.default)((0, util_2.title)(provider, `memory under limit ${opts}`), memoryLimitOk, provider, config);
|
153 | (0, ava_1.default)((0, util_2.title)(provider, `out of memory`, config), memoryLimitFail, provider, config);
|
154 | }
|
155 | if (limitTypes.find(t => t === "timeout")) {
|
156 | (0, ava_1.default)((0, util_2.title)(provider, `timeout`, config), testTimeout, provider, config);
|
157 | }
|
158 | if (limitTypes.find(t => t === "long")) {
|
159 | (0, ava_1.default)((0, util_2.title)(provider, `long invoke`, config), testLongInvoke, provider, config);
|
160 | }
|
161 | if (limitTypes.find(t => t === "generator")) {
|
162 | (0, ava_1.default)((0, util_2.title)(provider, `generator timeout`, config), testGenerator, provider, config);
|
163 | }
|
164 | }
|
165 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGltaXRzLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90ZXN0L2xpbWl0cy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZDO0FBQzdDLCtCQUErQjtBQUMvQixvQ0FBdUY7QUFDdkYsOENBQThDO0FBQzlDLDBDQUF3QztBQUV4Qzs7Ozs7Ozs7Ozs7R0FXRztBQUNILEtBQUssVUFBVSxXQUFXLENBQ3RCLENBQW1CLEVBQ25CLFFBQWtCLEVBQ2xCLE9BQXNCO0lBRXRCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSxhQUFLLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRTtRQUN4QyxHQUFHLE9BQU87UUFDVixPQUFPLEVBQUUsQ0FBQztRQUNWLFVBQVUsRUFBRSxDQUFDO1FBQ2IsRUFBRSxFQUFFLEtBQUs7UUFDVCxXQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUs7S0FDdkIsQ0FBQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNWLCtCQUErQjtJQUMvQixJQUFJO1FBQ0EsSUFBSTtZQUNBLE1BQU0sTUFBTSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztTQUN6QztRQUFDLE9BQU8sR0FBUSxFQUFFO1lBQ2YsTUFBTSxTQUFTLEdBQUcsa0JBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsdUJBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3RSxDQUFDLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxJQUFBLGNBQU8sRUFBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDNUM7S0FDSjtZQUFTO1FBQ04sTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7S0FDMUI7QUFDTCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxhQUFhLENBQ3hCLENBQW1CLEVBQ25CLFFBQWtCLEVBQ2xCLE9BQXNCO0lBRXRCLENB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QyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssU0FBUyxDQUFDLEVBQUU7UUFDdkMsSUFBQSxhQUFJLEVBQUMsSUFBQSxZQUFLLEVBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0tBQzNFO0lBQ0QsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxFQUFFO1FBQ3BDLElBQUEsYUFBSSxFQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsRUFBRSxhQUFhLEVBQUUsTUFBTSxDQUFDLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztLQUNsRjtJQUNELElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxXQUFXLENBQUMsRUFBRTtRQUN6QyxJQUFBLGFBQUksRUFDQSxJQUFBLFlBQUssRUFBQyxRQUFRLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLEVBQzVDLGFBQWEsRUFDYixRQUFRLEVBQ1IsTUFBTSxDQUNULENBQUM7S0FDTDtDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IGluc3BlY3QgfSBmcm9tIFwidXRpbFwiO1xuaW1wb3J0IHsgQ29tbW9uT3B0aW9ucywgZmFhc3QsIEZhYXN0RXJyb3IsIEZhYXN0RXJyb3JOYW1lcywgUHJvdmlkZXIgfSBmcm9tIFwiLi4vaW5kZXhcIjtcbmltcG9ydCAqIGFzIGZ1bmNzIGZyb20gXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiO1xuaW1wb3J0IHsgdGl0bGUgfSBmcm9tIFwiLi9maXh0dXJlcy91dGlsXCI7XG5cbi8qKlxuICogTm90ZSB0aGF0IHRoZXJlIGlzIGFuIEFXUyBMYW1iZGEgYnVnIHdoZXJlIHRpbWVvdXRzIGFyZSBub3QgZGVsaXZlcmVkIGlmIHRoZVxuICogZnVuY3Rpb24gaGFzIGEgdGltZW91dCA+PSAzMDBzLCBhbmQgdGhlIGZ1bmN0aW9uIGlzIGludm9rZWQgZGlyZWN0bHkgd2l0aCB0aGVcbiAqIEludm9rZSBBUEkgKGUuZy4gaW4gZmFhc3QuanMnIFwiaHR0cHNcIiBtb2RlLCB3aGljaCBpcyB0aGUgZGVmYXVsdC4pLiBJbiB0aGlzXG4gKiBjYXNlIGlmIGZhYXN0LmpzIGhhcyBjaGlsZFByb2Nlc3MgbW9kZSBvbiAodGhlIGRlZmF1bHQpLCB0aGVuIGl0IHdpbGwgc2V0IGl0c1xuICogb3duIHRpbWVvdXQuIFRoaXMgc2l0dWF0aW9uIGlzIG5vdCBleHBsaWNpdGx5IHRlc3RlZCBoZXJlIGJlY2F1c2UgaXQgd291bGRcbiAqIG1ha2UgdGhlIGVudGlyZSB0ZXN0c3VpdGUgc2xvd2VyIGZvciBqdXN0IG9uZSB0ZXN0LiBUbyB0ZXN0IHRoaXMgc2l0dWF0aW9uXG4gKiBtYW51YWxseSwgY2hhbmdlIHRoZSB0aW1lb3V0IHRvIDMwMCBvciBtb3JlLCBhbmQgcnVuIG9uZSBvZiB0aGVzZSB0ZXN0czpcbiAqXG4gKiAgICAkIGF2YSAtLXRpbWVvdXQ9MTBtIC1tPVwicmVtb3RlIGF3cyBnZW5lcmF0b3IgdGltZW91dCB7IG1vZGU6ICdodHRwcycsIGNoaWxkUHJvY2VzczogdHJ1ZSB9XCJcbiAqICAgICQgYXZhIC0tdGltZW91dD0xMG0gLW09XCJyZW1vdGUgYXdzIHRpbWVvdXQgeyBtb2RlOiAnaHR0cHMnLCBjaGlsZFByb2Nlc3M6IHRydWUgfVwiXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRlc3RUaW1lb3V0KFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIGNvbnN0IGxhbWJkYSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0aW1lb3V0OiA1LFxuICAgICAgICBtYXhSZXRyaWVzOiAwLFxuICAgICAgICBnYzogXCJvZmZcIixcbiAgICAgICAgZGVzY3JpcHRpb246IHQudGl0bGVcbiAgICB9KTtcbiAgICB0LnBsYW4oMSk7XG4gICAgLy8gdC5sb2coYCR7bGFtYmRhLmxvZ1VybCgpfWApO1xuICAgIHRyeSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBsYW1iZGEuZnVuY3Rpb25zLmluZmluaXRlTG9vcCgpO1xuICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgY29uc3QgaXNUaW1lb3V0ID0gRmFhc3RFcnJvci5oYXNDYXVzZVdpdGhOYW1lKGVyciwgRmFhc3RFcnJvck5hbWVzLkVUSU1FT1VUKTtcbiAgICAgICAgICAgIHQuaXMoaXNUaW1lb3V0LCB0cnVlLCBgJHtpbnNwZWN0KGVycil9YCk7XG4gICAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBsYW1iZGEuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGUgcHVycG9zZSBvZiB0aGlzIHRlc3QgaXMgdG8gdmVyaWZ5IHRoYXQgYSBDUFUgaG9nZ2luZyBhc3luYyBnZW5lcmF0b3JcbiAqIGZ1bmN0aW9uIHdvbid0IHN0YXJ2ZSB0aGUgc2VuZGluZyBsb2dpYywgc28geWllbGQgbWVzc2FnZXMgcHJpb3IgdG8gdGhlIENQVVxuICogaW50ZW5zaXZlIHdvcmsgYXJlIGRlbGl2ZXJlZC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdGVzdEdlbmVyYXRvcihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIHByb3ZpZGVyOiBQcm92aWRlcixcbiAgICBvcHRpb25zOiBDb21tb25PcHRpb25zXG4pIHtcbiAgICB0LnBsYW4oMik7XG4gICAgY29uc3QgbGFtYmRhID0gYXdhaXQgZmFhc3QocHJvdmlkZXIsIGZ1bmNzLCB7XG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIHRpbWVvdXQ6IDUsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH0pO1xuICAgIC8vIHQubG9nKGAke2xhbWJkYS5sb2dVcmwoKX1gKTtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBhcmcgPSBcImhlbGxvLCBnZW5lcmF0b3IhXCI7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgcmVzdWx0IG9mIGxhbWJkYS5mdW5jdGlvbnMuZ2VuZXJhdGVUaGVuSW5maW5pdGVMb29wKGFyZykpIHtcbiAgICAgICAgICAgIHQuaXMocmVzdWx0LCBhcmcpO1xuICAgICAgICB9XG4gICAgICAgIHQuZmFpbChcIkRpZCBub3QgdGltZW91dFwiKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0LmlzKEZhYXN0RXJyb3IuaGFzQ2F1c2VXaXRoTmFtZShlcnIsIEZhYXN0RXJyb3JOYW1lcy5FVElNRU9VVCksIHRydWUpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGxhbWJkYS5jbGVhbnVwKCk7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtZW1vcnlMaW1pdE9rKFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIGNvbnN0IGxhbWJkYSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywge1xuICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB0aW1lb3V0OiAyMDAsXG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgbWF4UmV0cmllczogMCxcbiAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlXG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgICBjb25zdCBieXRlcyA9IDY0ICogMTAyNCAqIDEwMjQ7XG4gICAgICAgIGNvbnN0IHJ2ID0gYXdhaXQgbGFtYmRhLmZ1bmN0aW9ucy5hbGxvY2F0ZShieXRlcyk7XG4gICAgICAgIHQuaXMocnYuZWxlbXMsIGJ5dGVzIC8gOCk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgbGFtYmRhLmNsZWFudXAoKTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1lbW9yeUxpbWl0RmFpbChcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIHByb3ZpZGVyOiBQcm92aWRlcixcbiAgICBvcHRpb25zOiBDb21tb25PcHRpb25zXG4pIHtcbiAgICBjb25zdCBsYW1iZGEgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgZnVuY3MsIHtcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgdGltZW91dDogMjAwLFxuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIG1heFJldHJpZXM6IDAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuICAgIH0pO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYnl0ZXMgPSA1MTIgKiAxMDI0ICogMTAyNDtcbiAgICAgICAgYXdhaXQgdC50aHJvd3NBc3luYyhsYW1iZGEuZnVuY3Rpb25zLmFsbG9jYXRlKGJ5dGVzKSwgeyBtZXNzYWdlOiAvbWVtb3J5L2kgfSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgbGFtYmRhICYmIChhd2FpdCBsYW1iZGEuY2xlYW51cCgpKTtcbiAgICB9XG59XG5cbi8vIE5vdGUgdGhhdCB0aGlzIHRlc3QgdGFrZXMgMTgwcyBieSBkZWZhdWx0LiBTZXQgdGhlIGF2YSB0aW1lb3V0IHRvIDJtIG9yXG4vLyBsb25nZXIgb3RoZXJ3aXNlIGl0IHdpbGwgZmFpbCB3aXRoIGEgdGltZW91dCBlcnJvci5cbmFzeW5jIGZ1bmN0aW9uIHRlc3RMb25nSW52b2tlKFxuICAgIHQ6IEV4ZWN1dGlvbkNvbnRleHQsXG4gICAgcHJvdmlkZXI6IFByb3ZpZGVyLFxuICAgIG9wdGlvbnM6IENvbW1vbk9wdGlvbnNcbikge1xuICAgIC8vIFRoZSBodHRwIHRpbWVvdXQgaXMgMTIwcyBpbiBhd3NzZGsgYnkgZGVmYXVsdC4gVW5jb21tZW50IHRoZSBmb2xsb3dpbmdcbiAgICAvLyBsaW5lIHRvIHNob3J0ZW4gaXQgdG8gMjBzIGZvciBmb2N1c2VkIHRlc3RpbmcuIE5vdGUgdGhhdCBzaG9ydGVuaW5nIGl0XG4gICAgLy8gYmVsb3cgMjBzIGNhdXNlcyAoaGFybWxlc3MpIHRpbWVvdXQgZXJyb3IgbWVzc2FnZXMgZnJvbSBTUVMgb24gdGhlIGxvbmdcbiAgICAvLyBwb2xsaW5nIHJlc3BvbnNlIHF1ZXVlLiBJZiBmYWFzdC5qcyBpcyB3b3JraW5nIGNvcnJlY3RseSwgdGhlIHNob3J0ZW5lZFxuICAgIC8vIHRpbWVvdXQgc2hvdWxkIG5vdCBjYXVzZSBhIHRlc3QgZmFpbHVyZS5cbiAgICAvL1xuICAgIC8vIGNvbmZpZy51cGRhdGUoeyBodHRwT3B0aW9uczogeyB0aW1lb3V0OiAyMDAwMCB9IH0pO1xuICAgIGNvbnN0IG9wdHM6IENvbW1vbk9wdGlvbnMgPSB7XG4gICAgICAgIHRpbWVvdXQ6IDUwMCxcbiAgICAgICAgZ2M6IFwib2ZmXCIsXG4gICAgICAgIGRlc2NyaXB0aW9uOiB0LnRpdGxlLFxuICAgICAgICAuLi5vcHRpb25zXG4gICAgfTtcbiAgICBjb25zdCBmYWFzdE1vZHVsZSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywgb3B0cyk7XG4gICAgY29uc3QgcmVtb3RlID0gZmFhc3RNb2R1bGUuZnVuY3Rpb25zO1xuICAgIHRyeSB7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgY29uc3QgYXJncyA9IFtcImFcIiwgXCJiXCIsIFwiY1wiXTtcbiAgICAgICAgLy8gVGhlIHVzZSBvZiBhbiBhc3luYyBnZW5lcmF0b3IgaXMgdG8gbWltaWNrIGEgcmVhbCB1c2UgY2FzZSBmcm9tIGFcbiAgICAgICAgLy8gY2xpZW50IG9mIGZhYXN0LmpzLiBUaGUgcHJlc2VuY2Ugb2YgYW4gZXJyb3Igc2hvdWxkIGFsc28gYmUgcmV2ZWFsZWRcbiAgICAgICAgLy8gd2l0aCBhIHJlZ3VsYXIgcmVtb3RlIGZ1bmN0aW9uIGNhbGwuXG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgYXJnIG9mIHJlbW90ZS5hc3luY0dlbmVyYXRvckRlbGF5KGFyZ3MsIDYwMDAwKSkge1xuICAgICAgICAgICAgdC5pcyhhcmcsIGFyZ3NbaSsrXSk7XG4gICAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBhd2FpdCBmYWFzdE1vZHVsZS5jbGVhbnVwKCk7XG4gICAgfVxufVxuXG50eXBlIExpbWl0VHlwZSA9IFwibWVtb3J5XCIgfCBcInRpbWVvdXRcIiB8IFwiZ2VuZXJhdG9yXCIgfCBcImxvbmdcIjtcbmNvbnN0IGFsbExpbWl0cyA9IFtcIm1lbW9yeVwiLCBcInRpbWVvdXRcIiwgXCJsb25nXCIsIFwiZ2VuZXJhdG9yXCJdIGFzIGNvbnN0O1xuXG5jb25zdCBjb25maWd1cmF0aW9uczogW1Byb3ZpZGVyLCBDb21tb25PcHRpb25zLCByZWFkb25seSBMaW1pdFR5cGVbXV1bXSA9IFtcbiAgICBbXCJhd3NcIiwgeyBtb2RlOiBcImh0dHBzXCIsIGNoaWxkUHJvY2VzczogdHJ1ZSB9LCBhbGxMaW1pdHNdLFxuICAgIFtcImF3c1wiLCB7IG1vZGU6IFwicXVldWVcIiwgY2hpbGRQcm9jZXNzOiB0cnVlIH0sIGFsbExpbWl0c10sXG4gICAgW1wiYXdzXCIsIHsgbW9kZTogXCJodHRwc1wiLCBjaGlsZFByb2Nlc3M6IGZhbHNlIH0sIFtcIm1lbW9yeVwiLCBcInRpbWVvdXRcIiwgXCJnZW5lcmF0b3JcIl1dLFxuICAgIFtcImF3c1wiLCB7IG1vZGU6IFwicXVldWVcIiwgY2hpbGRQcm9jZXNzOiBmYWxzZSB9LCBbXCJtZW1vcnlcIiwgXCJ0aW1lb3V0XCIsIFwiZ2VuZXJhdG9yXCJdXSxcbiAgICBbXCJnb29nbGVcIiwgeyBtb2RlOiBcImh0dHBzXCIsIGNoaWxkUHJvY2VzczogdHJ1ZSB9LCBbXCJtZW1vcnlcIiwgXCJ0aW1lb3V0XCIsIFwibG9uZ1wiXV0sXG4gICAgW1wiZ29vZ2xlXCIsIHsgbW9kZTogXCJxdWV1ZVwiLCBjaGlsZFByb2Nlc3M6IHRydWUgfSwgW11dLFxuICAgIFtcImxvY2FsXCIsIHt9LCBbXCJ0aW1lb3V0XCJdXVxuXTtcblxuZm9yIChjb25zdCBbcHJvdmlkZXIsIGNvbmZpZywgbGltaXRUeXBlc10gb2YgY29uZmlndXJhdGlvbnMpIHtcbiAgICBjb25zdCBvcHRzID0gaW5zcGVjdChjb25maWcpO1xuICAgIGlmIChsaW1pdFR5cGVzLmZpbmQodCA9PiB0ID09PSBcIm1lbW9yeVwiKSkge1xuICAgICAgICB0ZXN0KFxuICAgICAgICAgICAgdGl0bGUocHJvdmlkZXIsIGBtZW1vcnkgdW5kZXIgbGltaXQgJHtvcHRzfWApLFxuICAgICAgICAgICAgbWVtb3J5TGltaXRPayxcbiAgICAgICAgICAgIHByb3ZpZGVyLFxuICAgICAgICAgICAgY29uZmlnXG4gICAgICAgICk7XG4gICAgICAgIHRlc3QodGl0bGUocHJvdmlkZXIsIGBvdXQgb2YgbWVtb3J5YCwgY29uZmlnKSwgbWVtb3J5TGltaXRGYWlsLCBwcm92aWRlciwgY29uZmlnKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0VHlwZXMuZmluZCh0ID0+IHQgPT09IFwidGltZW91dFwiKSkge1xuICAgICAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgdGltZW91dGAsIGNvbmZpZyksIHRlc3RUaW1lb3V0LCBwcm92aWRlciwgY29uZmlnKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0VHlwZXMuZmluZCh0ID0+IHQgPT09IFwibG9uZ1wiKSkge1xuICAgICAgICB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgbG9uZyBpbnZva2VgLCBjb25maWcpLCB0ZXN0TG9uZ0ludm9rZSwgcHJvdmlkZXIsIGNvbmZpZyk7XG4gICAgfVxuICAgIGlmIChsaW1pdFR5cGVzLmZpbmQodCA9PiB0ID09PSBcImdlbmVyYXRvclwiKSkge1xuICAgICAgICB0ZXN0KFxuICAgICAgICAgICAgdGl0bGUocHJvdmlkZXIsIGBnZW5lcmF0b3IgdGltZW91dGAsIGNvbmZpZyksXG4gICAgICAgICAgICB0ZXN0R2VuZXJhdG9yLFxuICAgICAgICAgICAgcHJvdmlkZXIsXG4gICAgICAgICAgICBjb25maWdcbiAgICAgICAgKTtcbiAgICB9XG59XG4iXX0= |
\ | No newline at end of file |