UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

578 lines 72 kB
"use strict"; const lib_1 = require("../lib"); const encoding_1 = require("../lib/private/encoding"); const intrinsic_1 = require("../lib/private/intrinsic"); const resolve_1 = require("../lib/private/resolve"); const evaluate_cfn_1 = require("./evaluate-cfn"); class Promise2 { constructor() { this.creationStack = []; } resolve() { return { Data: { stringProp: 'hello', numberProp: 1234, }, Recurse: new intrinsic_1.Intrinsic(42) }; } } class Promise1 { constructor() { this.creationStack = []; this.p2 = [new Promise2(), new Promise2()]; } resolve() { return this.p2; } } class BaseDataType { constructor(foo) { this.foo = foo; } } class DataType extends BaseDataType { constructor() { super(12); this.goo = 'hello'; } } /** * Return Tokens in both flavors that resolve to the given string */ function tokensThatResolveTo(value) { return [ new intrinsic_1.Intrinsic(value), lib_1.Lazy.anyValue({ produce: () => value }) ]; } /** * Wrapper for resolve that creates an throwaway Construct to call it on * * So I don't have to change all call sites in this file. */ function resolve(x) { return new lib_1.Stack().resolve(x); } module.exports = { 'resolve a plain old object should just return the object'(test) { const obj = { PlainOldObject: 123, Array: [1, 2, 3] }; test.deepEqual(resolve(obj), obj); test.done(); }, 'if a value is an object with a token value, it will be evaluated'(test) { const obj = { RegularValue: 'hello', LazyValue: new intrinsic_1.Intrinsic('World') }; test.deepEqual(resolve(obj), { RegularValue: 'hello', LazyValue: 'World' }); test.done(); }, 'tokens are evaluated anywhere in the object tree'(test) { const obj = new Promise1(); const actual = resolve({ Obj: obj }); test.deepEqual(actual, { Obj: [ { Data: { stringProp: "hello", numberProp: 1234 }, Recurse: 42 }, { Data: { stringProp: "hello", numberProp: 1234 }, Recurse: 42 } ] }); test.done(); }, 'tokens are evaluated recursively'(test) { const obj = new Promise1(); const actual = resolve(new intrinsic_1.Intrinsic({ Obj: obj })); test.deepEqual(actual, { Obj: [ { Data: { stringProp: "hello", numberProp: 1234 }, Recurse: 42 }, { Data: { stringProp: "hello", numberProp: 1234 }, Recurse: 42 } ] }); test.done(); }, 'empty arrays or objects are kept'(test) { test.deepEqual(resolve({}), {}); test.deepEqual(resolve([]), []); const obj = { Prop1: 1234, Prop2: {}, Prop3: [], Prop4: 'hello', Prop5: { PropA: {}, PropB: { PropC: [undefined, undefined], PropD: 'Yoohoo' } } }; test.deepEqual(resolve(obj), { Prop1: 1234, Prop2: {}, Prop3: [], Prop4: 'hello', Prop5: { PropA: {}, PropB: { PropC: [], PropD: 'Yoohoo' } } }); test.done(); }, 'if an object has a "resolve" property that is not a function, it is not considered a token'(test) { test.deepEqual(resolve({ a_token: { resolve: () => 78787 } }), { a_token: 78787 }); test.deepEqual(resolve({ not_a_token: { resolve: 12 } }), { not_a_token: { resolve: 12 } }); test.done(); }, // tslint:disable-next-line:max-line-length 'if a resolvable object inherits from a class that is also resolvable, the "constructor" function will not get in the way (uses Object.keys instead of "for in")'(test) { test.deepEqual(resolve({ prop: new DataType() }), { prop: { foo: 12, goo: 'hello' } }); test.done(); }, 'isToken(obj) can be used to determine if an object is a token'(test) { test.ok(lib_1.isResolvableObject({ resolve: () => 123 })); test.ok(lib_1.isResolvableObject({ a: 1, b: 2, resolve: () => 'hello' })); test.ok(!lib_1.isResolvableObject({ a: 1, b: 2, resolve: 3 })); test.done(); }, 'Token can be used to create tokens that contain a constant value'(test) { test.equal(resolve(new intrinsic_1.Intrinsic(12)), 12); test.equal(resolve(new intrinsic_1.Intrinsic('hello')), 'hello'); test.deepEqual(resolve(new intrinsic_1.Intrinsic(['hi', 'there'])), ['hi', 'there']); test.done(); }, 'resolving leaves a Date object in working order'(test) { const date = new Date('2000-01-01'); const resolved = resolve(date); test.equal(date.toString(), resolved.toString()); test.done(); }, 'tokens can be stringified and evaluated to conceptual value'(test) { // GIVEN const token = new intrinsic_1.Intrinsic('woof woof'); // WHEN const stringified = `The dog says: ${token}`; const resolved = resolve(stringified); // THEN test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), 'The dog says: woof woof'); test.done(); }, 'tokens stringification can be reversed'(test) { // GIVEN const token = new intrinsic_1.Intrinsic('woof woof'); // THEN test.equal(token, lib_1.Tokenization.reverseString(`${token}`).firstToken); test.done(); }, 'Tokens stringification and reversing of CloudFormation Tokens is implemented using Fn::Join'(test) { // GIVEN const token = new intrinsic_1.Intrinsic(({ woof: 'woof' })); // WHEN const stringified = `The dog says: ${token}`; const resolved = resolve(stringified); // THEN test.deepEqual(resolved, { 'Fn::Join': ['', ['The dog says: ', { woof: 'woof' }]] }); test.done(); }, 'Doubly nested strings evaluate correctly in scalar context'(test) { // GIVEN const token1 = new intrinsic_1.Intrinsic("world"); const token2 = new intrinsic_1.Intrinsic(`hello ${token1}`); // WHEN const resolved1 = resolve(token2.toString()); const resolved2 = resolve(token2); // THEN test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved1), "hello world"); test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved2), "hello world"); test.done(); }, 'integer Tokens can be stringified and evaluate to conceptual value'(test) { // GIVEN for (const token of tokensThatResolveTo(1)) { // WHEN const stringified = `the number is ${token}`; const resolved = resolve(stringified); // THEN test.deepEqual(evaluate_cfn_1.evaluateCFN(resolved), 'the number is 1'); } test.done(); }, 'intrinsic Tokens can be stringified and evaluate to conceptual value'(test) { // GIVEN for (const bucketName of tokensThatResolveTo({ Ref: 'MyBucket' })) { // WHEN const resolved = resolve(`my bucket is named ${bucketName}`); // THEN const context = { MyBucket: 'TheName' }; test.equal(evaluate_cfn_1.evaluateCFN(resolved, context), 'my bucket is named TheName'); } test.done(); }, 'tokens resolve properly in initial position'(test) { // GIVEN for (const token of tokensThatResolveTo('Hello')) { // WHEN const resolved = resolve(`${token} world`); // THEN test.equal(evaluate_cfn_1.evaluateCFN(resolved), 'Hello world'); } test.done(); }, 'side-by-side Tokens resolve correctly'(test) { // GIVEN for (const token1 of tokensThatResolveTo('Hello ')) { for (const token2 of tokensThatResolveTo('world')) { // WHEN const resolved = resolve(`${token1}${token2}`); // THEN test.equal(evaluate_cfn_1.evaluateCFN(resolved), 'Hello world'); } } test.done(); }, 'tokens can be used in hash keys but must resolve to a string'(test) { // GIVEN const token = new intrinsic_1.Intrinsic('I am a string'); // WHEN const s = { [token.toString()]: `boom ${token}` }; // THEN test.deepEqual(resolve(s), { 'I am a string': 'boom I am a string' }); test.done(); }, 'tokens can be nested in hash keys'(test) { // GIVEN const token = new intrinsic_1.Intrinsic(lib_1.Lazy.stringValue({ produce: () => lib_1.Lazy.stringValue({ produce: (() => 'I am a string') }) })); // WHEN const s = { [token.toString()]: `boom ${token}` }; // THEN test.deepEqual(resolve(s), { 'I am a string': 'boom I am a string' }); test.done(); }, 'tokens can be nested and concatenated in hash keys'(test) { // GIVEN const innerToken = new intrinsic_1.Intrinsic('toot'); const token = new intrinsic_1.Intrinsic(`${innerToken} the woot`); // WHEN const s = { [token.toString()]: `boom chicago` }; // THEN test.deepEqual(resolve(s), { 'toot the woot': 'boom chicago' }); test.done(); }, 'can find nested tokens in hash keys'(test) { // GIVEN const innerToken = new intrinsic_1.Intrinsic('toot'); const token = new intrinsic_1.Intrinsic(`${innerToken} the woot`); // WHEN const s = { [token.toString()]: `boom chicago` }; // THEN const tokens = resolve_1.findTokens(new lib_1.Stack(), () => s); test.ok(tokens.some(t => t === innerToken), 'Cannot find innerToken'); test.ok(tokens.some(t => t === token), 'Cannot find token'); test.done(); }, 'fails if token in a hash key resolves to a non-string'(test) { // GIVEN const token = new intrinsic_1.Intrinsic({ Ref: 'Other' }); // WHEN const s = { [token.toString()]: `boom ${token}` }; // THEN test.throws(() => resolve(s), 'The key "${Token[TOKEN.19]}" has been resolved to {"Ref":"Other"} but must be resolvable to a string'); test.done(); }, 'list encoding': { 'can encode Token to string and resolve the encoding'(test) { // GIVEN const token = new intrinsic_1.Intrinsic({ Ref: 'Other' }); // WHEN const struct = { XYZ: lib_1.Token.asList(token) }; // THEN test.deepEqual(resolve(struct), { XYZ: { Ref: 'Other' } }); test.done(); }, 'cannot add to encoded list'(test) { // GIVEN const token = new intrinsic_1.Intrinsic({ Ref: 'Other' }); // WHEN const encoded = lib_1.Token.asList(token); encoded.push('hello'); // THEN test.throws(() => { resolve(encoded); }, /Cannot add elements to list token/); test.done(); }, 'cannot add to strings in encoded list'(test) { // GIVEN const token = new intrinsic_1.Intrinsic({ Ref: 'Other' }); // WHEN const encoded = lib_1.Token.asList(token); encoded[0] += 'hello'; // THEN test.throws(() => { resolve(encoded); }, /concatenate strings in/); test.done(); }, 'can pass encoded lists to FnSelect'(test) { // GIVEN const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' })); // WHEN const struct = lib_1.Fn.select(1, encoded); // THEN test.deepEqual(resolve(struct), { 'Fn::Select': [1, { Ref: 'Other' }] }); test.done(); }, 'can pass encoded lists to FnJoin'(test) { // GIVEN const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' })); // WHEN const struct = lib_1.Fn.join('/', encoded); // THEN test.deepEqual(resolve(struct), { 'Fn::Join': ['/', { Ref: 'Other' }] }); test.done(); }, 'can pass encoded lists to FnJoin, even if join is stringified'(test) { // GIVEN const encoded = lib_1.Token.asList(new intrinsic_1.Intrinsic({ Ref: 'Other' })); // WHEN const struct = lib_1.Fn.join('/', encoded).toString(); // THEN test.deepEqual(resolve(struct), { 'Fn::Join': ['/', { Ref: 'Other' }] }); test.done(); }, }, 'number encoding': { 'basic integer encoding works'(test) { test.equal(16, encoding_1.extractTokenDouble(encoding_1.createTokenDouble(16))); test.done(); }, 'arbitrary integers can be encoded, stringified, and recovered'(test) { for (let i = 0; i < 100; i++) { // We can encode all numbers up to 2^48-1 const x = Math.floor(Math.random() * (Math.pow(2, 48) - 1)); const encoded = encoding_1.createTokenDouble(x); // Roundtrip through JSONification const roundtripped = JSON.parse(JSON.stringify({ theNumber: encoded })).theNumber; const decoded = encoding_1.extractTokenDouble(roundtripped); test.equal(decoded, x, `Fail roundtrip encoding of ${x}`); } test.done(); }, 'arbitrary numbers are correctly detected as not being tokens'(test) { test.equal(undefined, encoding_1.extractTokenDouble(0)); test.equal(undefined, encoding_1.extractTokenDouble(1243)); test.equal(undefined, encoding_1.extractTokenDouble(4835e+532)); test.done(); }, 'can number-encode and resolve Token objects'(test) { // GIVEN const x = new intrinsic_1.Intrinsic(123); // THEN const encoded = lib_1.Token.asNumber(x); test.equal(false, lib_1.isResolvableObject(encoded), 'encoded number does not test as token'); test.equal(true, lib_1.Token.isUnresolved(encoded), 'encoded number does not test as token'); // THEN const resolved = resolve({ value: encoded }); test.deepEqual(resolved, { value: 123 }); test.done(); }, }, 'stack trace is captured at token creation'(test) { function fn1() { function fn2() { class ExposeTrace extends intrinsic_1.Intrinsic { get creationTrace() { return this.creationStack; } } return new ExposeTrace('hello'); } return fn2(); } const token = fn1(); test.ok(token.creationTrace.find(x => x.includes('fn1'))); test.ok(token.creationTrace.find(x => x.includes('fn2'))); test.done(); }, 'newError returns an error with the creation stack trace'(test) { function fn1() { function fn2() { function fn3() { class ThrowingToken extends intrinsic_1.Intrinsic { throwError(message) { throw this.newError(message); } } return new ThrowingToken('boom'); } return fn3(); } return fn2(); } const token = fn1(); test.throws(() => token.throwError('message!'), /Token created:/); test.done(); }, 'type coercion': (() => { const tests = {}; const inputs = [ 'a string', 1234, { an_object: 1234 }, [1, 2, 3], false ]; for (const input of inputs) { // GIVEN const stringToken = lib_1.Token.asString(new intrinsic_1.Intrinsic(input)); const numberToken = lib_1.Token.asNumber(new intrinsic_1.Intrinsic(input)); const listToken = lib_1.Token.asList(new intrinsic_1.Intrinsic(input)); // THEN const expected = input; tests[`${input}<string>.toNumber()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(stringToken))), expected); test.done(); }; tests[`${input}<list>.toNumber()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(listToken))), expected); test.done(); }; tests[`${input}<number>.toNumber()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asNumber(new intrinsic_1.Intrinsic(numberToken))), expected); test.done(); }; tests[`${input}<string>.toString()`] = (test) => { test.deepEqual(resolve(new intrinsic_1.Intrinsic(stringToken).toString()), expected); test.done(); }; tests[`${input}<list>.toString()`] = (test) => { test.deepEqual(resolve(new intrinsic_1.Intrinsic(listToken).toString()), expected); test.done(); }; tests[`${input}<number>.toString()`] = (test) => { test.deepEqual(resolve(new intrinsic_1.Intrinsic(numberToken).toString()), expected); test.done(); }; tests[`${input}<string>.toList()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(stringToken))), expected); test.done(); }; tests[`${input}<list>.toList()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(listToken))), expected); test.done(); }; tests[`${input}<number>.toList()`] = (test) => { test.deepEqual(resolve(lib_1.Token.asList(new intrinsic_1.Intrinsic(numberToken))), expected); test.done(); }; } return tests; })(), 'creation stack is attached to errors emitted during resolve'(test) { function showMeInTheStackTrace() { return lib_1.Lazy.stringValue({ produce: () => { throw new Error('fooError'); } }); } const x = showMeInTheStackTrace(); let message; try { resolve(x); } catch (e) { message = e.message; } test.ok(message && message.includes('showMeInTheStackTrace')); test.done(); }, 'stringifyNumber': { 'converts number to string'(test) { test.equal(lib_1.Tokenization.stringifyNumber(100), '100'); test.done(); }, 'converts tokenized number to string'(test) { test.equal(resolve(lib_1.Tokenization.stringifyNumber({ resolve: () => 100 })), '100'); test.done(); }, 'string remains the same'(test) { test.equal(lib_1.Tokenization.stringifyNumber('123'), '123'); test.done(); }, 'Ref remains the same'(test) { const val = { Ref: 'SomeLogicalId' }; test.deepEqual(lib_1.Tokenization.stringifyNumber(val), val); test.done(); }, 'lazy Ref remains the same'(test) { const resolvedVal = { Ref: 'SomeLogicalId' }; const tokenizedVal = lib_1.Lazy.anyValue({ produce: () => resolvedVal }); const res = lib_1.Tokenization.stringifyNumber(tokenizedVal); test.notDeepEqual(res, resolvedVal); test.deepEqual(resolve(res), resolvedVal); test.done(); }, 'tokenized Ref remains the same'(test) { const resolvedVal = { Ref: 'SomeLogicalId' }; const tokenizedVal = lib_1.Token.asNumber(resolvedVal); const res = lib_1.Tokenization.stringifyNumber(tokenizedVal); test.notDeepEqual(res, resolvedVal); test.deepEqual(resolve(res), resolvedVal); test.done(); }, } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC50b2tlbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZXN0LnRva2Vucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQ0EsZ0NBQWtGO0FBQ2xGLHNEQUFnRjtBQUNoRix3REFBcUQ7QUFDckQsb0RBQW9EO0FBRXBELGlEQUE2QztBQWtvQjdDLE1BQU0sUUFBUTtJQUFkO1FBQ2tCLGtCQUFhLEdBQUcsRUFBRSxDQUFDO0lBV3JDLENBQUM7SUFUUSxPQUFPO1FBQ1osT0FBTztZQUNMLElBQUksRUFBRTtnQkFDSixVQUFVLEVBQUUsT0FBTztnQkFDbkIsVUFBVSxFQUFFLElBQUk7YUFDakI7WUFDRCxPQUFPLEVBQUUsSUFBSSxxQkFBUyxDQUFFLEVBQUUsQ0FBQztTQUM1QixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBRUQsTUFBTSxRQUFRO0lBQWQ7UUFDa0Isa0JBQWEsR0FBRyxFQUFFLENBQUM7UUFDNUIsT0FBRSxHQUFHLENBQUUsSUFBSSxRQUFRLEVBQUUsRUFBRSxJQUFJLFFBQVEsRUFBRSxDQUFFLENBQUM7SUFLakQsQ0FBQztJQUhRLE9BQU87UUFDWixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDakIsQ0FBQztDQUNGO0FBRUQsTUFBTSxZQUFZO0lBQ2hCLFlBQXFCLEdBQVc7UUFBWCxRQUFHLEdBQUgsR0FBRyxDQUFRO0lBQ2hDLENBQUM7Q0FDRjtBQUVELE1BQU0sUUFBUyxTQUFRLFlBQVk7SUFHakM7UUFDRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFITCxRQUFHLEdBQUcsT0FBTyxDQUFDO0lBSXJCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxLQUFVO0lBQ3JDLE9BQU87UUFDTCxJQUFJLHFCQUFTLENBQUMsS0FBSyxDQUFDO1FBQ3BCLFVBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7S0FDeEMsQ0FBQztB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QUksQ0FBQyxRQUFRLENBQUM7Z0JBQ2pDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxXQUFXO2FBQzNCLENBQUMsQ0FBQztZQUNILE1BQU0sR0FBRyxHQUFHLGtCQUFZLENBQUMsZUFBZSxDQUFDLFlBQW1CLENBQVEsQ0FBQztZQUNyRSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDZCxDQUFDO1FBRUQsZ0NBQWdDLENBQUMsSUFBVTtZQUN6QyxNQUFNLFdBQVcsR0FBRyxFQUFFLEdBQUcsRUFBRSxlQUFlLEVBQUUsQ0FBQztZQUM3QyxNQUFNLFlBQVksR0FBRyxXQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sR0FBRyxHQUFHLGtCQUFZLENBQUMsZUFBZSxDQUFDLFlBQVksQ0FBUSxDQUFDO1lBQzlELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQzFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNkLENBQUM7S0FDRjtDQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZXN0IH0gZnJvbSAnbm9kZXVuaXQnO1xuaW1wb3J0IHsgRm4sIGlzUmVzb2x2YWJsZU9iamVjdCwgTGF6eSwgU3RhY2ssIFRva2VuLCBUb2tlbml6YXRpb24gfSBmcm9tICcuLi9saWInO1xuaW1wb3J0IHsgY3JlYXRlVG9rZW5Eb3VibGUsIGV4dHJhY3RUb2tlbkRvdWJsZSB9IGZyb20gJy4uL2xpYi9wcml2YXRlL2VuY29kaW5nJztcbmltcG9ydCB7IEludHJpbnNpYyB9IGZyb20gJy4uL2xpYi9wcml2YXRlL2ludHJpbnNpYyc7XG5pbXBvcnQgeyBmaW5kVG9rZW5zIH0gZnJvbSAnLi4vbGliL3ByaXZhdGUvcmVzb2x2ZSc7XG5pbXBvcnQgeyBJUmVzb2x2YWJsZSB9IGZyb20gJy4uL2xpYi9yZXNvbHZhYmxlJztcbmltcG9ydCB7IGV2YWx1YXRlQ0ZOIH0gZnJvbSAnLi9ldmFsdWF0ZS1jZm4nO1xuXG5leHBvcnQgPSB7XG4gICdyZXNvbHZlIGEgcGxhaW4gb2xkIG9iamVjdCBzaG91bGQganVzdCByZXR1cm4gdGhlIG9iamVjdCcodGVzdDogVGVzdCkge1xuICAgIGNvbnN0IG9iaiA9IHsgUGxhaW5PbGRPYmplY3Q6IDEyMywgQXJyYXk6IFsgMSwgMiwgMyBdIH07XG4gICAgdGVzdC5kZWVwRXF1YWwocmVzb2x2ZShvYmopLCBvYmopO1xuICAgIHRlc3QuZG9uZSgpO1xuICB9LFxuXG4gICdpZiBhIHZhbHVlIGlzIGFuIG9iamVjdCB3aXRoIGEgdG9rZW4gdmFsdWUsIGl0IHdpbGwgYmUgZXZhbHVhdGVkJyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0ge1xuICAgICAgUmVndWxhclZhbHVlOiAnaGVsbG8nLFxuICAgICAgTGF6eVZhbHVlOiBuZXcgSW50cmluc2ljKCdXb3JsZCcpXG4gICAgfTtcblxuICAgIHRlc3QuZGVlcEVxdWFsKHJlc29sdmUob2JqKSwge1xuICAgICAgUmVndWxhclZhbHVlOiAnaGVsbG8nLFxuICAgICAgTGF6eVZhbHVlOiAnV29ybGQnXG4gICAgfSk7XG5cbiAgICB0ZXN0LmRvbmUoKTtcbiAgfSxcblxuICAndG9rZW5zIGFyZSBldmFsdWF0ZWQgYW55d2hlcmUgaW4gdGhlIG9iamVjdCB0cmVlJyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0gbmV3IFByb21pc2UxKCk7XG4gICAgY29uc3QgYWN0dWFsID0gcmVzb2x2ZSh7IE9iajogb2JqIH0pO1xuXG4gICAgdGVzdC5kZWVwRXF1YWwoYWN0dWFsLCB7XG4gICAgICBPYmo6IFtcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ3Rva2VucyBhcmUgZXZhbHVhdGVkIHJlY3Vyc2l2ZWx5Jyh0ZXN0OiBUZXN0KSB7XG4gICAgY29uc3Qgb2JqID0gbmV3IFByb21pc2UxKCk7XG4gICAgY29uc3QgYWN0dWFsID0gcmVzb2x2ZShuZXcgSW50cmluc2ljKHsgT2JqOiBvYmogfSkpO1xuXG4gICAgdGVzdC5kZWVwRXF1YWwoYWN0dWFsLCB7XG4gICAgICBPYmo6IFtcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgc3RyaW5nUHJvcDogXCJoZWxsb1wiLFxuICAgICAgICAgIG51bWJlclByb3A6IDEyMzRcbiAgICAgICAgfSxcbiAgICAgICAgUmVjdXJzZTogNDJcbiAgICAgICAgfVxuICAgICAgXVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2VtcHR5IGFycmF5cyBvciBvYmplY3RzIGFyZSBrZXB0Jyh0ZXN0OiBUZXN0KSB7XG4gICAgdGVzdC5kZWVwRXF1YWwocmVzb2x2ZSh7IH0pLCB7IH0pO1xuICAgIHRlc3QuZGVlcEVxdWFsKHJlc29sdmUoWyBdKSwgWyBdKTtcblxuICAgIGNvbnN0IG9iaiA9IHtcbiAgICAgIFByb3AxOiAxMjM0LFxuICAgICAgUHJvcDI6IHsgfSxcbiAgICAgIFByb3AzOiBbIF0sXG4gICAgICBQcm9wNDogJ2hlbGxvJyxcbiAgICAgIFByb3A1OiB7XG4gICAgICAgIFByb3BBOiB7IH0sXG4gICAgICAgIFByb3BCOiB7XG4gICAgICAgICAgUHJvcEM6IFsgdW5kZWZpbmVkLCB1bmRlZmluZWQgXSxcbiAgICAgICAgICBQcm9wRDogJ1lvb2hvbydcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB0ZXN0LmRlZXBFcXVhbChyZXNvbHZlKG9iaiksIHtcbiAgICAgIFByb3AxOiAxMjM0LFxuICAgICAgUHJvcDI6IHsgfSxcbiAgICAgIFByb3AzOiBbIF0sXG4gICAgICBQcm9wNDogJ2hlbGxvJyxcbiAgICAgIFByb3A1OiB7XG4gICAgICAgIFByb3BBOiB7IH0sXG4gICAgICAgIFByb3BCOiB7XG4gICAgICAgICAgUHJvcEM6IFsgXSxcbiAgICAgICAgICBQcm9wRDogJ1lvb2hvbydcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGVzdC5kb25lKCk7XG4gIH0sXG5cbiAgJ2lmIGFuIG9iamVjdCBoYXMgYSBcInJlc29sdmVcIiBwcm9wZXJ0eSB0aGF0IGlzIG5vdCBhIGZ1bmN