@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
193 lines • 26.4 kB
JavaScript
"use strict";
const lib_1 = require("../lib");
const intrinsic_1 = require("../lib/private/intrinsic");
const evaluate_cfn_1 = require("./evaluate-cfn");
/**
* Return two Tokens, one of which evaluates to a Token directly, one which evaluates to it lazily
*/
function tokensThatResolveTo(value) {
return [
new intrinsic_1.Intrinsic(value),
lib_1.Lazy.anyValue({ produce: () => value })
];
}
module.exports = {
'string tokens can be JSONified and JSONification can be reversed'(test) {
const stack = new lib_1.Stack();
for (const token of tokensThatResolveTo('woof woof')) {
// GIVEN
const fido = { name: 'Fido', speaks: token };
// WHEN
const resolved = stack.resolve(stack.toJsonString(fido));
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), '{"name":"Fido","speaks":"woof woof"}');
}
test.done();
},
'string tokens can be embedded while being JSONified'(test) {
const stack = new lib_1.Stack();
for (const token of tokensThatResolveTo('woof woof')) {
// GIVEN
const fido = { name: 'Fido', speaks: `deep ${token}` };
// WHEN
const resolved = stack.resolve(stack.toJsonString(fido));
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), '{"name":"Fido","speaks":"deep woof woof"}');
}
test.done();
},
'constant string has correct amount of quotes applied'(test) {
const stack = new lib_1.Stack();
const inputString = 'Hello, "world"';
// WHEN
const resolved = stack.resolve(stack.toJsonString(inputString));
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), JSON.stringify(inputString));
test.done();
},
'integer Tokens behave correctly in stringification and JSONification'(test) {
// GIVEN
const stack = new lib_1.Stack();
const num = new intrinsic_1.Intrinsic(1);
const embedded = `the number is ${num}`;
// WHEN
test.equal(evaluate_cfn_1.evaluateCFN(stack.resolve(embedded)), "the number is 1");
test.equal(evaluate_cfn_1.evaluateCFN(stack.resolve(stack.toJsonString({ embedded }))), "{\"embedded\":\"the number is 1\"}");
test.equal(evaluate_cfn_1.evaluateCFN(stack.resolve(stack.toJsonString({ num }))), "{\"num\":1}");
test.done();
},
'tokens in strings survive additional TokenJSON.stringification()'(test) {
// GIVEN
const stack = new lib_1.Stack();
for (const token of tokensThatResolveTo('pong!')) {
// WHEN
const stringified = stack.toJsonString(`ping? ${token}`);
// THEN
test.equal(evaluate_cfn_1.evaluateCFN(stack.resolve(stringified)), '"ping? pong!"');
}
test.done();
},
'intrinsic Tokens embed correctly in JSONification'(test) {
// GIVEN
const stack = new lib_1.Stack();
const bucketName = new intrinsic_1.Intrinsic({ Ref: 'MyBucket' });
// WHEN
const resolved = stack.resolve(stack.toJsonString({ theBucket: bucketName }));
// THEN
const context = { MyBucket: 'TheName' };
test.equal(evaluate_cfn_1.evaluateCFN(resolved, context), '{"theBucket":"TheName"}');
test.done();
},
'fake intrinsics are serialized to objects'(test) {
const stack = new lib_1.Stack();
const fakeIntrinsics = new intrinsic_1.Intrinsic({
a: {
'Fn::GetArtifactAtt': {
key: 'val',
},
},
b: {
'Fn::GetParam': [
'val1',
'val2',
],
},
});
const stringified = stack.toJsonString(fakeIntrinsics);
test.equal(evaluate_cfn_1.evaluateCFN(stack.resolve(stringified)), '{"a":{"Fn::GetArtifactAtt":{"key":"val"}},"b":{"Fn::GetParam":["val1","val2"]}}');
test.done();
},
'embedded string literals in intrinsics are escaped when calling TokenJSON.stringify()'(test) {
// GIVEN
const stack = new lib_1.Stack();
const token = lib_1.Fn.join('', ['Hello', 'This\nIs', 'Very "cool"']);
// WHEN
const resolved = stack.resolve(stack.toJsonString({
literal: 'I can also "contain" quotes',
token
}));
// THEN
const expected = '{"literal":"I can also \\"contain\\" quotes","token":"HelloThis\\nIsVery \\"cool\\""}';
test.equal(evaluate_cfn_1.evaluateCFN(resolved), expected);
test.done();
},
'Tokens in Tokens are handled correctly'(test) {
// GIVEN
const stack = new lib_1.Stack();
const bucketName = new intrinsic_1.Intrinsic({ Ref: 'MyBucket' });
const combinedName = lib_1.Fn.join('', ['The bucket name is ', bucketName.toString()]);
// WHEN
const resolved = stack.resolve(stack.toJsonString({ theBucket: combinedName }));
// THEN
const context = { MyBucket: 'TheName' };
test.equal(evaluate_cfn_1.evaluateCFN(resolved, context), '{"theBucket":"The bucket name is TheName"}');
test.done();
},
'Doubly nested strings evaluate correctly in JSON context'(test) {
// WHEN
const stack = new lib_1.Stack();
const fidoSays = lib_1.Lazy.stringValue({ produce: () => 'woof' });
// WHEN
const resolved = stack.resolve(stack.toJsonString({
information: `Did you know that Fido says: ${fidoSays}`
}));
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), '{"information":"Did you know that Fido says: woof"}');
test.done();
},
'Doubly nested intrinsics evaluate correctly in JSON context'(test) {
// GIVEN
const stack = new lib_1.Stack();
const fidoSays = lib_1.Lazy.anyValue({ produce: () => ({ Ref: 'Something' }) });
// WHEN
const resolved = stack.resolve(stack.toJsonString({
information: `Did you know that Fido says: ${fidoSays}`
}));
// THEN
const context = { Something: 'woof woof' };
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved, context), '{"information":"Did you know that Fido says: woof woof"}');
test.done();
},
'Quoted strings in embedded JSON context are escaped'(test) {
// GIVEN
const stack = new lib_1.Stack();
const fidoSays = lib_1.Lazy.stringValue({ produce: () => '"woof"' });
// WHEN
const resolved = stack.resolve(stack.toJsonString({
information: `Did you know that Fido says: ${fidoSays}`
}));
// THEN
test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), '{"information":"Did you know that Fido says: \\"woof\\""}');
test.done();
},
'cross-stack references are also properly converted by toJsonString()'(test) {
// GIVEN
const app = new lib_1.App();
const stack1 = new lib_1.Stack(app, 'Stack1');
const stack2 = new lib_1.Stack(app, 'Stack2');
// WHEN
new lib_1.CfnOutput(stack2, 'Stack1Id', { value: stack2.toJsonString({
Stack1Id: stack1.stackId,
Stack2Id: stack2.stackId,
}) });
// THEN
const asm = app.synth();
test.deepEqual(asm.getStackByName('Stack2').template, {
Outputs: {
Stack1Id: {
Value: {
'Fn::Join': ['', [
'{"Stack1Id":"',
{ 'Fn::ImportValue': 'Stack1:ExportsOutputRefAWSStackIdB2DD5BAA' },
'","Stack2Id":"',
{ Ref: 'AWS::StackId' },
'"}'
]]
}
}
}
});
test.done();
},
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5jbG91ZGZvcm1hdGlvbi1qc29uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidGVzdC5jbG91ZGZvcm1hdGlvbi1qc29uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSxnQ0FBZ0U7QUFDaEUsd0RBQXFEO0FBQ3JELGlEQUE2QztBQTBPN0M7O0dBRUc7QUFDSCxTQUFTLG1CQUFtQixDQUFDLEtBQVU7SUFDckMsT0FBTztRQUNMLElBQUkscUJBQVMsQ0FBQyxLQUFLLENBQUM7UUFDcEIsVUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztLQUN4QyxDQUFDO0FBQ0osQ0FBQztBQWhQRCxpQkFBUztJQUNQLGtFQUFrRSxDQUFDLElBQVU7UUFDM0UsTUFBTSxLQUFLLEdBQUcsSUFBSSxXQUFLLEVBQUUsQ0FBQztRQUUxQixLQUFLLE1BQU0sS0FBSyxJQUFJLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxFQUFFO1lBQ3BELFFBQVE7WUFDUixNQUFNLElBQUksR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBRTdDLE9BQU87WUFDUCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUV6RCxPQUFPO1lBQ1AsSUFBSSxDQUFDLFNBQVMsQ0FBQywwQkFBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLHNDQUFzQyxDQUFDLENBQUM7U0FDL0U7UUFFRCxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQscURBQXFELENBQUMsSUFBVTtRQUM5RCxNQUFNLEtBQUssR0FBRyxJQUFJLFdBQUssRUFBRSxDQUFDO1FBRTFCLEtBQUssTUFBTSxLQUFLLElBQUksbUJBQW1CLENBQUMsV0FBVyxDQUFDLEVBQUU7WUFDcEQsUUFBUTtZQUNS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LENBQUU7cUJBQ0o7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNkLENBQUM7Q0FDRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVGVzdCB9IGZyb20gJ25vZGV1bml0JztcbmltcG9ydCB7IEFwcCwgQ2ZuT3V0cHV0LCBGbiwgTGF6eSwgU3RhY2ssIFRva2VuIH0gZnJvbSAnLi4vbGliJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4uL2xpYi9wcml2YXRlL2ludHJpbnNpYyc7XG5pbXBvcnQgeyBldmFsdWF0ZUNGTiB9IGZyb20gJy4vZXZhbHVhdGUtY2ZuJztcblxuZXhwb3J0ID0ge1xuICAnc3RyaW5nIHRva2VucyBjYW4gYmUgSlNPTmlmaWVkIGFuZCBKU09OaWZpY2F0aW9uIGNhbiBiZSByZXZlcnNlZCcodGVzdDogVGVzdCkge1xuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgICBmb3IgKGNvbnN0IHRva2VuIG9mIHRva2Vuc1RoYXRSZXNvbHZlVG8oJ3dvb2Ygd29vZicpKSB7XG4gICAgICAvLyBHSVZFTlxuICAgICAgY29uc3QgZmlkbyA9IHsgbmFtZTogJ0ZpZG8nLCBzcGVha3M6IHRva2VuIH07XG5cbiAgICAgIC8vIFdIRU5cbiAgICAgIGNvbnN0IHJlc29sdmVkID0gc3RhY2sucmVzb2x2ZShzdGFjay50b0pzb25TdHJpbmcoZmlkbykpO1xuXG4gICAgICAvLyBUSEVOXG4gICAgICB0ZXN0LmRlZXBFcXVhbChldmFsdWF0ZUNGTihyZXNvbHZlZCksICd7XCJuYW1lXCI6XCJGaWRvXCIsXCJzcGVha3NcIjpcIndvb2Ygd29vZlwifScpO1xuICAgIH1cblxuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICdzdHJpbmcgdG9rZW5zIGNhbiBiZSBlbWJlZGRlZCB3aGlsZSBiZWluZyBKU09OaWZpZWQnKHRlc3Q6IFRlc3QpIHtcbiAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuXG4gICAgZm9yIChjb25zdCB0b2tlbiBvZiB0b2tlbnNUaGF0UmVzb2x2ZVRvKCd3b29mIHdvb2YnKSkge1xuICAgICAgLy8gR0lWRU5cbiAgICAgIGNvbnN0IGZpZG8gPSB7IG5hbWU6ICdGaWRvJywgc3BlYWtzOiBgZGVlcCAke3Rva2VufWAgfTtcblxuICAgICAgLy8gV0hFTlxuICAgICAgY29uc3QgcmVzb2x2ZWQgPSBzdGFjay5yZXNvbHZlKHN0YWNrLnRvSnNvblN0cmluZyhmaWRvKSk7XG5cbiAgICAgIC8vIFRIRU5cbiAgICAgIHRlc3QuZGVlcEVxdWFsKGV2YWx1YXRlQ0ZOKHJlc29sdmVkKSwgJ3tcIm5hbWVcIjpcIkZpZG9cIixcInNwZWFrc1wiOlwiZGVlcCB3b29mIHdvb2ZcIn0nKTtcbiAgICB9XG5cbiAgICB0ZXN0LmRvbmUoKTtcbiAgfSxcblxuICAnY29uc3RhbnQgc3RyaW5nIGhhcyBjb3JyZWN0IGFtb3VudCBvZiBxdW90ZXMgYXBwbGllZCcodGVzdDogVGVzdCkge1xuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgICBjb25zdCBpbnB1dFN0cmluZyA9ICdIZWxsbywgXCJ3b3JsZFwiJztcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXNvbHZlZCA9IHN0YWNrLnJlc29sdmUoc3RhY2sudG9Kc29uU3RyaW5nKGlucHV0U3RyaW5nKSk7XG5cbiAgICAvLyBUSEVOXG4gICAgdGVzdC5kZWVwRXF1YWwoZXZhbHVhdGVDRk4ocmVzb2x2ZWQpLCBKU09OLnN0cmluZ2lmeShpbnB1dFN0cmluZykpO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2ludGVnZXIgVG9rZW5zIGJlaGF2ZSBjb3JyZWN0bHkgaW4gc3RyaW5naWZpY2F0aW9uIGFuZCBKU09OaWZpY2F0aW9uJyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIGNvbnN0IG51bSA9IG5ldyBJbnRyaW5zaWMoMSk7XG4gICAgY29uc3QgZW1iZWRkZWQgPSBgdGhlIG51bWJlciBpcyAke251bX1gO1xuXG4gICAgLy8gV0hFTlxuICAgIHRlc3QuZXF1YWwoZXZhbHVhdGVDRk4oc3RhY2sucmVzb2x2ZShlbWJlZGRlZCkpLCBcInRoZSBudW1iZXIgaXMgMVwiKTtcbiAgICB0ZXN0LmVxdWFsKGV2YWx1YXRlQ0ZOKHN0YWNrLnJlc29sdmUoc3RhY2sudG9Kc29uU3RyaW5nKHsgZW1iZWRkZWQgfSkpKSwgXCJ7XFxcImVtYmVkZGVkXFxcIjpcXFwidGhlIG51bWJlciBpcyAxXFxcIn1cIik7XG4gICAgdGVzdC5lcXVhbChldmFsdWF0ZUNGTihzdGFjay5yZXNvbHZlKHN0YWNrLnRvSnNvblN0cmluZyh7IG51bSB9KSkpLCBcIntcXFwibnVtXFxcIjoxfVwiKTtcblxuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICd0b2tlbnMgaW4gc3RyaW5ncyBzdXJ2aXZlIGFkZGl0aW9uYWwgVG9rZW5KU09OLnN0cmluZ2lmaWNhdGlvbigpJyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIGZvciAoY29uc3QgdG9rZW4gb2YgdG9rZW5zVGhhdFJlc29sdmVUbygncG9uZyEnKSkge1xuICAgICAgLy8gV0hFTlxuICAgICAgY29uc3Qgc3RyaW5naWZpZWQgPSBzdGFjay50b0pzb25TdHJpbmcoYHBpbmc/ICR7dG9rZW59YCk7XG5cbiAgICAgIC8vIFRIRU5cbiAgICAgIHRlc3QuZXF1YWwoZXZhbHVhdGVDRk4oc3RhY2sucmVzb2x2ZShzdHJpbmdpZmllZCkpLCAnXCJwaW5nPyBwb25nIVwiJyk7XG4gICAgfVxuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2ludHJpbnNpYyBUb2tlbnMgZW1iZWQgY29ycmVjdGx5IGluIEpTT05pZmljYXRpb24nKHRlc3Q6IFRlc3QpIHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgYnVja2V0TmFtZSA9IG5ldyBJbnRyaW5zaWMoeyBSZWY6ICdNeUJ1Y2tldCcgfSk7XG5cbiAgICAvLyBXSEVOXG4gICAgY29uc3QgcmVzb2x2ZWQgPSBzdGFjay5yZXNvbHZlKHN0YWNrLnRvSnNvblN0cmluZyh7IHRoZUJ1Y2tldDogYnVja2V0TmFtZSB9KSk7XG5cbiAgICAvLyBUSEVOXG4gICAgY29uc3QgY29udGV4dCA9IHtNeUJ1Y2tldDogJ1RoZU5hbWUnfTtcbiAgICB0ZXN0LmVxdWFsKGV2YWx1YXRlQ0ZOKHJlc29sdmVkLCBjb250ZXh0KSwgJ3tcInRoZUJ1Y2tldFwiOlwiVGhlTmFtZVwifScpO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2Zha2UgaW50cmluc2ljcyBhcmUgc2VyaWFsaXplZCB0byBvYmplY3RzJyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICBjb25zdCBmYWtlSW50cmluc2ljcyA9IG5ldyBJbnRyaW5zaWMoe1xuICAgICAgYToge1xuICAgICAgICAnRm46OkdldEFydGlmYWN0QXR0Jzoge1xuICAgICAgICAgIGtleTogJ3ZhbCcsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYjoge1xuICAgICAgICAnRm46OkdldFBhcmFtJzogW1xuICAgICAgICAgICd2YWwxJyxcbiAgICAgICAgICAndmFsMicsXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc3RyaW5naWZpZWQgPSBzdGFjay50b0pzb25TdHJpbmcoZmFrZUludHJpbnNpY3MpO1xuICAgIHRlc3QuZXF1YWwoZXZhbHVhdGVDRk4oc3RhY2sucmVzb2x2ZShzdHJpbmdpZmllZCkpLFxuICAgICAgICAne1wiYVwiOntcIkZuOjpHZXRBcnRpZmFjdEF0dFwiOntcImtleVwiOlwidmFsXCJ9fSxcImJcIjp7XCJGbjo6R2V0UGFyYW1cIjpbXCJ2YWwxXCIsXCJ2YWwyXCJdfX0nKTtcblxuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICdlbWJlZGRlZCBzdHJpbmcgbGl0ZXJhbHMgaW4gaW50cmluc2ljcyBhcmUgZXNjYXBlZCB3aGVuIGNhbGxpbmcgVG9rZW5KU09OLnN0cmluZ2lmeSgpJyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIGNvbnN0IHRva2VuID0gRm4uam9pbignJywgWyAnSGVsbG8nLCAnVGhpc1xcbklzJywgJ1ZlcnkgXCJjb29sXCInIF0pO1xuXG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IHJlc29sdmVkID0gc3RhY2sucmVzb2x2ZShzdGFjay50b0pzb25TdHJpbmcoe1xuICAgICAgbGl0ZXJhbDogJ0kgY2FuIGFsc28gXCJjb250YWluXCIgcXVvdGVzJyxcbiAgICAgIHRva2VuXG4gICAgfSkpO1xuXG4gICAgLy8gVEhFTlxuICAgIGNvbnN0IGV4cGVjdGVkID0gJ3tcImxpdGVyYWxcIjpcIkkgY2FuIGFsc28gXFxcXFwiY29udGFpblxcXFxcIiBxdW90ZXNcIixcInRva2VuXCI6XCJIZWxsb1RoaXNcXFxcbklzVmVyeSBcXFxcXCJjb29sXFxcXFwiXCJ9JztcbiAgICB0ZXN0LmVxdWFsKGV2YWx1YXRlQ0ZOKHJlc29sdmVkKSwgZXhwZWN0ZWQpO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ1Rva2VucyBpbiBUb2tlbnMgYXJlIGhhbmRsZWQgY29ycmVjdGx5Jyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIGNvbnN0IGJ1Y2tldE5hbWUgPSBuZXcgSW50cmluc2ljKHsgUmVmOiAnTXlCdWNrZXQnIH0pO1xuICAgIGNvbnN0IGNvbWJpbmVkTmFtZSA9IEZuLmpvaW4oJycsIFsgJ1RoZSBidWNrZXQgbmFtZSBpcyAnLCBidWNrZXROYW1lLnRvU3RyaW5nKCkgXSk7XG5cbiAgICAvLyBXSEVOXG4gICAgY29uc3QgcmVzb2x2ZWQgPSBzdGFjay5yZXNvbHZlKHN0YWNrLnRvSnNvblN0cmluZyh7IHRoZUJ1Y2tldDogY29tYmluZWROYW1lIH0pKTtcblxuICAgIC8vIFRIRU5cbiAgICBjb25zdCBjb250ZXh0ID0ge015QnVja2V0OiAnVGhlTmFtZSd9O1xuICAgIHRlc3QuZXF1YWwoZXZhbHVhdGVDRk4ocmVzb2x2ZWQsIGNvbnRleHQpLCAne1widGhlQnVja2V0XCI6XCJUaGUgYnVja2V0IG5hbWUgaXMgVGhlTmFtZVwifScpO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ0RvdWJseSBuZXN0ZWQgc3RyaW5ncyBldmFsdWF0ZSBjb3JyZWN0bHkgaW4gSlNPTiBjb250ZXh0Jyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgZmlkb1NheXMgPSBMYXp5LnN0cmluZ1ZhbHVlKHsgcHJvZHVjZTogKCkgPT4gJ3dvb2YnIH0pO1xuXG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IHJlc29sdmVkID0gc3RhY2sucmVzb2x2ZShzdGFjay50b0pzb25TdHJpbmcoe1xuICAgICAgaW5mb3JtYXRpb246IGBEaWQgeW91IGtub3cgdGhhdCBGaWRvIHNheXM6ICR7Zmlkb1NheXN9YFxuICAgIH0pKTtcblxuICAgIC8vIFRIRU5cbiAgICB0ZXN0LmRlZXBFcXVhbChldmFsdWF0ZUNGTihyZXNvbHZlZCksICd7XCJpbmZvcm1hdGlvblwiOlwiRGlkIHlvdSBrbm93IHRoYXQgRmlkbyBzYXlzOiB3b29mXCJ9Jyk7XG5cbiAgICB0ZXN0LmRvbmUoKTtcbiAgfSxcblxuICAnRG91Ymx5IG5lc3RlZCBpbnRyaW5zaWNzIGV2YWx1YXRlIGNvcnJlY3RseSBpbiBKU09OIGNvbnRleHQnKHRlc3Q6IFRlc3QpIHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgZmlkb1NheXMgPSBMYXp5LmFueVZhbHVlKHsgcHJvZHVjZTogKCkgPT4gKHsgUmVmOiAnU29tZXRoaW5nJyB9KSB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXNvbHZlZCA9IHN0YWNrLnJlc29sdmUoc3RhY2sudG9Kc29uU3RyaW5nKHtcbiAgICAgIGluZm9ybWF0aW9uOiBgRGlkIHlvdSBrbm93IHRoYXQgRmlkbyBzYXlzOiAke2ZpZG9TYXlzfWBcbiAgICB9KSk7XG5cbiAgICAvLyBUSEVOXG4gICAgY29uc3QgY29udGV4dCA9IHtTb21ldGhpbmc6ICd3b29mIHdvb2YnfTtcbiAgICB0ZXN0LmRlZXBFcXVhbChldmFsdWF0ZUNGTihyZXNvbHZlZCwgY29udGV4dCksICd7XCJpbmZvcm1hdGlvblwiOlwiRGlkIHlvdSBrbm93IHRoYXQgRmlkbyBzYXlzOiB3b29mIHdvb2ZcIn0nKTtcblxuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICdRdW90ZWQgc3RyaW5ncyBpbiBlbWJlZGRlZCBKU09OIGNvbnRleHQgYXJlIGVzY2FwZWQnKHRlc3Q6IFRlc3QpIHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgZmlkb1NheXMgPSBMYXp5LnN0cmluZ1ZhbHVlKHsgcHJvZHVjZTogKCkgPT4gJ1wid29vZlwiJyB9KTtcblxuICAgIC8vIFdIRU5cbiAgICBjb25zdCByZXNvbHZlZCA9IHN0YWNrLnJlc29sdmUoc3RhY2sudG9Kc29uU3RyaW5nKHtcbiAgICAgIGluZm9ybWF0aW9uOiBgRGlkIHlvdSBrbm93IHRoYXQgRmlkbyBzYXlzOiAke2ZpZG9TYXlzfWBcbiAgICB9KSk7XG5cbiAgICAvLyBUSEVOXG4gICAgdGVzdC5kZWVwRXF1YWwoZXZhbHVhdGVDRk4ocmVzb2x2ZWQpLCAne1wiaW5mb3JtYXRpb25cIjpcIkRpZCB5b3Uga25vdyB0aGF0IEZpZG8gc2F5czogXFxcXFwid29vZlxcXFxcIlwifScpO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2Nyb3NzLXN0YWNrIHJlZmVyZW5jZXMgYXJlIGFsc28gcHJvcGVybHkgY29udmVydGVkIGJ5IHRvSnNvblN0cmluZygpJyh0ZXN0OiBUZXN0KSB7XG4gICAgLy8gR0lWRU5cbiAgICBjb25zdCBhcHAgPSBuZXcgQXBwKCk7XG4gICAgY29uc3Qgc3RhY2sxID0gbmV3IFN0YWNrKGFwcCwgJ1N0YWNrMScpO1xuICAgIGNvbnN0IHN0YWNrMiA9IG5ldyBTdGFjayhhcHAsICdTdGFjazInKTtcblxuICAgIC8vIFdIRU5cbiAgICBuZXcgQ2ZuT3V0cHV0KHN0YWNrMiwgJ1N0YWNrMUlkJywgeyB2YWx1ZTogc3RhY2syLnRvSnNvblN0cmluZyh7XG4gICAgICBTdGFjazFJZDogc3RhY2sxLnN0YWNrSWQsXG4gICAgICBTdGFjazJJZDogc3RhY2syLnN0YWNrSWQsXG4gICAgfSl9KTtcblxuICAgIC8vIFRIRU5cbiAgICBjb25zdCBhc20gPSBhcHAuc3ludGgoKTtcbiAgICB0ZXN0LmRlZXBFcXVhbChhc20uZ2V0U3RhY2tCeU5hbWUoJ1N0YWNrMicpLnRlbXBsYXRlLCB7XG4gICAgICBPdXRwdXRzOiB7XG4gICAgICAgIFN0YWNrMUlkOiB7XG4gICAgICAgICAgVmFsdWU6IHtcbiAgICAgICAgICAgICdGbjo6Sm9pbic6IFsgJycsIFtcbiAgICAgICAgICAgICAgJ3tcIlN0YWNrMUlkXCI6XCInLFxuICAgICAgICAgICAgICB7ICdGbjo6SW1wb3J0VmFsdWUnOiAnU3RhY2sxOkV4cG9ydHNPdXRwdXRSZWZBV1NTdGFja0lkQjJERDVCQUEnIH0sXG4gICAgICAgICAgICAgICdcIixcIlN0YWNrMklkXCI6XCInLFxuICAgICAgICAgICAgICB7IFJlZjogJ0FXUzo6U3RhY2tJZCcgfSxcbiAgICAgICAgICAgICAgJ1wifSdcbiAgICAgICAgICAgIF0gXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG59O1xuXG4vKipcbiAqIFJldHVybiB0d28gVG9rZW5zLCBvbmUgb2Ygd2hpY2ggZXZhbHVhdGVzIHRvIGEgVG9rZW4gZGlyZWN0bHksIG9uZSB3aGljaCBldmFsdWF0ZXMgdG8gaXQgbGF6aWx5XG4gKi9cbmZ1bmN0aW9uIHRva2Vuc1RoYXRSZXNvbHZlVG8odmFsdWU6IGFueSk6IFRva2VuW10ge1xuICByZXR1cm4gW1xuICAgIG5ldyBJbnRyaW5zaWModmFsdWUpLFxuICAgIExhenkuYW55VmFsdWUoeyBwcm9kdWNlOiAoKSA9PiB2YWx1ZSB9KVxuICBdO1xufVxuIl19