UNPKG

faastjs

Version:

Serverless batch computing made simple.

182 lines 29.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const ava_1 = tslib_1.__importDefault(require("ava")); const index_1 = require("../index"); const funcs = tslib_1.__importStar(require("./fixtures/functions")); const util_1 = require("./fixtures/util"); function nodeMajorVersion() { const match = process.version.match(/^v(\d+)\./); if (match) { return Number(match[1]); } return 0; } async function testBasic(t, provider, options) { const opts = { timeout: 60, gc: "off", description: t.title, env: { faastEnvironmentVariable: "the_answer_is_42" }, ...options }; const faastModule = await (0, index_1.faast)(provider, funcs, opts); const remote = faastModule.functions; try { t.is(await remote.hello("Andy"), "Hello Andy!"); t.is(await remote.identityString("你好"), "你好"); t.is(await remote.identityNum(42), 42); t.is(await remote.identityNum(Infinity), Infinity); t.is(await remote.identityNum(-Infinity), -Infinity); if (nodeMajorVersion() >= 10) { t.is(await remote.identityNum(NaN), NaN); } t.is(await remote.empty(), undefined); t.is(await remote.arrow("arrow"), "arrow"); t.is(await remote.asyncArrow("asyncArrow"), "asyncArrow"); t.is(await remote.fact(5), 120); t.is(await remote.concat("abc", "def"), "abcdef"); await t.throwsAsync(() => remote.error("hey"), { message: /Expected error. Arg: hey/ }); t.is(await remote.noargs(), "called function with no args."); t.is(await remote.async(), "async function: success"); t.is(typeof (await remote.path()), "string"); t.is(await remote.optionalArg(), "No arg"); t.is(await remote.optionalArg("has arg"), "has arg"); const date = new Date(); t.deepEqual(await remote.identityDate(date), date); const buffer = Buffer.from("contents"); t.deepEqual(await remote.identityBuffer(buffer), buffer); t.deepEqual(await remote.identityArrayNum([42, 8, 10]), [42, 8, 10]); const inf = [Infinity, -Infinity]; t.deepEqual(await remote.identityArrayNum(inf), inf); if (nodeMajorVersion() >= 10) { t.deepEqual(await remote.identityArrayNum([NaN]), [NaN]); } t.deepEqual(await remote.identityArrayString(["a", "there"]), ["a", "there"]); t.is(await remote.identityBool(true), true); t.is(await remote.identityBool(false), false); t.is(await remote.identityUndefined(undefined), undefined); t.is(await remote.identityNull(null), null); t.deepEqual(await remote.identityObject({}), {}); t.deepEqual(await remote.identityObject({ a: 42, b: "hello" }), { a: 42, b: "hello" }); const int8 = Int8Array.of(0, -8, 42); t.deepEqual(await remote.identityInt8(int8), int8); const uint8 = Uint8Array.of(0, 8, 42); t.deepEqual(await remote.identityUint8(uint8), uint8); const uint8Clamped = Uint8ClampedArray.of(0, 8, 42); t.deepEqual(await remote.identityUint8Clamped(uint8Clamped), uint8Clamped); const int16 = Int16Array.of(0, 8, 42, -1); t.deepEqual(await remote.identityInt16(int16), int16); const uint16 = Uint16Array.of(0, 8, 42, -1); t.deepEqual(await remote.identityUint16(uint16), uint16); const int32 = Int32Array.of(0, 8, 42, -1); t.deepEqual(await remote.identityInt32(int32), int32); const uint32 = Uint32Array.of(0, 8, 42, -1); t.deepEqual(await remote.identityUint32(uint32), uint32); const float32 = Float32Array.of(0, 0.3, 100.042, -1); t.deepEqual(await remote.identityFloat32(float32), float32); const float64 = Float64Array.of(0, 0.3, 100.042, -1); t.deepEqual(await remote.identityFloat64(float64), float64); const m = new Map([ [1, 2], [42, 10] ]); t.deepEqual(await remote.identityMap(m), m); const s = new Set([1, 42, 100]); t.deepEqual(await remote.identitySet(s), s); try { await remote.emptyReject(); t.fail("remote.emptyReject() did not reject as expected"); } catch (err) { t.is(err, undefined); } try { await remote.rejected(); t.fail("remote.rejected() did not reject as expected"); } catch (err) { t.is(err, "intentionally rejected"); } try { await remote.customError(); t.fail("remote.customError() did not reject as expected"); } catch (err) { t.true(err instanceof index_1.FaastError); t.truthy(err.message.match(/^custom error message/)); t.is(index_1.FaastError.info(err).custom, "custom value"); } t.is(await remote.getEnv("faastEnvironmentVariable"), "the_answer_is_42"); t.is(await remote.getEnv("faastNonexistent"), undefined); t.deepEqual(await remote.returnsError(), funcs.returnsError()); const elements = ["bar", "baz"]; t.deepEqual(await (0, util_1.toArray)(remote.generator(elements)), elements); t.deepEqual(await (0, util_1.toArray)(remote.asyncGenerator(elements)), elements); try { for await (const _ of remote.asyncGeneratorError("async generator failed")) { // ignore } t.fail(`remote.asyncGeneratorError() did not reject as expected (2)`); } catch (err) { t.true(err instanceof index_1.FaastError); t.truthy(err.message.match(/^async generator failed/)); } } finally { await faastModule.cleanup(); } } async function testBasicRequire(t, provider) { const requiredFuncs = require("./fixtures/functions"); const opts = { timeout: 30, gc: "off", description: t.title }; const faastModule = await (0, index_1.faast)(provider, requiredFuncs, opts); const remote = faastModule.functions; try { t.is(await remote.identityString("id"), "id"); t.is(await remote.arrow("arrow"), "arrow"); } finally { await faastModule.cleanup(); } } // async function testCpuMetrics(t: ExecutionContext, provider: Provider) { // t.plan(4); // const lambda = await faast(provider, funcs, { // childProcess: true, // timeout: 90, // memorySize: 512, // maxRetries: 0, // gc: "off", // description: t.title // }); // try { // const NSec = 4; // await lambda.functions.spin(NSec * 1000); // const usage = lambda.cpuUsage.get("spin"); // t.truthy(usage); // t.true(usage!.size > 0); // for (const [, instance] of usage!) { // t.true(instance.stime instanceof Statistics); // t.true(instance.utime instanceof Statistics); // break; // } // } finally { // await lambda.cleanup(); // } // } for (const provider of index_1.providers) { for (const config of [...util_1.configs, ...util_1.noValidateConfigs]) { ava_1.default.serial((0, util_1.title)(provider, `basic calls`, config), testBasic, provider, config); } // XXX Disable CPU metrics for now. // test(title(provider, `cpu metrics are received`), testCpuMetrics, provider); ava_1.default.serial((0, util_1.title)(provider, `basic calls with require`), testBasicRequire, provider); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3Rlc3QvYmFzaWMudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxzREFBNkM7QUFDN0Msb0NBQWlGO0FBQ2pGLG9FQUE4QztBQUM5QywwQ0FBNkU7QUFFN0UsU0FBUyxnQkFBZ0I7SUFDckIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDakQsSUFBSSxLQUFLLEVBQUU7UUFDUCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUMzQjtJQUNELE9BQU8sQ0FBQyxDQUFDO0FBQ2IsQ0FBQztBQUVELEtBQUssVUFBVSxTQUFTLENBQ3BCLENBQW1CLEVBQ25CLFFBQWtCLEVBQ2xCLE9BQXNCO0lBRXRCLE1BQU0sSUFBSSxHQUFrQjtRQUN4QixPQUFPLEVBQUUsRUFBRTtRQUNYLEVBQUUsRUFBRSxLQUFLO1FBQ1QsV0FBVyxFQUFFLENBQUMsQ0FBQyxLQUFLO1FBQ3BCLEdBQUcsRUFBRSxFQUFFLHdCQUF3QixFQUFFLGtCQUFrQixFQUFFO1FBQ3JELEdBQUcsT0FBTztLQUNiLENBQUM7SUFFRixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUEsYUFBSyxFQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdkQsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLFNBQVMsQ0FBQztJQUVyQyxJQUFJO1FBQ0EsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdkMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDbkQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3JELElBQUksZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDMUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDNUM7UUFDRCxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFELENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2hDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNsRCxNQUFNLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUMzQyxPQUFPLEVBQUUsMEJBQTBCO1NBQ3RDLENBQUMsQ0FBQztRQUNILENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxN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QkFBMEIsQ0FBQyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxDQUFDO0NBQ3hGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHRlc3QsIHsgRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gXCJhdmFcIjtcbmltcG9ydCB7IENvbW1vbk9wdGlvbnMsIGZhYXN0LCBGYWFzdEVycm9yLCBQcm92aWRlciwgcHJvdmlkZXJzIH0gZnJvbSBcIi4uL2luZGV4XCI7XG5pbXBvcnQgKiBhcyBmdW5jcyBmcm9tIFwiLi9maXh0dXJlcy9mdW5jdGlvbnNcIjtcbmltcG9ydCB7IGNvbmZpZ3MsIG5vVmFsaWRhdGVDb25maWdzLCB0aXRsZSwgdG9BcnJheSB9IGZyb20gXCIuL2ZpeHR1cmVzL3V0aWxcIjtcblxuZnVuY3Rpb24gbm9kZU1ham9yVmVyc2lvbigpIHtcbiAgICBjb25zdCBtYXRjaCA9IHByb2Nlc3MudmVyc2lvbi5tYXRjaCgvXnYoXFxkKylcXC4vKTtcbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcihtYXRjaFsxXSk7XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0ZXN0QmFzaWMoXG4gICAgdDogRXhlY3V0aW9uQ29udGV4dCxcbiAgICBwcm92aWRlcjogUHJvdmlkZXIsXG4gICAgb3B0aW9uczogQ29tbW9uT3B0aW9uc1xuKSB7XG4gICAgY29uc3Qgb3B0czogQ29tbW9uT3B0aW9ucyA9IHtcbiAgICAgICAgdGltZW91dDogNjAsXG4gICAgICAgIGdjOiBcIm9mZlwiLFxuICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZSxcbiAgICAgICAgZW52OiB7IGZhYXN0RW52aXJvbm1lbnRWYXJpYWJsZTogXCJ0aGVfYW5zd2VyX2lzXzQyXCIgfSxcbiAgICAgICAgLi4ub3B0aW9uc1xuICAgIH07XG5cbiAgICBjb25zdCBmYWFzdE1vZHVsZSA9IGF3YWl0IGZhYXN0KHByb3ZpZGVyLCBmdW5jcywgb3B0cyk7XG4gICAgY29uc3QgcmVtb3RlID0gZmFhc3RNb2R1bGUuZnVuY3Rpb25zO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgdC5pcyhhd2FpdCByZW1vdGUuaGVsbG8oXCJBbmR5XCIpLCBcIkhlbGxvIEFuZHkhXCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5pZGVudGl0eVN0cmluZyhcIuS9oOWlvVwiKSwgXCLkvaDlpb1cIik7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmlkZW50aXR5TnVtKDQyKSwgNDIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5pZGVudGl0eU51bShJbmZpbml0eSksIEluZmluaXR5KTtcbiAgICAgICAgdC5pcyhhd2FpdCByZW1vdGUuaWRlbnRpdHlOdW0oLUluZmluaXR5KSwgLUluZmluaXR5KTtcbiAgICAgICAgaWYgKG5vZGVNYWpvclZlcnNpb24oKSA+PSAxMCkge1xuICAgICAgICAgICAgdC5pcyhhd2FpdCByZW1vdGUuaWRlbnRpdHlOdW0oTmFOKSwgTmFOKTtcbiAgICAgICAgfVxuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5lbXB0eSgpLCB1bmRlZmluZWQpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5hcnJvdyhcImFycm93XCIpLCBcImFycm93XCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5hc3luY0Fycm93KFwiYXN5bmNBcnJvd1wiKSwgXCJhc3luY0Fycm93XCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5mYWN0KDUpLCAxMjApO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5jb25jYXQoXCJhYmNcIiwgXCJkZWZcIiksIFwiYWJjZGVmXCIpO1xuICAgICAgICBhd2FpdCB0LnRocm93c0FzeW5jKCgpID0+IHJlbW90ZS5lcnJvcihcImhleVwiKSwge1xuICAgICAgICAgICAgbWVzc2FnZTogL0V4cGVjdGVkIGVycm9yLiBBcmc6IGhleS9cbiAgICAgICAgfSk7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLm5vYXJncygpLCBcImNhbGxlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3MuXCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5hc3luYygpLCBcImFzeW5jIGZ1bmN0aW9uOiBzdWNjZXNzXCIpO1xuICAgICAgICB0LmlzKHR5cGVvZiAoYXdhaXQgcmVtb3RlLnBhdGgoKSksIFwic3RyaW5nXCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5vcHRpb25hbEFyZygpLCBcIk5vIGFyZ1wiKTtcbiAgICAgICAgdC5pcyhhd2FpdCByZW1vdGUub3B0aW9uYWxBcmcoXCJoYXMgYXJnXCIpLCBcImhhcyBhcmdcIik7XG5cbiAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eURhdGUoZGF0ZSksIGRhdGUpO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFwiY29udGVudHNcIik7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eUJ1ZmZlcihidWZmZXIpLCBidWZmZXIpO1xuXG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eUFycmF5TnVtKFs0MiwgOCwgMTBdKSwgWzQyLCA4LCAxMF0pO1xuXG4gICAgICAgIGNvbnN0IGluZiA9IFtJbmZpbml0eSwgLUluZmluaXR5XTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5QXJyYXlOdW0oaW5mKSwgaW5mKTtcblxuICAgICAgICBpZiAobm9kZU1ham9yVmVyc2lvbigpID49IDEwKSB7XG4gICAgICAgICAgICB0LmRlZXBFcXVhbChhd2FpdCByZW1vdGUuaWRlbnRpdHlBcnJheU51bShbTmFOXSksIFtOYU5dKTtcbiAgICAgICAgfVxuICAgICAgICB0LmRlZXBFcXVhbChhd2FpdCByZW1vdGUuaWRlbnRpdHlBcnJheVN0cmluZyhbXCJhXCIsIFwidGhlcmVcIl0pLCBbXCJhXCIsIFwidGhlcmVcIl0pO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5pZGVudGl0eUJvb2wodHJ1ZSksIHRydWUpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5pZGVudGl0eUJvb2woZmFsc2UpLCBmYWxzZSk7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmlkZW50aXR5VW5kZWZpbmVkKHVuZGVmaW5lZCksIHVuZGVmaW5lZCk7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmlkZW50aXR5TnVsbChudWxsKSwgbnVsbCk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eU9iamVjdCh7fSksIHt9KTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5T2JqZWN0KHsgYTogNDIsIGI6IFwiaGVsbG9cIiB9KSwge1xuICAgICAgICAgICAgYTogNDIsXG4gICAgICAgICAgICBiOiBcImhlbGxvXCJcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGludDggPSBJbnQ4QXJyYXkub2YoMCwgLTgsIDQyKTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5SW50OChpbnQ4KSwgaW50OCk7XG5cbiAgICAgICAgY29uc3QgdWludDggPSBVaW50OEFycmF5Lm9mKDAsIDgsIDQyKTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5VWludDgodWludDgpLCB1aW50OCk7XG5cbiAgICAgICAgY29uc3QgdWludDhDbGFtcGVkID0gVWludDhDbGFtcGVkQXJyYXkub2YoMCwgOCwgNDIpO1xuICAgICAgICB0LmRlZXBFcXVhbChhd2FpdCByZW1vdGUuaWRlbnRpdHlVaW50OENsYW1wZWQodWludDhDbGFtcGVkKSwgdWludDhDbGFtcGVkKTtcblxuICAgICAgICBjb25zdCBpbnQxNiA9IEludDE2QXJyYXkub2YoMCwgOCwgNDIsIC0xKTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5SW50MTYoaW50MTYpLCBpbnQxNik7XG5cbiAgICAgICAgY29uc3QgdWludDE2ID0gVWludDE2QXJyYXkub2YoMCwgOCwgNDIsIC0xKTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgcmVtb3RlLmlkZW50aXR5VWludDE2KHVpbnQxNiksIHVpbnQxNik7XG5cbiAgICAgICAgY29uc3QgaW50MzIgPSBJbnQzMkFycmF5Lm9mKDAsIDgsIDQyLCAtMSk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eUludDMyKGludDMyKSwgaW50MzIpO1xuXG4gICAgICAgIGNvbnN0IHVpbnQzMiA9IFVpbnQzMkFycmF5Lm9mKDAsIDgsIDQyLCAtMSk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eVVpbnQzMih1aW50MzIpLCB1aW50MzIpO1xuXG4gICAgICAgIGNvbnN0IGZsb2F0MzIgPSBGbG9hdDMyQXJyYXkub2YoMCwgMC4zLCAxMDAuMDQyLCAtMSk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eUZsb2F0MzIoZmxvYXQzMiksIGZsb2F0MzIpO1xuXG4gICAgICAgIGNvbnN0IGZsb2F0NjQgPSBGbG9hdDY0QXJyYXkub2YoMCwgMC4zLCAxMDAuMDQyLCAtMSk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eUZsb2F0NjQoZmxvYXQ2NCksIGZsb2F0NjQpO1xuXG4gICAgICAgIGNvbnN0IG0gPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFsxLCAyXSxcbiAgICAgICAgICAgIFs0MiwgMTBdXG4gICAgICAgIF0pO1xuICAgICAgICB0LmRlZXBFcXVhbChhd2FpdCByZW1vdGUuaWRlbnRpdHlNYXAobSksIG0pO1xuXG4gICAgICAgIGNvbnN0IHMgPSBuZXcgU2V0KFsxLCA0MiwgMTAwXSk7XG4gICAgICAgIHQuZGVlcEVxdWFsKGF3YWl0IHJlbW90ZS5pZGVudGl0eVNldChzKSwgcyk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHJlbW90ZS5lbXB0eVJlamVjdCgpO1xuICAgICAgICAgICAgdC5mYWlsKFwicmVtb3RlLmVtcHR5UmVqZWN0KCkgZGlkIG5vdCByZWplY3QgYXMgZXhwZWN0ZWRcIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICB0LmlzKGVyciwgdW5kZWZpbmVkKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgcmVtb3RlLnJlamVjdGVkKCk7XG4gICAgICAgICAgICB0LmZhaWwoXCJyZW1vdGUucmVqZWN0ZWQoKSBkaWQgbm90IHJlamVjdCBhcyBleHBlY3RlZFwiKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgICAgIHQuaXMoZXJyLCBcImludGVudGlvbmFsbHkgcmVqZWN0ZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHJlbW90ZS5jdXN0b21FcnJvcigpO1xuICAgICAgICAgICAgdC5mYWlsKFwicmVtb3RlLmN1c3RvbUVycm9yKCkgZGlkIG5vdCByZWplY3QgYXMgZXhwZWN0ZWRcIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICB0LnRydWUoZXJyIGluc3RhbmNlb2YgRmFhc3RFcnJvcik7XG4gICAgICAgICAgICB0LnRydXRoeShlcnIubWVzc2FnZS5tYXRjaCgvXmN1c3RvbSBlcnJvciBtZXNzYWdlLykpO1xuICAgICAgICAgICAgdC5pcyhGYWFzdEVycm9yLmluZm8oZXJyKS5jdXN0b20sIFwiY3VzdG9tIHZhbHVlXCIpO1xuICAgICAgICB9XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmdldEVudihcImZhYXN0RW52aXJvbm1lbnRWYXJpYWJsZVwiKSwgXCJ0aGVfYW5zd2VyX2lzXzQyXCIpO1xuICAgICAgICB0LmlzKGF3YWl0IHJlbW90ZS5nZXRFbnYoXCJmYWFzdE5vbmV4aXN0ZW50XCIpLCB1bmRlZmluZWQpO1xuICAgICAgICB0LmRlZXBFcXVhbChhd2FpdCByZW1vdGUucmV0dXJuc0Vycm9yKCksIGZ1bmNzLnJldHVybnNFcnJvcigpKTtcblxuICAgICAgICBjb25zdCBlbGVtZW50cyA9IFtcImJhclwiLCBcImJhelwiXTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgdG9BcnJheShyZW1vdGUuZ2VuZXJhdG9yKGVsZW1lbnRzKSksIGVsZW1lbnRzKTtcbiAgICAgICAgdC5kZWVwRXF1YWwoYXdhaXQgdG9BcnJheShyZW1vdGUuYXN5bmNHZW5lcmF0b3IoZWxlbWVudHMpKSwgZWxlbWVudHMpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZm9yIGF3YWl0IChjb25zdCBfIG9mIHJlbW90ZS5hc3luY0dlbmVyYXRvckVycm9yKFwiYXN5bmMgZ2VuZXJhdG9yIGZhaWxlZFwiKSkge1xuICAgICAgICAgICAgICAgIC8vIGlnbm9yZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdC5mYWlsKGByZW1vdGUuYXN5bmNHZW5lcmF0b3JFcnJvcigpIGRpZCBub3QgcmVqZWN0IGFzIGV4cGVjdGVkICgyKWApO1xuICAgICAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICAgICAgdC50cnVlKGVyciBpbnN0YW5jZW9mIEZhYXN0RXJyb3IpO1xuICAgICAgICAgICAgdC50cnV0aHkoKGVyciBhcyBGYWFzdEVycm9yKS5tZXNzYWdlLm1hdGNoKC9eYXN5bmMgZ2VuZXJhdG9yIGZhaWxlZC8pKTtcbiAgICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICAgIGF3YWl0IGZhYXN0TW9kdWxlLmNsZWFudXAoKTtcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRlc3RCYXNpY1JlcXVpcmUodDogRXhlY3V0aW9uQ29udGV4dCwgcHJvdmlkZXI6IFByb3ZpZGVyKSB7XG4gICAgY29uc3QgcmVxdWlyZWRGdW5jcyA9IHJlcXVpcmUoXCIuL2ZpeHR1cmVzL2Z1bmN0aW9uc1wiKTtcbiAgICBjb25zdCBvcHRzOiBDb21tb25PcHRpb25zID0geyB0aW1lb3V0OiAzMCwgZ2M6IFwib2ZmXCIsIGRlc2NyaXB0aW9uOiB0LnRpdGxlIH07XG4gICAgY29uc3QgZmFhc3RNb2R1bGUgPSBhd2FpdCBmYWFzdChwcm92aWRlciwgcmVxdWlyZWRGdW5jcywgb3B0cyk7XG4gICAgY29uc3QgcmVtb3RlID0gZmFhc3RNb2R1bGUuZnVuY3Rpb25zO1xuICAgIHRyeSB7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmlkZW50aXR5U3RyaW5nKFwiaWRcIiksIFwiaWRcIik7XG4gICAgICAgIHQuaXMoYXdhaXQgcmVtb3RlLmFycm93KFwiYXJyb3dcIiksIFwiYXJyb3dcIik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYXdhaXQgZmFhc3RNb2R1bGUuY2xlYW51cCgpO1xuICAgIH1cbn1cblxuLy8gYXN5bmMgZnVuY3Rpb24gdGVzdENwdU1ldHJpY3ModDogRXhlY3V0aW9uQ29udGV4dCwgcHJvdmlkZXI6IFByb3ZpZGVyKSB7XG4vLyAgICAgdC5wbGFuKDQpO1xuXG4vLyAgICAgY29uc3QgbGFtYmRhID0gYXdhaXQgZmFhc3QocHJvdmlkZXIsIGZ1bmNzLCAge1xuLy8gICAgICAgICBjaGlsZFByb2Nlc3M6IHRydWUsXG4vLyAgICAgICAgIHRpbWVvdXQ6IDkwLFxuLy8gICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4vLyAgICAgICAgIG1heFJldHJpZXM6IDAsXG4vLyAgICAgICAgIGdjOiBcIm9mZlwiLFxuLy8gICAgICAgICBkZXNjcmlwdGlvbjogdC50aXRsZVxuLy8gICAgIH0pO1xuXG4vLyAgICAgdHJ5IHtcbi8vICAgICAgICAgY29uc3QgTlNlYyA9IDQ7XG4vLyAgICAgICAgIGF3YWl0IGxhbWJkYS5mdW5jdGlvbnMuc3BpbihOU2VjICogMTAwMCk7XG4vLyAgICAgICAgIGNvbnN0IHVzYWdlID0gbGFtYmRhLmNwdVVzYWdlLmdldChcInNwaW5cIik7XG4vLyAgICAgICAgIHQudHJ1dGh5KHVzYWdlKTtcbi8vICAgICAgICAgdC50cnVlKHVzYWdlIS5zaXplID4gMCk7XG4vLyAgICAgICAgIGZvciAoY29uc3QgWywgaW5zdGFuY2VdIG9mIHVzYWdlISkge1xuLy8gICAgICAgICAgICAgdC50cnVlKGluc3RhbmNlLnN0aW1lIGluc3RhbmNlb2YgU3RhdGlzdGljcyk7XG4vLyAgICAgICAgICAgICB0LnRydWUoaW5zdGFuY2UudXRpbWUgaW5zdGFuY2VvZiBTdGF0aXN0aWNzKTtcbi8vICAgICAgICAgICAgIGJyZWFrO1xuLy8gICAgICAgICB9XG4vLyAgICAgfSBmaW5hbGx5IHtcbi8vICAgICAgICAgYXdhaXQgbGFtYmRhLmNsZWFudXAoKTtcbi8vICAgICB9XG4vLyB9XG5cbmZvciAoY29uc3QgcHJvdmlkZXIgb2YgcHJvdmlkZXJzKSB7XG4gICAgZm9yIChjb25zdCBjb25maWcgb2YgWy4uLmNvbmZpZ3MsIC4uLm5vVmFsaWRhdGVDb25maWdzXSkge1xuICAgICAgICB0ZXN0LnNlcmlhbCh0aXRsZShwcm92aWRlciwgYGJhc2ljIGNhbGxzYCwgY29uZmlnKSwgdGVzdEJhc2ljLCBwcm92aWRlciwgY29uZmlnKTtcbiAgICB9XG4gICAgLy8gWFhYIERpc2FibGUgQ1BVIG1ldHJpY3MgZm9yIG5vdy5cbiAgICAvLyB0ZXN0KHRpdGxlKHByb3ZpZGVyLCBgY3B1IG1ldHJpY3MgYXJlIHJlY2VpdmVkYCksIHRlc3RDcHVNZXRyaWNzLCBwcm92aWRlcik7XG4gICAgdGVzdC5zZXJpYWwodGl0bGUocHJvdmlkZXIsIGBiYXNpYyBjYWxscyB3aXRoIHJlcXVpcmVgKSwgdGVzdEJhc2ljUmVxdWlyZSwgcHJvdmlkZXIpO1xufVxuIl19