@aws-mdaa/dataops-job-l3-construct 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +38 -28
- package/README.md +5 -0
- package/lib/dataops-job-l3-construct.d.ts +8 -1
- package/lib/dataops-job-l3-construct.js +40 -13
- package/node_modules/@aws-mdaa/config/README.md +3 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.d.ts +20 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.js +70 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.ts +88 -0
- package/node_modules/@aws-mdaa/config/lib/config.d.ts +87 -0
- package/node_modules/@aws-mdaa/config/lib/config.js +7 -0
- package/node_modules/@aws-mdaa/config/lib/config.ts +92 -0
- package/node_modules/@aws-mdaa/config/lib/index.d.ts +11 -0
- package/node_modules/@aws-mdaa/config/lib/index.js +28 -0
- package/node_modules/@aws-mdaa/config/lib/index.ts +12 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.d.ts +49 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.js +160 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.ts +159 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.d.ts +10 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.js +30 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.ts +27 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.d.ts +44 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.js +243 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.ts +302 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.d.ts +8 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.js +22 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.ts +21 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.d.ts +35 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.js +66 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.ts +74 -0
- package/node_modules/@aws-mdaa/config/package.json +42 -0
- package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.js +224 -0
- package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.ts +259 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.js +129 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.ts +163 -0
- package/node_modules/@aws-mdaa/config/test/config.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/config.test.js +409 -0
- package/node_modules/@aws-mdaa/config/test/config.test.ts +517 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.js +216 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.ts +234 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.js +59 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.ts +68 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.js +254 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.ts +304 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.js +66 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.ts +79 -0
- package/node_modules/@aws-mdaa/config/tsconfig.tsbuildinfo +1 -0
- package/node_modules/lodash/README.md +2 -2
- package/node_modules/lodash/_baseOrderBy.js +1 -1
- package/node_modules/lodash/_baseUnset.js +7 -20
- package/node_modules/lodash/_setCacheHas.js +1 -1
- package/node_modules/lodash/compact.js +1 -1
- package/node_modules/lodash/core.js +3 -3
- package/node_modules/lodash/core.min.js +26 -25
- package/node_modules/lodash/fromPairs.js +3 -1
- package/node_modules/lodash/lodash.js +38 -27
- package/node_modules/lodash/lodash.min.js +125 -129
- package/node_modules/lodash/package.json +4 -2
- package/node_modules/lodash/random.js +9 -0
- package/node_modules/lodash/template.js +16 -4
- package/node_modules/lodash/templateSettings.js +4 -0
- package/package.json +27 -32
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/README.md +0 -185
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.d.ts +0 -57
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.js +0 -198
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.ts +0 -241
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/package.json +0 -44
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/test/bucketpolicy-helper.test.js +0 -200
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/test/bucketpolicy-helper.test.ts +0 -215
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/tsconfig.tsbuildinfo +0 -1
- package/node_modules/@aws-mdaa/s3-inventory-helper/.npmignore +0 -34
- package/node_modules/@aws-mdaa/s3-inventory-helper/README.md +0 -3
- package/node_modules/@aws-mdaa/s3-inventory-helper/jest.config.js +0 -5
- package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.d.ts +0 -48
- package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.js +0 -213
- package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.ts +0 -241
- package/node_modules/@aws-mdaa/s3-inventory-helper/package.json +0 -44
- package/node_modules/@aws-mdaa/s3-inventory-helper/test/TODO +0 -0
- package/node_modules/@aws-mdaa/s3-inventory-helper/tsconfig.json +0 -40
- package/node_modules/@aws-mdaa/s3-inventory-helper/tsconfig.tsbuildinfo +0 -1
- package/node_modules/@aws-mdaa/s3-inventory-helper/typedoc.json +0 -7
- /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/.npmignore +0 -0
- /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/jest.config.js +0 -0
- /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper/test/bucketpolicy-helper.test.d.ts → config/test/blueprint-value-transformer.test.d.ts} +0 -0
- /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/tsconfig.json +0 -0
- /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/typedoc.json +0 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
8
|
+
// nosemgrep
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const lib_1 = require("../lib");
|
|
11
|
+
const console = require("console");
|
|
12
|
+
const naming_1 = require("@aws-mdaa/naming");
|
|
13
|
+
class TestKeyTransformer {
|
|
14
|
+
transformValue(value, contextPath) {
|
|
15
|
+
console.log(`Transforming ${contextPath}:${value} -> "transformedValue"`);
|
|
16
|
+
return 'transformedKey';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
class TestValueTransformer {
|
|
20
|
+
transformValue(value, contextPath) {
|
|
21
|
+
console.log(`Transforming ${contextPath}:${value} -> "transformedValue"`);
|
|
22
|
+
return 'transformedValue';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
describe('Test MdaaConfigKeyTransformer', () => {
|
|
26
|
+
describe('Test transformConfigObject', () => {
|
|
27
|
+
const testConfigObj = {
|
|
28
|
+
testString: 'testing',
|
|
29
|
+
};
|
|
30
|
+
const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer(), new TestKeyTransformer()).transformConfig(testConfigObj);
|
|
31
|
+
test('String Transformation', () => {
|
|
32
|
+
expect(transformedConfig['transformedKey']).toBe('transformedValue');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('Test MdaaConfigValueTransformer', () => {
|
|
37
|
+
describe('Test transformConfigObject', () => {
|
|
38
|
+
const testConfigObj = {
|
|
39
|
+
testString: 'testing',
|
|
40
|
+
testNumber: 123,
|
|
41
|
+
testObj: {
|
|
42
|
+
testObjString: 'testing',
|
|
43
|
+
},
|
|
44
|
+
testArray: ['testing1', 'testing2'],
|
|
45
|
+
};
|
|
46
|
+
const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer()).transformConfig(testConfigObj);
|
|
47
|
+
test('String Transformation', () => {
|
|
48
|
+
expect(transformedConfig['testString']).toBe('transformedValue');
|
|
49
|
+
});
|
|
50
|
+
test('Number Transformation', () => {
|
|
51
|
+
expect(transformedConfig['testNumber']).toBe(123);
|
|
52
|
+
});
|
|
53
|
+
test('Child Object String Transformation', () => {
|
|
54
|
+
expect(transformedConfig['testObj']['testObjString']).toBe('transformedValue');
|
|
55
|
+
});
|
|
56
|
+
test('Child Array String Transformation', () => {
|
|
57
|
+
expect(transformedConfig['testArray'][0]).toBe('transformedValue');
|
|
58
|
+
expect(transformedConfig['testArray'][1]).toBe('transformedValue');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('Test transformConfigArray', () => {
|
|
62
|
+
const testArray = [
|
|
63
|
+
'testing1',
|
|
64
|
+
'testing2',
|
|
65
|
+
{
|
|
66
|
+
testingobj: 'testingobjvalue',
|
|
67
|
+
},
|
|
68
|
+
['testingchild1', 'testingchild2'],
|
|
69
|
+
123,
|
|
70
|
+
];
|
|
71
|
+
const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer()).transformConfigArray('/', testArray);
|
|
72
|
+
describe('Array String Transformation', () => {
|
|
73
|
+
test('Array String values', () => {
|
|
74
|
+
expect(transformedConfig[0]).toBe('transformedValue');
|
|
75
|
+
expect(transformedConfig[1]).toBe('transformedValue');
|
|
76
|
+
});
|
|
77
|
+
test('Array child object values', () => {
|
|
78
|
+
expect(transformedConfig[2]['testingobj']).toBe('transformedValue');
|
|
79
|
+
});
|
|
80
|
+
test('Array child array values', () => {
|
|
81
|
+
expect(transformedConfig[3][0]).toBe('transformedValue');
|
|
82
|
+
expect(transformedConfig[3][1]).toBe('transformedValue');
|
|
83
|
+
});
|
|
84
|
+
test('Array number values', () => {
|
|
85
|
+
expect(transformedConfig[4]).toBe(123);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('Test MdaaConfigRefValueTransformer', () => {
|
|
91
|
+
// Helper function that mimics CLI encoding (copied from packages/cli/lib/utils.ts)
|
|
92
|
+
// This documents the encoding contract that the decoder must handle
|
|
93
|
+
function encodeContextValue(contextValue) {
|
|
94
|
+
let encodedContextValue;
|
|
95
|
+
if (contextValue instanceof Array) {
|
|
96
|
+
encodedContextValue = `"list:${JSON.stringify(contextValue)}"`;
|
|
97
|
+
}
|
|
98
|
+
else if (contextValue instanceof Object) {
|
|
99
|
+
encodedContextValue = `"obj:${JSON.stringify(contextValue)}"`;
|
|
100
|
+
}
|
|
101
|
+
else if (typeof contextValue === 'string') {
|
|
102
|
+
encodedContextValue = contextValue;
|
|
103
|
+
}
|
|
104
|
+
else if (typeof contextValue === 'boolean') {
|
|
105
|
+
encodedContextValue = contextValue ? 'true' : 'false';
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw Error(`Don't know how to handle type ${contextValue}`);
|
|
109
|
+
}
|
|
110
|
+
return encodedContextValue;
|
|
111
|
+
}
|
|
112
|
+
const testContextObj = {
|
|
113
|
+
testingkey: 'testingobjval',
|
|
114
|
+
};
|
|
115
|
+
const testContextList = ['val1', 'val2', 'val3'];
|
|
116
|
+
const context = {
|
|
117
|
+
org: 'testorg',
|
|
118
|
+
domain: 'testdomain',
|
|
119
|
+
env: 'testenv',
|
|
120
|
+
module_name: 'testmodule',
|
|
121
|
+
test_context_obj: encodeContextValue(testContextObj),
|
|
122
|
+
test_context_name: 'test_context_value',
|
|
123
|
+
test_context_list: encodeContextValue(testContextList),
|
|
124
|
+
};
|
|
125
|
+
const testApp = new aws_cdk_lib_1.App({ context: context });
|
|
126
|
+
const testStack = new aws_cdk_lib_1.Stack(testApp, 'testStack');
|
|
127
|
+
const namingProps = {
|
|
128
|
+
cdkNode: new aws_cdk_lib_1.App().node,
|
|
129
|
+
org: 'test-org',
|
|
130
|
+
env: 'test-env',
|
|
131
|
+
domain: 'test-domain',
|
|
132
|
+
moduleName: 'test-module',
|
|
133
|
+
};
|
|
134
|
+
const naming = new naming_1.MdaaDefaultResourceNaming(namingProps);
|
|
135
|
+
const transformerProps = {
|
|
136
|
+
naming: naming,
|
|
137
|
+
org: 'testorg',
|
|
138
|
+
domain: 'testdomain',
|
|
139
|
+
env: 'testenv',
|
|
140
|
+
module_name: 'testmodule',
|
|
141
|
+
scope: testStack,
|
|
142
|
+
};
|
|
143
|
+
const serviceCatalogConfig = {
|
|
144
|
+
portfolio_arn: 'dummy-portfolio-arn',
|
|
145
|
+
portfolio_bucket_name: 'test-bucket',
|
|
146
|
+
owner: 'owner',
|
|
147
|
+
name: 'test product name',
|
|
148
|
+
launch_role_name: 'dummy-launch-role',
|
|
149
|
+
parameters: {
|
|
150
|
+
number_param: {
|
|
151
|
+
props: {
|
|
152
|
+
type: 'Number',
|
|
153
|
+
description: 'Sample number parameter',
|
|
154
|
+
default: 10,
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
string_param: {
|
|
158
|
+
props: {
|
|
159
|
+
type: 'String',
|
|
160
|
+
description: 'Sample string parameter',
|
|
161
|
+
default: 'default_string',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
list_param: {
|
|
165
|
+
props: {
|
|
166
|
+
type: 'CommaDelimitedList',
|
|
167
|
+
description: 'Sample list parameter',
|
|
168
|
+
default: 'sample,list,of,strings',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
test('Nested', () => {
|
|
174
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:ssm:/{{org}}/{{domain}}/{{env}}/{{module_name}}}}testing');
|
|
175
|
+
expect(transformedValue).toMatch(/testing\${Token\[TOKEN.\d+]}testing/);
|
|
176
|
+
});
|
|
177
|
+
test('MultiRef', () => {
|
|
178
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('multi-{{org}}-{{domain}}-{{env}}');
|
|
179
|
+
expect(transformedValue).toBe('multi-testorg-testdomain-testenv');
|
|
180
|
+
});
|
|
181
|
+
test('No Ref', () => {
|
|
182
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('noref');
|
|
183
|
+
expect(transformedValue).toBe('noref');
|
|
184
|
+
});
|
|
185
|
+
test('Env Var', () => {
|
|
186
|
+
process.env['TEST_VAR'] = 'testval';
|
|
187
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:TEST_VAR}}');
|
|
188
|
+
expect(transformedValue).toBe('testval');
|
|
189
|
+
});
|
|
190
|
+
test('MissingContext', () => {
|
|
191
|
+
expect(() => new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:missing}}')).toThrow();
|
|
192
|
+
});
|
|
193
|
+
test('Context Obj - Naked Reference', () => {
|
|
194
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:test_context_obj}}');
|
|
195
|
+
// Naked reference should return the actual object
|
|
196
|
+
expect(transformedValue).toEqual(testContextObj);
|
|
197
|
+
});
|
|
198
|
+
test('Context Obj - Embedded Reference Should Error', () => {
|
|
199
|
+
// Embedding an object in a string should throw an error
|
|
200
|
+
expect(() => {
|
|
201
|
+
new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{context:test_context_obj}}');
|
|
202
|
+
}).toThrow(/Cannot embed array or object context value in string/);
|
|
203
|
+
});
|
|
204
|
+
test('Context List - Naked Reference', () => {
|
|
205
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:test_context_list}}');
|
|
206
|
+
// Naked reference should return the actual array
|
|
207
|
+
expect(transformedValue).toEqual(testContextList);
|
|
208
|
+
});
|
|
209
|
+
test('Context List - Embedded Reference Should Error', () => {
|
|
210
|
+
// Embedding an array in a string should throw an error
|
|
211
|
+
expect(() => {
|
|
212
|
+
new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{context:test_context_list}}');
|
|
213
|
+
}).toThrow(/Cannot embed array or object context value in string/);
|
|
214
|
+
});
|
|
215
|
+
test('Resolve ssm ref', () => {
|
|
216
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:ssm:/test/param/path}}testing');
|
|
217
|
+
expect(transformedValue).toMatch(/testing\${Token\[TOKEN.\d+]}testing/);
|
|
218
|
+
});
|
|
219
|
+
test('Resolve ssm non ref', () => {
|
|
220
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:nonssm}}testing');
|
|
221
|
+
expect(transformedValue).toBe('testing{{resolve:nonssm}}testing');
|
|
222
|
+
});
|
|
223
|
+
test('Context', () => {
|
|
224
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{context:test_context_name}}testing');
|
|
225
|
+
expect(transformedValue).toBe('testingtest_context_valuetesting');
|
|
226
|
+
});
|
|
227
|
+
test('ContextOrg', () => {
|
|
228
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{context:org}}testing');
|
|
229
|
+
expect(transformedValue).toBe('testingtestorgtesting');
|
|
230
|
+
});
|
|
231
|
+
test('OrgRef', () => {
|
|
232
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{org}}');
|
|
233
|
+
expect(transformedValue).toBe('testorg');
|
|
234
|
+
});
|
|
235
|
+
const paramTransformerProps = {
|
|
236
|
+
...transformerProps,
|
|
237
|
+
paramProps: Object.fromEntries(Object.entries(serviceCatalogConfig.parameters || {}).map(([paramName, props]) => {
|
|
238
|
+
return [paramName, props.props];
|
|
239
|
+
})),
|
|
240
|
+
};
|
|
241
|
+
test('Param', () => {
|
|
242
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:paramname}}');
|
|
243
|
+
expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
|
|
244
|
+
});
|
|
245
|
+
test('ParamNotInServiceCatalogConfig', () => {
|
|
246
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:parameter_not_in_sc_config}}');
|
|
247
|
+
expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
|
|
248
|
+
});
|
|
249
|
+
test('StringParamInServiceCatalogConfig', () => {
|
|
250
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:string_param}}');
|
|
251
|
+
expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
|
|
252
|
+
});
|
|
253
|
+
test('NumberParamInServiceCatalogConfig', () => {
|
|
254
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number_param}}');
|
|
255
|
+
expect(typeof transformedValue).toBe('number');
|
|
256
|
+
});
|
|
257
|
+
test('ListParamInServiceCatalogConfig', () => {
|
|
258
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:list_param}}');
|
|
259
|
+
expect(transformedValue).toMatch(/#{Token\[TOKEN.\d+]}/);
|
|
260
|
+
});
|
|
261
|
+
test('StringParamAnnotation', () => {
|
|
262
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:string:string_param}}');
|
|
263
|
+
expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
|
|
264
|
+
});
|
|
265
|
+
test('NumberParamAnnotation', () => {
|
|
266
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number:number_param}}');
|
|
267
|
+
expect(typeof transformedValue).toBe('number');
|
|
268
|
+
});
|
|
269
|
+
test('ListParamAnnotation', () => {
|
|
270
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:list:list_param}}');
|
|
271
|
+
expect(transformedValue).toMatch(/#{Token\[TOKEN.\d+]}/);
|
|
272
|
+
});
|
|
273
|
+
test('PrefixedNumberParam', () => {
|
|
274
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('testing{{param:number:number_param}}');
|
|
275
|
+
expect(transformedValue).toMatch(/^testing-\d+(\.\d+)?(e\+\d+)?$/);
|
|
276
|
+
});
|
|
277
|
+
test('PrefixedListParam', () => {
|
|
278
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('testing{{param:list:list_param}}');
|
|
279
|
+
expect(transformedValue).toMatch(/testing#{Token\[TOKEN.\d+]}/);
|
|
280
|
+
});
|
|
281
|
+
test('NestedResolutionWithinNumberParam', () => {
|
|
282
|
+
const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number:{{org}}_param}}');
|
|
283
|
+
expect(typeof transformedValue).toBe('number');
|
|
284
|
+
});
|
|
285
|
+
test('Partition', () => {
|
|
286
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{partition}}');
|
|
287
|
+
expect(transformedValue).toMatch(/\${Token\[AWS.Partition.\d+]}/);
|
|
288
|
+
});
|
|
289
|
+
test('Region', () => {
|
|
290
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{region}}');
|
|
291
|
+
expect(transformedValue).toMatch(/\${Token\[AWS.Region.\d+]}/);
|
|
292
|
+
});
|
|
293
|
+
test('Account', () => {
|
|
294
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{account}}');
|
|
295
|
+
expect(transformedValue).toMatch(/\${Token\[AWS.AccountId.\d+]}/);
|
|
296
|
+
});
|
|
297
|
+
test('Module Name', () => {
|
|
298
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{module_name}}');
|
|
299
|
+
expect(transformedValue).toBe('testmodule');
|
|
300
|
+
});
|
|
301
|
+
// Additional test cases for better coverage
|
|
302
|
+
test('Naked SSM Reference', () => {
|
|
303
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{resolve:ssm:/test/param/path}}');
|
|
304
|
+
expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
|
|
305
|
+
});
|
|
306
|
+
test('Naked Env Var', () => {
|
|
307
|
+
process.env['NAKED_TEST_VAR'] = 'naked_testval';
|
|
308
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:NAKED_TEST_VAR}}');
|
|
309
|
+
expect(transformedValue).toBe('naked_testval');
|
|
310
|
+
});
|
|
311
|
+
test('Missing Env Var - Embedded', () => {
|
|
312
|
+
delete process.env['MISSING_VAR'];
|
|
313
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{env_var:MISSING_VAR}}-suffix');
|
|
314
|
+
// Should leave the reference as-is when env var is undefined
|
|
315
|
+
expect(transformedValue).toBe('prefix-{{env_var:MISSING_VAR}}-suffix');
|
|
316
|
+
});
|
|
317
|
+
test('Missing Env Var - Naked Reference', () => {
|
|
318
|
+
delete process.env['MISSING_VAR_NAKED'];
|
|
319
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:MISSING_VAR_NAKED}}');
|
|
320
|
+
// Should return the original string for naked reference with undefined env var
|
|
321
|
+
expect(transformedValue).toBe('{{env_var:MISSING_VAR_NAKED}}');
|
|
322
|
+
});
|
|
323
|
+
test('Nested Context Array in SSM Path Should Error', () => {
|
|
324
|
+
expect(() => {
|
|
325
|
+
new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{resolve:ssm:/{{context:test_context_list}}/path}}');
|
|
326
|
+
}).toThrow(/Cannot embed array or object context value in string/);
|
|
327
|
+
});
|
|
328
|
+
test('Nested Context Object in String Should Error', () => {
|
|
329
|
+
expect(() => {
|
|
330
|
+
new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{resolve:ssm:/{{context:test_context_obj}}/path}}');
|
|
331
|
+
}).toThrow(/Cannot embed array or object context value in string/);
|
|
332
|
+
});
|
|
333
|
+
test('Boolean Context Value', () => {
|
|
334
|
+
const contextWithBool = {
|
|
335
|
+
...context,
|
|
336
|
+
bool_value: 'true', // Encoded as string
|
|
337
|
+
};
|
|
338
|
+
const appWithBool = new aws_cdk_lib_1.App({ context: contextWithBool });
|
|
339
|
+
const stackWithBool = new aws_cdk_lib_1.Stack(appWithBool, 'testStackBool');
|
|
340
|
+
const propsWithBool = { ...transformerProps, scope: stackWithBool };
|
|
341
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithBool).transformValue('{{context:bool_value}}');
|
|
342
|
+
expect(transformedValue).toBe('true');
|
|
343
|
+
});
|
|
344
|
+
test('Nested Object Context', () => {
|
|
345
|
+
const nestedObj = {
|
|
346
|
+
outer: {
|
|
347
|
+
inner: 'value',
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
const contextWithNested = {
|
|
351
|
+
...context,
|
|
352
|
+
nested_obj: encodeContextValue(nestedObj),
|
|
353
|
+
};
|
|
354
|
+
const appWithNested = new aws_cdk_lib_1.App({ context: contextWithNested });
|
|
355
|
+
const stackWithNested = new aws_cdk_lib_1.Stack(appWithNested, 'testStackNested');
|
|
356
|
+
const propsWithNested = { ...transformerProps, scope: stackWithNested };
|
|
357
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithNested).transformValue('{{context:nested_obj}}');
|
|
358
|
+
expect(transformedValue).toEqual(nestedObj);
|
|
359
|
+
});
|
|
360
|
+
test('Array with Mixed Types Context', () => {
|
|
361
|
+
const mixedArray = ['string', 123, true, { key: 'value' }];
|
|
362
|
+
const contextWithMixed = {
|
|
363
|
+
...context,
|
|
364
|
+
mixed_array: encodeContextValue(mixedArray),
|
|
365
|
+
};
|
|
366
|
+
const appWithMixed = new aws_cdk_lib_1.App({ context: contextWithMixed });
|
|
367
|
+
const stackWithMixed = new aws_cdk_lib_1.Stack(appWithMixed, 'testStackMixed');
|
|
368
|
+
const propsWithMixed = { ...transformerProps, scope: stackWithMixed };
|
|
369
|
+
const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithMixed).transformValue('{{context:mixed_array}}');
|
|
370
|
+
expect(transformedValue).toEqual(mixedArray);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
describe('Test MdaaConfigSSMValueTransformer', () => {
|
|
374
|
+
test('Non ssm:', () => {
|
|
375
|
+
const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('testvalue', 'testPath');
|
|
376
|
+
expect(transformedValue).toBe('testvalue');
|
|
377
|
+
});
|
|
378
|
+
test('Naked ssm:', () => {
|
|
379
|
+
const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('ssm:testSSMParamPath', 'testPath');
|
|
380
|
+
expect(transformedValue).toBe('{{resolve:ssm:testSSMParamPath}}');
|
|
381
|
+
});
|
|
382
|
+
test('Ignored SSM: Action', () => {
|
|
383
|
+
const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('ssm:GetParameter', 'policyDocument/Statement/Action');
|
|
384
|
+
expect(transformedValue).toBe('ssm:GetParameter');
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
describe('Test ConfigConfigPathValueTransformer', () => {
|
|
388
|
+
test('Non relative', () => {
|
|
389
|
+
const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('testNonRelative');
|
|
390
|
+
expect(transformedValue).toBe('testNonRelative');
|
|
391
|
+
});
|
|
392
|
+
test('Relative', () => {
|
|
393
|
+
const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('./relative');
|
|
394
|
+
expect(transformedValue).toBe(path.resolve('./relative'.replace(/^\./, 'testBaseDir')));
|
|
395
|
+
});
|
|
396
|
+
test('Parent Relative', () => {
|
|
397
|
+
const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../relative-parent');
|
|
398
|
+
expect(transformedValue).toBe(path.resolve('./relative-parent'));
|
|
399
|
+
});
|
|
400
|
+
test('Parent Sub folder Relative', () => {
|
|
401
|
+
const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../app/code');
|
|
402
|
+
expect(transformedValue).toBe(path.resolve('./app/code'));
|
|
403
|
+
});
|
|
404
|
+
test('Grandparent folder Relative', () => {
|
|
405
|
+
const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../../mdaa-naming');
|
|
406
|
+
expect(transformedValue).toBe(path.resolve('../mdaa-naming'));
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb25maWcudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOztBQUVILDZDQUF5QztBQUN6QyxZQUFZO0FBQ1osNkJBQTZCO0FBQzdCLGdDQVdnQjtBQUNoQixtQ0FBbUM7QUFDbkMsNkNBQXVGO0FBRXZGLE1BQU0sa0JBQWtCO0lBQ2YsY0FBYyxDQUFDLEtBQWEsRUFBRSxXQUFnQztRQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixXQUFXLElBQUksS0FBSyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sZ0JBQWdCLENBQUM7SUFDMUIsQ0FBQztDQUNGO0FBRUQsTUFBTSxvQkFBb0I7SUFDakIsY0FBYyxDQUFDLEtBQWEsRUFBRSxXQUFnQztRQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixXQUFXLElBQUksS0FBSyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sa0JBQWtCLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBQ0QsUUFBUSxDQUFDLCtCQUErQixFQUFFLEdBQUcsRUFBRTtJQUM3QyxRQUFRLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxFQUFFO1FBQzFDLE1BQU0sYUFBYSxHQUFHO1lBQ3BCLFVBQVUsRUFBRSxTQUFTO1NBQ3RCLENBQUM7UUFDRixNQUFNLGlCQUFpQixHQUFHLElBQUksMkJBQXFCLENBQ2pELElBQUksb0JBQW9CLEVBQUUsRUFDMUIsSUFBSSxrQkFBa0IsRUFBRSxDQUN6QixDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVqQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdkUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztB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LENBQUM7SUFDMUYsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO1FBQzNCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxhQUFhLENBQUMsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNsSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxFQUFFO1FBQ3RDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxhQUFhLENBQUMsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDM0csTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7UUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2pILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHsgQXBwLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbi8vIG5vc2VtZ3JlcFxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7XG4gIE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnU1NNVmFsdWVUcmFuc2Zvcm1lcixcbiAgTWRhYUNvbmZpZ1RyYW5zZm9ybWVyLFxuICBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcixcbiAgTWRhYVNlcnZpY2VDYXRhbG9nUHJvZHVjdENvbmZpZyxcbiAgSU1kYWFDb25maWdWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzLFxuICBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyUHJvcHMsXG4gIENvbmZpZ3VyYXRpb25FbGVtZW50LFxufSBmcm9tICcuLi9saWInO1xuaW1wb3J0ICogYXMgY29uc29sZSBmcm9tICdjb25zb2xlJztcbmltcG9ydCB7IE1kYWFEZWZhdWx0UmVzb3VyY2VOYW1pbmcsIE1kYWFSZXNvdXJjZU5hbWluZ0NvbmZpZyB9IGZyb20gJ0Bhd3MtbWRhYS9uYW1pbmcnO1xuXG5jbGFzcyBUZXN0S2V5VHJhbnNmb3JtZXIgaW1wbGVtZW50cyBJTWRhYUNvbmZpZ1ZhbHVlVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgdHJhbnNmb3JtVmFsdWUodmFsdWU6IHN0cmluZywgY29udGV4dFBhdGg/OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICAgIGNvbnNvbGUubG9nKGBUcmFuc2Zvcm1pbmcgJHtjb250ZXh0UGF0aH06JHt2YWx1ZX0gLT4gXCJ0cmFuc2Zvcm1lZFZhbHVlXCJgKTtcbiAgICByZXR1cm4gJ3RyYW5zZm9ybWVkS2V5JztcbiAgfVxufVxuXG5jbGFzcyBUZXN0VmFsdWVUcmFuc2Zvcm1lciBpbXBsZW1lbnRzIElNZGFhQ29uZmlnVmFsdWVUcmFuc2Zvcm1lciB7XG4gIHB1YmxpYyB0cmFuc2Zvcm1WYWx1ZSh2YWx1ZTogc3RyaW5nLCBjb250ZXh0UGF0aD86IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgY29uc29sZS5sb2coYFRyYW5zZm9ybWluZyAke2NvbnRleHRQYXRofToke3ZhbHVlfSAtPiBcInRyYW5zZm9ybWVkVmFsdWVcImApO1xuICAgIHJldHVybiAndHJhbnNmb3JtZWRWYWx1ZSc7XG4gIH1cbn1cbmRlc2NyaWJlKCdUZXN0IE1kYWFDb25maWdLZXlUcmFuc2Zvcm1lcicsICgpID0+IHtcbiAgZGVzY3JpYmUoJ1Rlc3QgdHJhbnNmb3JtQ29uZmlnT2JqZWN0JywgKCkgPT4ge1xuICAgIGNvbnN0IHRlc3RDb25maWdPYmogPSB7XG4gICAgICB0ZXN0U3RyaW5nOiAndGVzdGluZycsXG4gICAgfTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZENvbmZpZyA9IG5ldyBNZGFhQ29uZmlnVHJhbnNmb3JtZXIoXG4gICAgICBuZXcgVGVzdFZhbHVlVHJhbnNmb3JtZXIoKSxcbiAgICAgIG5ldyBUZXN0S2V5VHJhbnNmb3JtZXIoKSxcbiAgICApLnRyYW5zZm9ybUNvbmZpZyh0ZXN0Q29uZmlnT2JqKTtcblxuICAgIHRlc3QoJ1N0cmluZyBUcmFuc2Zvcm1hdGlvbicsICgpID0+IHtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sndHJhbnNmb3JtZWRLZXknXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuZGVzY3JpYmUoJ1Rlc3QgTWRhYUNvbmZpZ1ZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdUZXN0IHRyYW5zZm9ybUNvbmZpZ09iamVjdCcsICgpID0+IHtcbiAgICBjb25zdCB0ZXN0Q29uZmlnT2JqID0ge1xuICAgICAgdGVzdFN0cmluZzogJ3Rlc3RpbmcnLFxuICAgICAgdGVzdE51bWJlcjogMTIzLFxuICAgICAgdGVzdE9iajoge1xuICAgICAgICB0ZXN0T2JqU3RyaW5nOiAndGVzdGluZycsXG4gICAgICB9LFxuICAgICAgdGVzdEFycmF5OiBbJ3Rlc3RpbmcxJywgJ3Rlc3RpbmcyJ10sXG4gICAgfTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZENvbmZpZyA9IG5ldyBNZGFhQ29uZmlnVHJhbnNmb3JtZXIobmV3IFRlc3RWYWx1ZVRyYW5zZm9ybWVyKCkpLnRyYW5zZm9ybUNvbmZpZyh0ZXN0Q29uZmlnT2JqKTtcblxuICAgIHRlc3QoJ1N0cmluZyBUcmFuc2Zvcm1hdGlvbicsICgpID0+IHtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdFN0cmluZyddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgfSk7XG4gICAgdGVzdCgnTnVtYmVyIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWyd0ZXN0TnVtYmVyJ10pLnRvQmUoMTIzKTtcbiAgICB9KTtcbiAgICB0ZXN0KCdDaGlsZCBPYmplY3QgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdE9iaiddIGFzIENvbmZpZ3VyYXRpb25FbGVtZW50KVsndGVzdE9ialN0cmluZyddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgfSk7XG4gICAgdGVzdCgnQ2hpbGQgQXJyYXkgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdEFycmF5J10gYXMgdW5rbm93bltdKVswXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdEFycmF5J10gYXMgdW5rbm93bltdKVsxXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVGVzdCB0cmFuc2Zvcm1Db25maWdBcnJheScsICgpID0+IHtcbiAgICBjb25zdCB0ZXN0QXJyYXkgPSBbXG4gICAgICAndGVzdGluZzEnLFxuICAgICAgJ3Rlc3RpbmcyJyxcbiAgICAgIHtcbiAgICAgICAgdGVzdGluZ29iajogJ3Rlc3RpbmdvYmp2YWx1ZScsXG4gICAgICB9LFxuICAgICAgWyd0ZXN0aW5nY2hpbGQxJywgJ3Rlc3RpbmdjaGlsZDInXSxcbiAgICAgIDEyMyxcbiAgICBdO1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkQ29uZmlnID0gbmV3IE1kYWFDb25maWdUcmFuc2Zvcm1lcihuZXcgVGVzdFZhbHVlVHJhbnNmb3JtZXIoKSkudHJhbnNmb3JtQ29uZmlnQXJyYXkoXG4gICAgICAnLycsXG4gICAgICB0ZXN0QXJyYXksXG4gICAgKTtcbiAgICBkZXNjcmliZSgnQXJyYXkgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgdGVzdCgnQXJyYXkgU3RyaW5nIHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWzBdKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sxXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgICAgfSk7XG4gICAgICB0ZXN0KCdBcnJheSBjaGlsZCBvYmplY3QgdmFsdWVzJywgKCkgPT4ge1xuICAgICAgICBleHBlY3QoKHRyYW5zZm9ybWVkQ29uZmlnWzJdIGFzIENvbmZpZ3VyYXRpb25FbGVtZW50KVsndGVzdGluZ29iaiddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgICB9KTtcbiAgICAgIHRlc3QoJ0FycmF5IGNoaWxkIGFycmF5IHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1szXSBhcyBDb25maWd1cmF0aW9uRWxlbWVudClbMF0pLnRvQmUoJ3RyYW5zZm9ybWVkVmFsdWUnKTtcbiAgICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1szXSBhcyBDb25maWd1cmF0aW9uRWxlbWVudClbMV0pLnRvQmUoJ3RyYW5zZm9ybWVkVmFsdWUnKTtcbiAgICAgIH0pO1xuICAgICAgdGVzdCgnQXJyYXkgbnVtYmVyIHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWzRdKS50b0JlKDEyMyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbmRlc2NyaWJlKCdUZXN0IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyJywgKCkgPT4ge1xuICAvLyBIZWxwZXIgZnVuY3Rpb24gdGhhdCBtaW1pY3MgQ0xJIGVuY29kaW5nIChjb3BpZWQgZnJvbSBwYWNrYWdlcy9jbGkvbGliL3V0aWxzLnRzKVxuICAvLyBUaGlzIGRvY3VtZW50cyB0aGUgZW5jb2RpbmcgY29udHJhY3QgdGhhdCB0aGUgZGVjb2RlciBtdXN0IGhhbmRsZVxuICBmdW5jdGlvbiBlbmNvZGVDb250ZXh0VmFsdWUoY29udGV4dFZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBsZXQgZW5jb2RlZENvbnRleHRWYWx1ZTogc3RyaW5nO1xuICAgIGlmIChjb250ZXh0VmFsdWUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgZW5jb2RlZENvbnRleHRWYWx1ZSA9IGBcImxpc3Q6JHtKU09OLnN0cmluZ2lmeShjb250ZXh0VmFsdWUpfVwiYDtcbiAgICB9IGVsc2UgaWYgKGNvbnRleHRWYWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgZW5jb2RlZENvbnRleHRWYWx1ZSA9IGBcIm9iajoke0pTT04uc3RyaW5naWZ5KGNvbnRleHRWYWx1ZSl9XCJgO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbnRleHRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kZWRDb250ZXh0VmFsdWUgPSBjb250ZXh0VmFsdWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgY29udGV4dFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgIGVuY29kZWRDb250ZXh0VmFsdWUgPSBjb250ZXh0VmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBFcnJvcihgRG9uJ3Qga25vdyBob3cgdG8gaGFuZGxlIHR5cGUgJHtjb250ZXh0VmFsdWV9YCk7XG4gICAgfVxuICAgIHJldHVybiBlbmNvZGVkQ29udGV4dFZhbHVlO1xuICB9XG5cbiAgY29uc3QgdGVzdENvbnRleHRPYmogPSB7XG4gICAgdGVzdGluZ2tleTogJ3Rlc3RpbmdvYmp2YWwnLFxuICB9O1xuICBjb25zdCB0ZXN0Q29udGV4dExpc3QgPSBbJ3ZhbDEnLCAndmFsMicsICd2YWwzJ107XG4gIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgb3JnOiAndGVzdG9yZycsXG4gICAgZG9tYWluOiAndGVzdGRvbWFpbicsXG4gICAgZW52OiAndGVzdGVudicsXG4gICAgbW9kdWxlX25hbWU6ICd0ZXN0bW9kdWxlJyxcbiAgICB0ZXN0X2NvbnRleHRfb2JqOiBlbmNvZGVDb250ZXh0VmFsdWUodGVzdENvbnRleHRPYmopLFxuICAgIHRlc3RfY29udGV4dF9uYW1lOiAndGVzdF9jb250ZXh0X3ZhbHVlJyxcbiAgICB0ZXN0X2NvbnRleHRfbGlzdDogZW5jb2RlQ29udGV4dFZhbHVlKHRlc3RDb250ZXh0TGlzdCksXG4gIH07XG4gIGNvbnN0IHRlc3RBcHAgPSBuZXcgQXBwKHsgY29udGV4dDogY29udGV4dCB9KTtcbiAgY29uc3QgdGVzdFN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICd0ZXN0U3RhY2snKTtcbiAgY29uc3QgbmFtaW5nUHJvcHM6IE1kYWFSZXNvdXJjZU5hbWluZ0NvbmZpZyA9IHtcbiAgICBjZGtOb2RlOiBuZXcgQXBwKCkubm9kZSxcbiAgICBvcmc6ICd0ZXN0LW9yZycsXG4gICAgZW52OiAndGVzdC1lbnYnLFxuICAgIGRvbWFpbjogJ3Rlc3QtZG9tYWluJyxcbiAgICBtb2R1bGVOYW1lOiAndGVzdC1tb2R1bGUnLFxuICB9O1xuXG4gIGNvbnN0IG5hbWluZyA9IG5ldyBNZGFhRGVmYXVsdFJlc291cmNlTmFtaW5nKG5hbWluZ1Byb3BzKTtcblxuICBjb25zdCB0cmFuc2Zvcm1lclByb3BzOiBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzID0ge1xuICAgIG5hbWluZzogbmFtaW5nLFxuICAgIG9yZzogJ3Rlc3RvcmcnLFxuICAgIGRvbWFpbjogJ3Rlc3Rkb21haW4nLFxuICAgIGVudjogJ3Rlc3RlbnYnLFxuICAgIG1vZHVsZV9uYW1lOiAndGVzdG1vZHVsZScsXG4gICAgc2NvcGU6IHRlc3RTdGFjayxcbiAgfTtcblxuICBjb25zdCBzZXJ2aWNlQ2F0YWxvZ0NvbmZpZzogTWRhYVNlcnZpY2VDYXRhbG9nUHJvZHVjdENvbmZpZyA9IHtcbiAgICBwb3J0Zm9saW9fYXJuOiAnZHVtbXktcG9ydGZvbGlvLWFybicsXG4gICAgcG9ydGZvbGlvX2J1Y2tldF9uYW1lOiAndGVzdC1idWNrZXQnLFxuICAgIG93bmVyOiAnb3duZXInLFxuICAgIG5hbWU6ICd0ZXN0IHByb2R1Y3QgbmFtZScsXG4gICAgbGF1bmNoX3JvbGVfbmFtZTogJ2R1bW15LWxhdW5jaC1yb2xlJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBudW1iZXJfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnTnVtYmVyJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBudW1iZXIgcGFyYW1ldGVyJyxcbiAgICAgICAgICBkZWZhdWx0OiAxMCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzdHJpbmdfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnU3RyaW5nJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBzdHJpbmcgcGFyYW1ldGVyJyxcbiAgICAgICAgICBkZWZhdWx0OiAnZGVmYXVsdF9zdHJpbmcnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGxpc3RfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnQ29tbWFEZWxpbWl0ZWRMaXN0JyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBsaXN0IHBhcmFtZXRlcicsXG4gICAgICAgICAgZGVmYXVsdDogJ3NhbXBsZSxsaXN0LG9mLHN0cmluZ3MnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuICB0ZXN0KCdOZXN0ZWQnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3tyZXNvbHZlOnNzbTove3tvcmd9fS97e2RvbWFpbn19L3t7ZW52fX0ve3ttb2R1bGVfbmFtZX19fX10ZXN0aW5nJyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC90ZXN0aW5nXFwke1Rva2VuXFxbVE9LRU4uXFxkK119dGVzdGluZy8pO1xuICB9KTtcbiAgdGVzdCgnTXVsdGlSZWYnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICdtdWx0aS17e29yZ319LXt7ZG9tYWlufX0te3tlbnZ9fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgnbXVsdGktdGVzdG9yZy10ZXN0ZG9tYWluLXRlc3RlbnYnKTtcbiAgfSk7XG4gIHRlc3QoJ05vIFJlZicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCdub3JlZicpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdub3JlZicpO1xuICB9KTtcblxuICB0ZXN0KCdFbnYgVmFyJywgKCkgPT4ge1xuICAgIHByb2Nlc3MuZW52WydURVNUX1ZBUiddID0gJ3Rlc3R2YWwnO1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7ZW52X3ZhcjpURVNUX1ZBUn19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3R2YWwnKTtcbiAgfSk7XG5cbiAgdGVzdCgnTWlzc2luZ0NvbnRleHQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3tjb250ZXh0Om1pc3Npbmd9fScpKS50b1Rocm93KCk7XG4gIH0pO1xuXG4gIHRlc3QoJ0NvbnRleHQgT2JqIC0gTmFrZWQgUmVmZXJlbmNlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3tjb250ZXh0OnRlc3RfY29udGV4dF9vYmp9fScsXG4gICAgKTtcbiAgICAvLyBOYWtlZCByZWZlcmVuY2Ugc2hvdWxkIHJldHVybiB0aGUgYWN0dWFsIG9iamVjdFxuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0VxdWFsKHRlc3RDb250ZXh0T2JqKTtcbiAgfSk7XG5cbiAgdGVzdCgnQ29udGV4dCBPYmogLSBFbWJlZGRlZCBSZWZlcmVuY2UgU2hvdWxkIEVycm9yJywgKCkgPT4ge1xuICAgIC8vIEVtYmVkZGluZyBhbiBvYmplY3QgaW4gYSBzdHJpbmcgc2hvdWxkIHRocm93IGFuIGVycm9yXG4gICAgZXhwZWN0KCgpID0+IHtcbiAgICAgIG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgncHJlZml4LXt7Y29udGV4dDp0ZXN0X2NvbnRleHRfb2JqfX0nKTtcbiAgICB9KS50b1Rocm93KC9DYW5ub3QgZW1iZWQgYXJyYXkgb3Igb2JqZWN0IGNvbnRleHQgdmFsdWUgaW4gc3RyaW5nLyk7XG4gIH0pO1xuXG4gIHRlc3QoJ0NvbnRleHQgTGlzdCAtIE5ha2VkIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfbGlzdH19JyxcbiAgICApO1xuICAgIC8vIE5ha2VkIHJlZmVyZW5jZSBzaG91bGQgcmV0dXJuIHRoZSBhY3R1YWwgYXJyYXlcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9FcXVhbCh0ZXN0Q29udGV4dExpc3QpO1xuICB9KTtcblxuICB0ZXN0KCdDb250ZXh0IExpc3QgLSBFbWJlZGRlZCBSZWZlcmVuY2UgU2hvdWxkIEVycm9yJywgKCkgPT4ge1xuICAgIC8vIEVtYmVkZGluZyBhbiBhcnJheSBpbiBhIHN0cmluZyBzaG91bGQgdGhyb3cgYW4gZXJyb3JcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCdwcmVmaXgte3tjb250ZXh0OnRlc3RfY29udGV4dF9saXN0fX0nKTtcbiAgICB9KS50b1Rocm93KC9DYW5ub3QgZW1iZWQgYXJyYXkgb3Igb2JqZWN0IGNvbnRleHQgdmFsdWUgaW4gc3RyaW5nLyk7XG4gIH0pO1xuXG4gIHRlc3QoJ1Jlc29sdmUgc3NtIHJlZicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3Rlc3Rpbmd7e3Jlc29sdmU6c3NtOi90ZXN0L3BhcmFtL3BhdGh9fXRlc3RpbmcnLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL3Rlc3RpbmdcXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX10ZXN0aW5nLyk7XG4gIH0pO1xuICB0ZXN0KCdSZXNvbHZlIHNzbSBub24gcmVmJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAndGVzdGluZ3t7cmVzb2x2ZTpub25zc219fXRlc3RpbmcnLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3Rpbmd7e3Jlc29sdmU6bm9uc3NtfX10ZXN0aW5nJyk7XG4gIH0pO1xuICB0ZXN0KCdDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAndGVzdGluZ3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfbmFtZX19dGVzdGluZycsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgndGVzdGluZ3Rlc3RfY29udGV4dF92YWx1ZXRlc3RpbmcnKTtcbiAgfSk7XG4gIHRlc3QoJ0NvbnRleHRPcmcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3tjb250ZXh0Om9yZ319dGVzdGluZycsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgndGVzdGluZ3Rlc3Rvcmd0ZXN0aW5nJyk7XG4gIH0pO1xuICB0ZXN0KCdPcmdSZWYnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3tvcmd9fScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0b3JnJyk7XG4gIH0pO1xuXG4gIGNvbnN0IHBhcmFtVHJhbnNmb3JtZXJQcm9wczogTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzID0ge1xuICAgIC4uLnRyYW5zZm9ybWVyUHJvcHMsXG4gICAgcGFyYW1Qcm9wczogT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMoc2VydmljZUNhdGFsb2dDb25maWcucGFyYW1ldGVycyB8fCB7fSkubWFwKChbcGFyYW1OYW1lLCBwcm9wc10pID0+IHtcbiAgICAgICAgcmV0dXJuIFtwYXJhbU5hbWUsIHByb3BzLnByb3BzXTtcbiAgICAgIH0pLFxuICAgICksXG4gIH07XG4gIHRlc3QoJ1BhcmFtJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcihwYXJhbVRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cGFyYW06cGFyYW1uYW1lfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL1xcJHtUb2tlblxcW1RPS0VOLlxcZCtdfS8pO1xuICB9KTtcblxuICB0ZXN0KCdQYXJhbU5vdEluU2VydmljZUNhdGFsb2dDb25maWcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpwYXJhbWV0ZXJfbm90X2luX3NjX2NvbmZpZ319JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1N0cmluZ1BhcmFtSW5TZXJ2aWNlQ2F0YWxvZ0NvbmZpZycsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOnN0cmluZ19wYXJhbX19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG5cbiAgdGVzdCgnTnVtYmVyUGFyYW1JblNlcnZpY2VDYXRhbG9nQ29uZmlnJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcihwYXJhbVRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cGFyYW06bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG4gIHRlc3QoJ0xpc3RQYXJhbUluU2VydmljZUNhdGFsb2dDb25maWcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpsaXN0X3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goLyN7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1N0cmluZ1BhcmFtQW5ub3RhdGlvbicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOnN0cmluZzpzdHJpbmdfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbVE9LRU4uXFxkK119Lyk7XG4gIH0pO1xuICB0ZXN0KCdOdW1iZXJQYXJhbUFubm90YXRpb24nLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpudW1iZXI6bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG4gIHRlc3QoJ0xpc3RQYXJhbUFubm90YXRpb24nLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpsaXN0Omxpc3RfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvI3tUb2tlblxcW1RPS0VOLlxcZCtdfS8pO1xuICB9KTtcbiAgdGVzdCgnUHJlZml4ZWROdW1iZXJQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3twYXJhbTpudW1iZXI6bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL150ZXN0aW5nLVxcZCsoXFwuXFxkKyk/KGVcXCtcXGQrKT8kLyk7XG4gIH0pO1xuICB0ZXN0KCdQcmVmaXhlZExpc3RQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3twYXJhbTpsaXN0Omxpc3RfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvdGVzdGluZyN7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ05lc3RlZFJlc29sdXRpb25XaXRoaW5OdW1iZXJQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOm51bWJlcjp7e29yZ319X3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG5cbiAgdGVzdCgnUGFydGl0aW9uJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7cGFydGl0aW9ufX0nKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbQVdTLlBhcnRpdGlvbi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1JlZ2lvbicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCd7e3JlZ2lvbn19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL1xcJHtUb2tlblxcW0FXUy5SZWdpb24uXFxkK119Lyk7XG4gIH0pO1xuXG4gIHRlc3QoJ0FjY291bnQnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3thY2NvdW50fX0nKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbQVdTLkFjY291bnRJZC5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ01vZHVsZSBOYW1lJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7bW9kdWxlX25hbWV9fScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0bW9kdWxlJyk7XG4gIH0pO1xuXG4gIC8vIEFkZGl0aW9uYWwgdGVzdCBjYXNlcyBmb3IgYmV0dGVyIGNvdmVyYWdlXG5cbiAgdGVzdCgnTmFrZWQgU1NNIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cmVzb2x2ZTpzc206L3Rlc3QvcGFyYW0vcGF0aH19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG5cbiAgdGVzdCgnTmFrZWQgRW52IFZhcicsICgpID0+IHtcbiAgICBwcm9jZXNzLmVudlsnTkFLRURfVEVTVF9WQVInXSA9ICduYWtlZF90ZXN0dmFsJztcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7ZW52X3ZhcjpOQUtFRF9URVNUX1ZBUn19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCduYWtlZF90ZXN0dmFsJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ01pc3NpbmcgRW52IFZhciAtIEVtYmVkZGVkJywgKCkgPT4ge1xuICAgIGRlbGV0ZSBwcm9jZXNzLmVudlsnTUlTU0lOR19WQVInXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3ByZWZpeC17e2Vudl92YXI6TUlTU0lOR19WQVJ9fS1zdWZmaXgnLFxuICAgICk7XG4gICAgLy8gU2hvdWxkIGxlYXZlIHRoZSByZWZlcmVuY2UgYXMtaXMgd2hlbiBlbnYgdmFyIGlzIHVuZGVmaW5lZFxuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdwcmVmaXgte3tlbnZfdmFyOk1JU1NJTkdfVkFSfX0tc3VmZml4Jyk7XG4gIH0pO1xuXG4gIHRlc3QoJ01pc3NpbmcgRW52IFZhciAtIE5ha2VkIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnZbJ01JU1NJTkdfVkFSX05BS0VEJ107XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e2Vudl92YXI6TUlTU0lOR19WQVJfTkFLRUR9fScsXG4gICAgKTtcbiAgICAvLyBTaG91bGQgcmV0dXJuIHRoZSBvcmlnaW5hbCBzdHJpbmcgZm9yIG5ha2VkIHJlZmVyZW5jZSB3aXRoIHVuZGVmaW5lZCBlbnYgdmFyXG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3t7ZW52X3ZhcjpNSVNTSU5HX1ZBUl9OQUtFRH19Jyk7XG4gIH0pO1xuXG4gIHRlc3QoJ05lc3RlZCBDb250ZXh0IEFycmF5IGluIFNTTSBQYXRoIFNob3VsZCBFcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgICAne3tyZXNvbHZlOnNzbTove3tjb250ZXh0OnRlc3RfY29udGV4dF9saXN0fX0vcGF0aH19JyxcbiAgICAgICk7XG4gICAgfSkudG9UaHJvdygvQ2Fubm90IGVtYmVkIGFycmF5IG9yIG9iamVjdCBjb250ZXh0IHZhbHVlIGluIHN0cmluZy8pO1xuICB9KTtcblxuICB0ZXN0KCdOZXN0ZWQgQ29udGV4dCBPYmplY3QgaW4gU3RyaW5nIFNob3VsZCBFcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgICAncHJlZml4LXt7cmVzb2x2ZTpzc206L3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfb2JqfX0vcGF0aH19JyxcbiAgICAgICk7XG4gICAgfSkudG9UaHJvdygvQ2Fubm90IGVtYmVkIGFycmF5IG9yIG9iamVjdCBjb250ZXh0IHZhbHVlIGluIHN0cmluZy8pO1xuICB9KTtcblxuICB0ZXN0KCdCb29sZWFuIENvbnRleHQgVmFsdWUnLCAoKSA9PiB7XG4gICAgY29uc3QgY29udGV4dFdpdGhCb29sID0ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIGJvb2xfdmFsdWU6ICd0cnVlJywgLy8gRW5jb2RlZCBhcyBzdHJpbmdcbiAgICB9O1xuICAgIGNvbnN0IGFwcFdpdGhCb29sID0gbmV3IEFwcCh7IGNvbnRleHQ6IGNvbnRleHRXaXRoQm9vbCB9KTtcbiAgICBjb25zdCBzdGFja1dpdGhCb29sID0gbmV3IFN0YWNrKGFwcFdpdGhCb29sLCAndGVzdFN0YWNrQm9vbCcpO1xuICAgIGNvbnN0IHByb3BzV2l0aEJvb2wgPSB7IC4uLnRyYW5zZm9ybWVyUHJvcHMsIHNjb3BlOiBzdGFja1dpdGhCb29sIH07XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHByb3BzV2l0aEJvb2wpLnRyYW5zZm9ybVZhbHVlKCd7e2NvbnRleHQ6Ym9vbF92YWx1ZX19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3RydWUnKTtcbiAgfSk7XG5cbiAgdGVzdCgnTmVzdGVkIE9iamVjdCBDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IG5lc3RlZE9iaiA9IHtcbiAgICAgIG91dGVyOiB7XG4gICAgICAgIGlubmVyOiAndmFsdWUnLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGNvbnRleHRXaXRoTmVzdGVkID0ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIG5lc3RlZF9vYmo6IGVuY29kZUNvbnRleHRWYWx1ZShuZXN0ZWRPYmopLFxuICAgIH07XG4gICAgY29uc3QgYXBwV2l0aE5lc3RlZCA9IG5ldyBBcHAoeyBjb250ZXh0OiBjb250ZXh0V2l0aE5lc3RlZCB9KTtcbiAgICBjb25zdCBzdGFja1dpdGhOZXN0ZWQgPSBuZXcgU3RhY2soYXBwV2l0aE5lc3RlZCwgJ3Rlc3RTdGFja05lc3RlZCcpO1xuICAgIGNvbnN0IHByb3BzV2l0aE5lc3RlZCA9IHsgLi4udHJhbnNmb3JtZXJQcm9wcywgc2NvcGU6IHN0YWNrV2l0aE5lc3RlZCB9O1xuXG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcihwcm9wc1dpdGhOZXN0ZWQpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7Y29udGV4dDpuZXN0ZWRfb2JqfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvRXF1YWwobmVzdGVkT2JqKTtcbiAgfSk7XG5cbiAgdGVzdCgnQXJyYXkgd2l0aCBNaXhlZCBUeXBlcyBDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IG1peGVkQXJyYXkgPSBbJ3N0cmluZycsIDEyMywgdHJ1ZSwgeyBrZXk6ICd2YWx1ZScgfV07XG4gICAgY29uc3QgY29udGV4dFdpdGhNaXhlZCA9IHtcbiAgICAgIC4uLmNvbnRleHQsXG4gICAgICBtaXhlZF9hcnJheTogZW5jb2RlQ29udGV4dFZhbHVlKG1peGVkQXJyYXkpLFxuICAgIH07XG4gICAgY29uc3QgYXBwV2l0aE1peGVkID0gbmV3IEFwcCh7IGNvbnRleHQ6IGNvbnRleHRXaXRoTWl4ZWQgfSk7XG4gICAgY29uc3Qgc3RhY2tXaXRoTWl4ZWQgPSBuZXcgU3RhY2soYXBwV2l0aE1peGVkLCAndGVzdFN0YWNrTWl4ZWQnKTtcbiAgICBjb25zdCBwcm9wc1dpdGhNaXhlZCA9IHsgLi4udHJhbnNmb3JtZXJQcm9wcywgc2NvcGU6IHN0YWNrV2l0aE1peGVkIH07XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHByb3BzV2l0aE1peGVkKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e2NvbnRleHQ6bWl4ZWRfYXJyYXl9fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9FcXVhbChtaXhlZEFycmF5KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ1Rlc3QgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIHRlc3QoJ05vbiBzc206JywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXIoKS50cmFuc2Zvcm1WYWx1ZSgndGVzdHZhbHVlJywgJ3Rlc3RQYXRoJyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3R2YWx1ZScpO1xuICB9KTtcbiAgdGVzdCgnTmFrZWQgc3NtOicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdTU01WYWx1ZVRyYW5zZm9ybWVyKCkudHJhbnNmb3JtVmFsdWUoJ3NzbTp0ZXN0U1NNUGFyYW1QYXRoJywgJ3Rlc3RQYXRoJyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3t7cmVzb2x2ZTpzc206dGVzdFNTTVBhcmFtUGF0aH19Jyk7XG4gIH0pO1xuICB0ZXN0KCdJZ25vcmVkIFNTTTogQWN0aW9uJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXIoKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICdzc206R2V0UGFyYW1ldGVyJyxcbiAgICAgICdwb2xpY3lEb2N1bWVudC9TdGF0ZW1lbnQvQWN0aW9uJyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdzc206R2V0UGFyYW1ldGVyJyk7XG4gIH0pO1xufSk7XG5kZXNjcmliZSgnVGVzdCBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcicsICgpID0+IHtcbiAgdGVzdCgnTm9uIHJlbGF0aXZlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoJ3Rlc3RCYXNlRGlyJykudHJhbnNmb3JtVmFsdWUoJ3Rlc3ROb25SZWxhdGl2ZScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0Tm9uUmVsYXRpdmUnKTtcbiAgfSk7XG4gIHRlc3QoJ1JlbGF0aXZlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoJ3Rlc3RCYXNlRGlyJykudHJhbnNmb3JtVmFsdWUoJy4vcmVsYXRpdmUnKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZShwYXRoLnJlc29sdmUoJy4vcmVsYXRpdmUnLnJlcGxhY2UoL15cXC4vLCAndGVzdEJhc2VEaXInKSkpO1xuICB9KTtcblxuICB0ZXN0KCdQYXJlbnQgUmVsYXRpdmUnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcigndGVzdEJhc2VEaXInKS50cmFuc2Zvcm1WYWx1ZSgnLi4vcmVsYXRpdmUtcGFyZW50Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUocGF0aC5yZXNvbHZlKCcuL3JlbGF0aXZlLXBhcmVudCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnUGFyZW50IFN1YiBmb2xkZXIgUmVsYXRpdmUnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcigndGVzdEJhc2VEaXInKS50cmFuc2Zvcm1WYWx1ZSgnLi4vYXBwL2NvZGUnKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZShwYXRoLnJlc29sdmUoJy4vYXBwL2NvZGUnKSk7XG4gIH0pO1xuXG4gIHRlc3QoJ0dyYW5kcGFyZW50IGZvbGRlciBSZWxhdGl2ZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IENvbmZpZ0NvbmZpZ1BhdGhWYWx1ZVRyYW5zZm9ybWVyKCd0ZXN0QmFzZURpcicpLnRyYW5zZm9ybVZhbHVlKCcuLi8uLi9tZGFhLW5hbWluZycpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKHBhdGgucmVzb2x2ZSgnLi4vbWRhYS1uYW1pbmcnKSk7XG4gIH0pO1xufSk7XG4iXX0=
|