@cdktn/hcl2cdk 0.22.0-pre.2

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.
Files changed (61) hide show
  1. package/README.md +95 -0
  2. package/ambient.d.ts +14 -0
  3. package/jest.config.js +16 -0
  4. package/lib/__tests__/coerceType.test.d.ts +2 -0
  5. package/lib/__tests__/coerceType.test.js +165 -0
  6. package/lib/__tests__/expressionToTs.test.d.ts +6 -0
  7. package/lib/__tests__/expressionToTs.test.js +693 -0
  8. package/lib/__tests__/expressions.test.d.ts +4 -0
  9. package/lib/__tests__/expressions.test.js +415 -0
  10. package/lib/__tests__/findExpressionType.test.d.ts +6 -0
  11. package/lib/__tests__/findExpressionType.test.js +105 -0
  12. package/lib/__tests__/functions.test.d.ts +6 -0
  13. package/lib/__tests__/functions.test.js +605 -0
  14. package/lib/__tests__/generation.test.d.ts +6 -0
  15. package/lib/__tests__/generation.test.js +45 -0
  16. package/lib/__tests__/jsii-rosetta-workarounds.test.d.ts +2 -0
  17. package/lib/__tests__/jsii-rosetta-workarounds.test.js +86 -0
  18. package/lib/__tests__/partialCode.test.d.ts +6 -0
  19. package/lib/__tests__/partialCode.test.js +390 -0
  20. package/lib/__tests__/terraformSchema.test.d.ts +6 -0
  21. package/lib/__tests__/terraformSchema.test.js +105 -0
  22. package/lib/__tests__/testHelpers.d.ts +7 -0
  23. package/lib/__tests__/testHelpers.js +16 -0
  24. package/lib/coerceType.d.ts +7 -0
  25. package/lib/coerceType.js +240 -0
  26. package/lib/dynamic-blocks.d.ts +8 -0
  27. package/lib/dynamic-blocks.js +44 -0
  28. package/lib/expressions.d.ts +9 -0
  29. package/lib/expressions.js +634 -0
  30. package/lib/function-bindings/functions.d.ts +31 -0
  31. package/lib/function-bindings/functions.generated.d.ts +806 -0
  32. package/lib/function-bindings/functions.generated.js +1142 -0
  33. package/lib/function-bindings/functions.js +73 -0
  34. package/lib/generation.d.ts +26 -0
  35. package/lib/generation.js +676 -0
  36. package/lib/index.d.ts +136 -0
  37. package/lib/index.js +364 -0
  38. package/lib/iteration.d.ts +23 -0
  39. package/lib/iteration.js +87 -0
  40. package/lib/jsii-rosetta-workarounds.d.ts +5 -0
  41. package/lib/jsii-rosetta-workarounds.js +126 -0
  42. package/lib/partialCode.d.ts +11 -0
  43. package/lib/partialCode.js +116 -0
  44. package/lib/provider.d.ts +8 -0
  45. package/lib/provider.js +40 -0
  46. package/lib/references.d.ts +11 -0
  47. package/lib/references.js +141 -0
  48. package/lib/schema.d.ts +297 -0
  49. package/lib/schema.js +81 -0
  50. package/lib/telemetryAllowList.json +24 -0
  51. package/lib/terraformSchema.d.ts +6 -0
  52. package/lib/terraformSchema.js +136 -0
  53. package/lib/types.d.ts +50 -0
  54. package/lib/types.js +3 -0
  55. package/lib/utils.d.ts +6 -0
  56. package/lib/utils.js +25 -0
  57. package/lib/variables.d.ts +10 -0
  58. package/lib/variables.js +172 -0
  59. package/package.json +71 -0
  60. package/package.sh +9 -0
  61. package/tsconfig.json +42 -0
@@ -0,0 +1,693 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) HashiCorp, Inc.
4
+ * SPDX-License-Identifier: MPL-2.0
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const expressions_1 = require("../expressions");
8
+ const testHelpers_1 = require("./testHelpers");
9
+ const awsProviderSchema = {
10
+ format_version: "1.0",
11
+ provider_schemas: {
12
+ "registry.terraform.io/hashicorp/aws": {
13
+ provider: {},
14
+ resource_schemas: {
15
+ aws_s3_bucket: {
16
+ block: {
17
+ attributes: {
18
+ foo: {
19
+ type: ["map", "string"],
20
+ description_kind: "plain",
21
+ },
22
+ },
23
+ },
24
+ },
25
+ },
26
+ data_source_schemas: {
27
+ aws_availability_zones: {
28
+ version: 0,
29
+ block: {
30
+ attributes: {
31
+ all_availability_zones: {
32
+ type: "bool",
33
+ description_kind: "plain",
34
+ optional: true,
35
+ },
36
+ exclude_names: {
37
+ type: ["set", "string"],
38
+ description_kind: "plain",
39
+ optional: true,
40
+ },
41
+ exclude_zone_ids: {
42
+ type: ["set", "string"],
43
+ description_kind: "plain",
44
+ optional: true,
45
+ },
46
+ group_names: {
47
+ type: ["set", "string"],
48
+ description_kind: "plain",
49
+ computed: true,
50
+ },
51
+ id: {
52
+ type: "string",
53
+ description_kind: "plain",
54
+ optional: true,
55
+ computed: true,
56
+ },
57
+ names: {
58
+ type: ["list", "string"],
59
+ description_kind: "plain",
60
+ computed: true,
61
+ },
62
+ state: {
63
+ type: "string",
64
+ description_kind: "plain",
65
+ optional: true,
66
+ },
67
+ zone_ids: {
68
+ type: ["list", "string"],
69
+ description_kind: "plain",
70
+ computed: true,
71
+ },
72
+ testing_map: {
73
+ type: ["map", "string"],
74
+ description_kind: "plain",
75
+ computed: true,
76
+ },
77
+ },
78
+ block_types: {
79
+ filter: {
80
+ nesting_mode: "set",
81
+ block: {
82
+ attributes: {
83
+ name: {
84
+ type: "string",
85
+ description_kind: "plain",
86
+ required: true,
87
+ },
88
+ values: {
89
+ type: ["set", "string"],
90
+ description_kind: "plain",
91
+ required: true,
92
+ },
93
+ },
94
+ description_kind: "plain",
95
+ },
96
+ },
97
+ timeouts: {
98
+ nesting_mode: "single",
99
+ block: {
100
+ attributes: {
101
+ read: {
102
+ type: "string",
103
+ description_kind: "plain",
104
+ optional: true,
105
+ },
106
+ },
107
+ description_kind: "plain",
108
+ },
109
+ },
110
+ },
111
+ description_kind: "plain",
112
+ },
113
+ },
114
+ },
115
+ },
116
+ },
117
+ };
118
+ const externalProviderSchema = {
119
+ format_version: "1.0",
120
+ provider_schemas: {
121
+ "registry.terraform.io/hashicorp/external": {
122
+ provider: {},
123
+ resource_schemas: {},
124
+ data_source_schemas: {
125
+ external: {
126
+ version: 0,
127
+ block: {
128
+ attributes: {
129
+ id: {
130
+ type: "string",
131
+ description: "The id of the data source. This will always be set to `-`",
132
+ description_kind: "plain",
133
+ computed: true,
134
+ },
135
+ program: {
136
+ type: ["list", "string"],
137
+ description: "A list of strings, whose first element is the program to run and whose subsequent elements are optional command line arguments to the program. Terraform does not execute the program through a shell, so it is not necessary to escape shell metacharacters nor add quotes around arguments containing spaces.",
138
+ description_kind: "plain",
139
+ required: true,
140
+ },
141
+ query: {
142
+ type: ["map", "string"],
143
+ description: "A map of string values to pass to the external program as the query arguments. If not supplied, the program will receive an empty object as its input.",
144
+ description_kind: "plain",
145
+ optional: true,
146
+ },
147
+ result: {
148
+ type: ["map", "string"],
149
+ description: "A map of string values returned from the external program.",
150
+ description_kind: "plain",
151
+ computed: true,
152
+ },
153
+ working_dir: {
154
+ type: "string",
155
+ description: "Working directory of the program. If not supplied, the program will run in the current directory.",
156
+ description_kind: "plain",
157
+ optional: true,
158
+ },
159
+ },
160
+ description: 'The `external` data source allows an external program implementing a specific protocol (defined below) to act as a data source, exposing arbitrary data for use elsewhere in the Terraform configuration.\n\n**Warning** This mechanism is provided as an "escape hatch" for exceptional situations where a first-class Terraform provider is not more appropriate. Its capabilities are limited in comparison to a true data source, and implementing a data source via an external program is likely to hurt the portability of your Terraform configuration by creating dependencies on external programs and libraries that may not be available (or may need to be used differently) on different operating systems.\n\n**Warning** Terraform Enterprise does not guarantee availability of any particular language runtimes or external programs beyond standard shell utilities, so it is not recommended to use this data source within configurations that are applied within Terraform Enterprise.',
161
+ description_kind: "plain",
162
+ },
163
+ },
164
+ },
165
+ },
166
+ },
167
+ };
168
+ function getScope({ provider, resources, data, variables, locals, forEachIteratorName, scopedVariables, withinOverrideExpression = false, } = {}) {
169
+ const scopeVariables = {};
170
+ resources === null || resources === void 0 ? void 0 : resources.forEach((varName) => {
171
+ let [resourceType, resourceName] = varName.split(".");
172
+ if (!resourceName) {
173
+ resourceName = varName;
174
+ resourceType = "aws_s3_bucket";
175
+ }
176
+ scopeVariables[varName] = {
177
+ resource: resourceType,
178
+ variableName: resourceName,
179
+ };
180
+ });
181
+ data === null || data === void 0 ? void 0 : data.forEach((varName) => {
182
+ scopeVariables[varName] = {
183
+ resource: "data.aws_s3_bucket",
184
+ variableName: varName,
185
+ };
186
+ });
187
+ variables === null || variables === void 0 ? void 0 : variables.forEach((varName) => {
188
+ scopeVariables[varName] = {
189
+ resource: "var",
190
+ variableName: varName,
191
+ };
192
+ });
193
+ locals === null || locals === void 0 ? void 0 : locals.forEach((varName) => {
194
+ scopeVariables[varName] = {
195
+ resource: "local",
196
+ variableName: varName,
197
+ };
198
+ });
199
+ const scope = {
200
+ providerSchema: provider !== null && provider !== void 0 ? provider : {},
201
+ providerGenerator: {},
202
+ constructs: new Set(),
203
+ variables: scopeVariables,
204
+ hasTokenBasedTypeCoercion: true,
205
+ scopedVariables: scopedVariables || {},
206
+ forEachIteratorName,
207
+ withinOverrideExpression,
208
+ nodeIds: [],
209
+ importables: [],
210
+ topLevelConfig: {},
211
+ };
212
+ return scope;
213
+ }
214
+ const getType = () => "string";
215
+ describe("expressionToTs", () => {
216
+ test("converts a simple string to a string", async () => {
217
+ const expression = "hello";
218
+ const scope = getScope();
219
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
220
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello""`);
221
+ });
222
+ test("converts a simple expression with a template", async () => {
223
+ const expression = "${22}";
224
+ const scope = getScope();
225
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
226
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(22)"`);
227
+ });
228
+ test("converts a variable reference", async () => {
229
+ const expression = "${var.foo}";
230
+ const scope = getScope();
231
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
232
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"foo.stringValue"`);
233
+ });
234
+ test("convert a variable reference with snake case", async () => {
235
+ const expression = "${var.foo_bar}";
236
+ const scope = getScope({ variables: ["foo_bar"] });
237
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
238
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(fooBar.value)"`);
239
+ });
240
+ test("convert a function call", async () => {
241
+ const expression = `\${replace("hello", "l", "w")}`;
242
+ const scope = getScope();
243
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
244
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.replace("hello", "l", "w"))"`);
245
+ });
246
+ test("converts a function call with an expression", async () => {
247
+ const expression = `\${replace("hello-\${22+22}", "44", "world")}`;
248
+ const scope = getScope();
249
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
250
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.replace("hello-" + Token.asString(Op.add(22, 22)), "44", "world"))"`);
251
+ });
252
+ test("converts string concatenation of iterator key", async () => {
253
+ const expression = '${"dynamic-ingress-${ingress.key}"}';
254
+ const scope = getScope({
255
+ scopedVariables: {
256
+ ingress: "dynamic_iterator0",
257
+ },
258
+ });
259
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
260
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""dynamic-ingress-\${" + Token.asString(dynamic_iterator0.key) + "}""`);
261
+ });
262
+ test("convert a variable reference", async () => {
263
+ const expression = `\${var.foo_bar}`;
264
+ const scope = getScope({ variables: ["foo_bar"] });
265
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
266
+ // TODO: This seems broken
267
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(fooBar.value)"`);
268
+ });
269
+ test("convert a resource reference", async () => {
270
+ const expression = `"simple-\${aws_s3_bucket.foo.id}"`;
271
+ const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
272
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
273
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo.id + "}""`);
274
+ });
275
+ test("convert a resource reference with nested properties", async () => {
276
+ const expression = `"simple-\${aws_s3_bucket.foo.prop.test}"`;
277
+ const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
278
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
279
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo.prop.test + "}""`);
280
+ });
281
+ test("convert a local reference", async () => {
282
+ const expression = `"simple-\${local.foo}"`;
283
+ const scope = getScope({ locals: ["foo"] });
284
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
285
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""simple-\${" + foo + "}""`);
286
+ });
287
+ test("plain resource references in arithmetics", async () => {
288
+ const expression = "${aws_s3_bucket.examplebucket.count + aws_s3_bucket.otherbucket.count }";
289
+ const scope = getScope({
290
+ resources: ["aws_s3_bucket.examplebucket", "aws_s3_bucket.otherbucket"],
291
+ });
292
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
293
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.add(examplebucket.count, otherbucket.count))"`);
294
+ });
295
+ test("use fqn for splat reference", async () => {
296
+ const expression = `\${aws_s3_bucket.foo.*.id}`;
297
+ const scope = getScope({ resources: ["aws_s3_bucket.foo"] });
298
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
299
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(foo, ["*", "id"]))"`);
300
+ });
301
+ test("use fqn if property is present on numeric access using dot notation", async () => {
302
+ const expression = "${aws_s3_bucket.examplebucket.network_interface.0.access_config.0.assigned_nat_ip}";
303
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
304
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
305
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
306
+ });
307
+ test("use fqn if property is present on numeric access", async () => {
308
+ const expression = "${aws_s3_bucket.examplebucket.network_interface[0].access_config[0].assigned_nat_ip}";
309
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
310
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
311
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
312
+ });
313
+ test("use no fqn if property is present on numeric access using []", async () => {
314
+ const expression = "${aws_s3_bucket.examplebucket.network_interface[0].access_config[0].assigned_nat_ip}";
315
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
316
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
317
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket.networkInterface, ["0", "access_config", "0", "assigned_nat_ip"]))"`);
318
+ });
319
+ test("detects splat reference within function", async () => {
320
+ const expression = "${toset(aws_s3_bucket.examplebucket.*)}";
321
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
322
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
323
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.toset(Fn.lookupNested(examplebucket, ["*"])))"`);
324
+ });
325
+ test("convert conditional", async () => {
326
+ const expression = "${aws_kms_key.key.deletion_window_in_days > 3 ? aws_s3_bucket.examplebucket.id : []}";
327
+ const scope = getScope({ resources: ["aws_kms_key.key", "examplebucket"] });
328
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
329
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(conditional(Op.gt(key.deletionWindowInDays, 3), examplebucket.id, []))"`);
330
+ });
331
+ test("converts a function with references", async () => {
332
+ const expression = "${element(aws_s3_bucket.examplebucket, 0).id}";
333
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
334
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
335
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(Fn.element(examplebucket, 0), ["id"]))"`);
336
+ });
337
+ test("converts a function with splat reference", async () => {
338
+ const expression = "${element(aws_s3_bucket.examplebucket.*.id, 0)}";
339
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
340
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
341
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.element(Fn.lookupNested(examplebucket, ["*", "id"]), 0))"`);
342
+ });
343
+ test("convert for loops", async () => {
344
+ const expression = "${{ for name, user in var.users : user.role => name...}}";
345
+ const scope = getScope();
346
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
347
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for name, user in \${" + users.value + "} : user.role => name...}}""`);
348
+ });
349
+ test("for expressions", async () => {
350
+ const expression = "{for s in var.list : s => upper(s)}";
351
+ const scope = getScope();
352
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
353
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for s in \${" + list.value + "} : s => upper(s)}}""`);
354
+ });
355
+ test("for list expression ", async () => {
356
+ const expression = "[for s in var.list : upper(s)]";
357
+ const scope = getScope();
358
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
359
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for s in \${" + list.value + "} : upper(s)]}""`);
360
+ });
361
+ test("for list with conditional", async () => {
362
+ const expression = '[for s in var.list : upper(s) if s != ""]';
363
+ const scope = getScope();
364
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
365
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for s in \${" + list.value + "} : upper(s) if s != \\"\\"]}""`);
366
+ });
367
+ test("convert property access resources", async () => {
368
+ const expression = "${aws_s3_bucket.examplebucket[0].id}";
369
+ const scope = getScope({ resources: ["aws_s3_bucket.examplebucket"] });
370
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
371
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket, ["0", "id"]))"`);
372
+ });
373
+ test("convert unary operators", async () => {
374
+ const expression = `\${!var.enabled}`;
375
+ const scope = getScope({ variables: ["enabled"] });
376
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "bool");
377
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asBoolean(Op.not(enabled.value))"`);
378
+ });
379
+ test("convert function with arrays and comments", async () => {
380
+ const expression = `\${compact([
381
+ # The example "bucket"
382
+ aws_s3_bucket.examplebucket,
383
+
384
+ # The "Learn" single page application. This is not configured in all environments.
385
+ var.input,
386
+ ])}`;
387
+ const scope = getScope({
388
+ resources: ["aws_s3_bucket.examplebucket"],
389
+ variables: ["input"],
390
+ });
391
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
392
+ // TODO: See if we have a way to preserve comments
393
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.compact(Token.asList([examplebucket, input.value])))"`);
394
+ });
395
+ test("convert references for same reference", async () => {
396
+ const expression = `\${var.input == "test" ? "azure-ad-int" : "azure-ad-\${var.input}"}`;
397
+ const scope = getScope({ variables: ["input"] });
398
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
399
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(conditional(Op.eq(input.value, "test"), "azure-ad-int", "azure-ad-\${" + input.value + "}"))"`);
400
+ });
401
+ test("nested variable access", async () => {
402
+ const expression = `\${element(var.test2["val1"], 0)}`;
403
+ const scope = getScope({ variables: ["test2"] });
404
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
405
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.element(Fn.lookupNested(test2.value, ["\\"val1\\""]), 0))"`);
406
+ });
407
+ test("complicated nested local value", async () => {
408
+ const expression = "${flatten(var.vnets[*].subnets[*].name)}";
409
+ const scope = getScope({ variables: ["vnets"] });
410
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
411
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.flatten(Fn.lookupNested(vnets.value, ["*", "subnets", "*", "name"])))"`);
412
+ });
413
+ // TOIMPROVE: I don't think we can handle this case yet, since the variable
414
+ // needs to be wrapped in an iterator. I'm leaving this in, but it's broken
415
+ test("complicated nested variable access with map", async () => {
416
+ const expression = `{
417
+ for vnet in var.vnets[*]:
418
+ (vnet.vnet_name) => vnet.subnets[*].name
419
+ }`;
420
+ const scope = getScope({ variables: ["vnets"] });
421
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
422
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${{ for vnet in \${" + Fn.lookupNested(vnets.value, ["*"]) + "} : (vnet.vnet_name) => vnet.subnets[*].name}}""`);
423
+ });
424
+ test("complicated nested variable access with list", async () => {
425
+ const expression = `\${flatten([
426
+ for k, v in var.route : [
427
+ for n, s in v : [
428
+ {
429
+ key = k,
430
+ name = n,
431
+ svc_url = s
432
+ }
433
+ ]
434
+ ]
435
+ ])}`;
436
+ const scope = getScope({ variables: ["route"] });
437
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
438
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.flatten("\${[ for k, v in \${" + route.value + "} : [\\n for n, s in v : [\\n {\\n key = k,\\n name = n,\\n svc_url = s\\n }\\n ]\\n ]]}"))"`);
439
+ });
440
+ test("simple local variable access", async () => {
441
+ const expression = "${!local.enabled}";
442
+ const scope = getScope({ locals: ["enabled"] });
443
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
444
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.not(enabled))"`);
445
+ });
446
+ test("multi local access", async () => {
447
+ const expression = '"${local.service_name},${local.owner},${local.is_it_great},${local.how_many}"';
448
+ const scope = getScope({
449
+ locals: ["service_name", "owner", "is_it_great", "how_many"],
450
+ });
451
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
452
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${" + serviceName + "},\${" + owner + "},\${" + isItGreat + "},\${" + howMany + "}""`);
453
+ });
454
+ test("binary operations within literals and variables", async () => {
455
+ const expression = '"${var.test} + 1"';
456
+ const scope = getScope({ variables: ["test"] });
457
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
458
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${" + test.value + "} + 1""`);
459
+ });
460
+ test("local variable access", async () => {
461
+ const expression = '"${local.enabled}"';
462
+ const scope = getScope({ locals: ["enabled"] });
463
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
464
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"enabled"`);
465
+ });
466
+ test("converts traversals that cannot be references", async () => {
467
+ const expression = "${self.path}";
468
+ const scope = getScope();
469
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
470
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(TerraformSelf.getAny("path"))"`);
471
+ });
472
+ test("converts join function with variables", async () => {
473
+ const expression = '${join("-", [var.tags.app, var.tags.env])}';
474
+ const scope = getScope({ variables: ["tags"] });
475
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
476
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.join("-", Token.asList([Fn.lookupNested(tags.value, ["app"]), Fn.lookupNested(tags.value, ["env"])])))"`);
477
+ });
478
+ test("converts join function with many arguments variables", async () => {
479
+ const expression = '${join("-", var.tags.app, var.tags.env, var.tags.other)}';
480
+ const scope = getScope({ variables: ["tags"] });
481
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
482
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.join("-", Token.asList(Fn.concat([Fn.lookupNested(tags.value, ["app"]), Fn.lookupNested(tags.value, ["env"]), Fn.lookupNested(tags.value, ["other"])]))))"`);
483
+ });
484
+ test("doesn't wrap any extra templates", async () => {
485
+ const expression = `"app-\${terraform.workspace}"`;
486
+ const scope = getScope();
487
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
488
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""app-\${terraform.workspace}""`);
489
+ });
490
+ test("converts a for expression", async () => {
491
+ const expression = `[for record in aws_route53_record.example : record.fqdn]`;
492
+ const scope = getScope();
493
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
494
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${[ for record in \${" + example.fqn + "} : record.fqdn]}""`);
495
+ });
496
+ test("converts a data source", async () => {
497
+ const expression = `"\${data.aws_route53_zone.example.zone_id}"`;
498
+ const scope = getScope();
499
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
500
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(example.zoneId)"`);
501
+ });
502
+ test("convert an each expression", async () => {
503
+ const expression = `"\${each.value.name}"`;
504
+ const scope = getScope({ forEachIteratorName: "myIterator" });
505
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
506
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(myIterator.value, ["name"]))"`);
507
+ });
508
+ test("converts a property of a function containing a resource", async () => {
509
+ const expression = `"\${element(aws_s3_bucket.examplebucket, 0).id}"`;
510
+ const scope = getScope();
511
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
512
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(Fn.element(examplebucket, 0), ["id"]))"`);
513
+ });
514
+ test("convert a function with references with splats", async () => {
515
+ const expression = `"\${concat(var.private_subnets.*.id, var.public_subnets.*.id)}"`;
516
+ const scope = getScope({
517
+ variables: ["private_subnets", "public_subnets"],
518
+ });
519
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
520
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.concat([Fn.lookupNested(privateSubnets.value, ["*", "id"]), Fn.lookupNested(publicSubnets.value, ["*", "id"])]))"`);
521
+ });
522
+ test("convert a iterator variable", async () => {
523
+ const expression = `"\${each.key}"`;
524
+ const scope = getScope({
525
+ variables: ["private_subnets", "public_subnets"],
526
+ forEachIteratorName: "myIterator",
527
+ });
528
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
529
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(myIterator.key)"`);
530
+ });
531
+ test("convert a self reference", async () => {
532
+ const expression = `"\${self.subnet.id}"`;
533
+ const scope = getScope({
534
+ variables: ["private_subnets", "public_subnets"],
535
+ forEachIteratorName: "myIterator",
536
+ });
537
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
538
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(TerraformSelf.getAny("subnet.id"))"`);
539
+ });
540
+ test("convert heredocs", async () => {
541
+ const expression = `<<EOF
542
+ [{
543
+ "Condition": {
544
+ "KeyPrefixEquals": "docs/"
545
+ },
546
+ "Redirect": {
547
+ "ReplaceKeyPrefixWith": "documents/"
548
+ }
549
+ }]
550
+ EOF
551
+ `;
552
+ const scope = getScope();
553
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
554
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""[{\\n \\"Condition\\": {\\n \\"KeyPrefixEquals\\": \\"docs/\\"\\n },\\n \\"Redirect\\": {\\n \\"ReplaceKeyPrefixWith\\": \\"documents/\\"\\n }\\n}]\\n""`);
555
+ });
556
+ test("convert heredocs without a trailing newline", async () => {
557
+ const expression = `<<EOF
558
+ hello world
559
+ EOF`;
560
+ const scope = getScope();
561
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
562
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello world\\n""`);
563
+ });
564
+ test("convert indented heredocs", async () => {
565
+ const expression = `<<-EOF
566
+ hello world
567
+ EOF`;
568
+ const scope = getScope();
569
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
570
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""hello world\\n""`);
571
+ });
572
+ test("convert override expressions", async () => {
573
+ const expression = '"${required_resource_access.value["resource_access"]}"';
574
+ const scope = getScope({
575
+ withinOverrideExpression: true,
576
+ scopedVariables: {
577
+ required_resource_access: "dynamic-block",
578
+ },
579
+ });
580
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
581
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`""\${required_resource_access.value[\\"resource_access\\"]}""`);
582
+ });
583
+ test("convert using operations while containing substring", async () => {
584
+ const expression =
585
+ // prettier-ignore
586
+ '"${length(var.image_id) > 4 && substr(var.image_id, 0, 4) == \"ami-\"}"';
587
+ const scope = getScope({});
588
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
589
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Op.and(Op.gt(Fn.lengthOf(imageId.value), 4), Op.eq(Fn.substr(imageId.stringValue, 0, 4), "ami-")))"`);
590
+ });
591
+ test("convert a data source with numeric access", async () => {
592
+ const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.names[0]}"`;
593
+ const scope = getScope({
594
+ provider: awsProviderSchema,
595
+ data: ["aws_subnet_ids"],
596
+ });
597
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
598
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(changemeAzListEbsSnapshot.names, ["0"]))"`);
599
+ });
600
+ test("convert a reference to a map access", async () => {
601
+ const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.testing_map.foo}"`;
602
+ const scope = getScope({
603
+ provider: awsProviderSchema,
604
+ data: ["aws_subnet_ids"],
605
+ });
606
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
607
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(changemeAzListEbsSnapshot, ["testing_map", "foo"]))"`);
608
+ });
609
+ test("convert attribute up to a map and not within attribute reference", async () => {
610
+ const expression = `"\${data.aws_availability_zones.changeme_az_list_ebs_snapshot.testing_map}"`;
611
+ const scope = getScope({
612
+ provider: awsProviderSchema,
613
+ });
614
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => ["map", "string"]);
615
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asStringMap(changemeAzListEbsSnapshot.testingMap)"`);
616
+ });
617
+ test("don't convert external unknown fields", async () => {
618
+ const expression = `"\${data.external.changeme_external_thumbprint_data.result.thumbprint}"`;
619
+ const scope = getScope({
620
+ provider: externalProviderSchema,
621
+ data: ["aws_subnet_ids"],
622
+ });
623
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => ["map", "string"]);
624
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asStringMap(Fn.lookupNested(changemeExternalThumbprintData, ["result", "thumbprint"]))"`);
625
+ });
626
+ test("convert resource reference with map attribute", async () => {
627
+ const expression = `"\${aws_s3_bucket.examplebucket.foo.bar}"`;
628
+ const scope = getScope({
629
+ provider: awsProviderSchema,
630
+ resources: ["aws_s3_bucket"],
631
+ });
632
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "string");
633
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(examplebucket, ["foo", "bar"]))"`);
634
+ });
635
+ test("convert complex variable reference in template", async () => {
636
+ const expression = `"\${var.default_tags.project}-client-tg"`;
637
+ const scope = getScope({
638
+ provider: awsProviderSchema,
639
+ resources: ["aws_s3_bucket"],
640
+ variables: ["default_tags"],
641
+ });
642
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "string");
643
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(defaultTags.value, ["project"])) + "-client-tg""`);
644
+ });
645
+ test("convert boolean values", async () => {
646
+ const expression = `"\${false}"`;
647
+ const scope = getScope({
648
+ provider: awsProviderSchema,
649
+ });
650
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, () => "bool");
651
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"false"`);
652
+ });
653
+ test("convert a data source with count", async () => {
654
+ const expression = `"\${data.aws_availability_zones.available.names[count.index]}"`;
655
+ const scope = getScope({
656
+ provider: awsProviderSchema,
657
+ data: ["aws_availability_zones"],
658
+ });
659
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
660
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.lookupNested(available.names, ["\${count.index}"]))"`);
661
+ });
662
+ test("accept escaped quotes within string", async () => {
663
+ const expression = `"\${jsonencode({
664
+ "Statement" = [{
665
+ "Action" = "s3:*",
666
+ "Effect" = "Allow",
667
+ }],
668
+ })}"`;
669
+ const scope = getScope();
670
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
671
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`
672
+ "Token.asString(Fn.jsonencode({
673
+ "Statement": [{
674
+ "Action": "s3:*",
675
+ "Effect": "Allow"
676
+ }]
677
+ }))"
678
+ `);
679
+ });
680
+ test("support variadic parameters in any position", async () => {
681
+ const expression = `"\${cidrsubnets("fd00:fd12:3456:7890::/56", 16, 16, 16, 32)}"`;
682
+ const scope = getScope();
683
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
684
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"Token.asString(Fn.cidrsubnets("fd00:fd12:3456:7890::/56", [16, 16, 16, 32]))"`);
685
+ });
686
+ test("converts template expression with escaped ${} expression", async () => {
687
+ const expression = '["$${path:name.givenName}"]'; // from aws_ssoadmin_instance_access_control_attributes example
688
+ const scope = getScope();
689
+ const result = await (0, expressions_1.convertTerraformExpressionToTs)(scope, expression, getType);
690
+ expect((0, testHelpers_1.astToCode)(result)).toMatchInlineSnapshot(`"["$\${path:name.givenName}"]"`);
691
+ });
692
+ });
693
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc2lvblRvVHMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4cHJlc3Npb25Ub1RzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUFFSCxnREFBZ0U7QUFHaEUsK0NBQWtEO0FBRWxELE1BQU0saUJBQWlCLEdBQUc7SUFDeEIsY0FBYyxFQUFFLEtBQUs7SUFDckIsZ0JBQWdCLEVBQUU7UUFDaEIscUNBQXFDLEVBQUU7WUFDckMsUUFBUSxFQUFFLEVBQUU7WUFDWixnQkFBZ0IsRUFBRTtnQkFDaEIsYUFBYSxFQUFFO29CQUNiLEtBQUssRUFBRTt3QkFDTCxVQUFVLEVBQUU7NEJBQ1YsR0FBRyxFQUFFO2dDQUNILElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUM7Z0NBQ3ZCLGdCQUFnQixFQUFFLE9BQU87NkJBQzFCO3lCQUNGO3FCQUNGO2lCQUNGO2FBQ0Y7WUFDRCxtQkFBbUIsRUFBRTtnQkFDbkIsc0JBQXNCLEVBQUU7b0JBQ3RCLE9BQU8sRUFBRSxDQUFDO29CQUNWLEtBQUssRUFBRTt3QkFDTCxVQUFVLEVBQUU7NEJBQ1Ysc0JBQXNCLEVBQUU7Z0NBQ3RCLElBQUksRUFBRSxNQUFNO2dDQUNaLGdCQUFnQixFQUFFLE9BQU87Z0NBQ3pCLFFBQVEsRUFBRSxJQUFJOzZCQUNmOzRCQUNELGFBQWEsRUFBRTtnQ0FDYixJQUFJLEVBQUUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDO2dDQUN2QixnQkFBZ0IsRUFBRSxPQUFPO2dDQUN6QixRQUFRLEVBQUUsSUFBSTs2QkFDZjs0QkFDRCxnQkFBZ0IsRUFBRTtnQ0FDaEIsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQztnQ0FDdkIsZ0JBQWdCLEVBQUUsT0FBTztnQ0FDekIsUUFBUSxFQUFFLElBQUk7NkJBQ2Y7NEJBQ0QsV0FBVyxFQUFFO2dDQUNYLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUM7Z0NB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ICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1QTC0yLjBcbiAqL1xuXG5pbXBvcnQgeyBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMgfSBmcm9tIFwiLi4vZXhwcmVzc2lvbnNcIjtcbmltcG9ydCB7IFJlc291cmNlU2NvcGUgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IEF0dHJpYnV0ZVR5cGUgfSBmcm9tIFwiQGNka3RuL2NvbW1vbnNcIjtcbmltcG9ydCB7IGFzdFRvQ29kZSBhcyBjb2RlIH0gZnJvbSBcIi4vdGVzdEhlbHBlcnNcIjtcblxuY29uc3QgYXdzUHJvdmlkZXJTY2hlbWEgPSB7XG4gIGZvcm1hdF92ZXJzaW9uOiBcIjEuMFwiLFxuICBwcm92aWRlcl9zY2hlbWFzOiB7XG4gICAgXCJyZWdpc3RyeS50ZXJyYWZvcm0uaW8vaGFzaGljb3JwL2F3c1wiOiB7XG4gICAgICBwcm92aWRlcjoge30sXG4gICAgICByZXNvdXJjZV9zY2hlbWFzOiB7XG4gICAgICAgIGF3c19zM19idWNrZXQ6IHtcbiAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICBmb286IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGRhdGFfc291cmNlX3NjaGVtYXM6IHtcbiAgICAgICAgYXdzX2F2YWlsYWJpbGl0eV96b25lczoge1xuICAgICAgICAgIHZlcnNpb246IDAsXG4gICAgICAgICAgYmxvY2s6IHtcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgYWxsX2F2YWlsYWJpbGl0eV96b25lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwiYm9vbFwiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZXhjbHVkZV9uYW1lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGV4Y2x1ZGVfem9uZV9pZHM6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJzZXRcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBncm91cF9uYW1lczoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcInNldFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGlkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIG5hbWVzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHN0YXRlOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHpvbmVfaWRzOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHRlc3RpbmdfbWFwOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBjb21wdXRlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBibG9ja190eXBlczoge1xuICAgICAgICAgICAgICBmaWx0ZXI6IHtcbiAgICAgICAgICAgICAgICBuZXN0aW5nX21vZGU6IFwic2V0XCIsXG4gICAgICAgICAgICAgICAgYmxvY2s6IHtcbiAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZToge1xuICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBbXCJzZXRcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB0aW1lb3V0czoge1xuICAgICAgICAgICAgICAgIG5lc3RpbmdfbW9kZTogXCJzaW5nbGVcIixcbiAgICAgICAgICAgICAgICBibG9jazoge1xuICAgICAgICAgICAgICAgICAgYXR0cmlidXRlczoge1xuICAgICAgICAgICAgICAgICAgICByZWFkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWw6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59O1xuXG5jb25zdCBleHRlcm5hbFByb3ZpZGVyU2NoZW1hID0ge1xuICBmb3JtYXRfdmVyc2lvbjogXCIxLjBcIixcbiAgcHJvdmlkZXJfc2NoZW1hczoge1xuICAgIFwicmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9leHRlcm5hbFwiOiB7XG4gICAgICBwcm92aWRlcjoge30sXG4gICAgICByZXNvdXJjZV9zY2hlbWFzOiB7fSxcbiAgICAgIGRhdGFfc291cmNlX3NjaGVtYXM6IHtcbiAgICAgICAgZXh0ZXJuYWw6IHtcbiAgICAgICAgICB2ZXJzaW9uOiAwLFxuICAgICAgICAgIGJsb2NrOiB7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiB7XG4gICAgICAgICAgICAgIGlkOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiVGhlIGlkIG9mIHRoZSBkYXRhIHNvdXJjZS4gVGhpcyB3aWxsIGFsd2F5cyBiZSBzZXQgdG8gYC1gXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIGNvbXB1dGVkOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBwcm9ncmFtOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogW1wibGlzdFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiQSBsaXN0IG9mIHN0cmluZ3MsIHdob3NlIGZpcnN0IGVsZW1lbnQgaXMgdGhlIHByb2dyYW0gdG8gcnVuIGFuZCB3aG9zZSBzdWJzZXF1ZW50IGVsZW1lbnRzIGFyZSBvcHRpb25hbCBjb21tYW5kIGxpbmUgYXJndW1lbnRzIHRvIHRoZSBwcm9ncmFtLiBUZXJyYWZvcm0gZG9lcyBub3QgZXhlY3V0ZSB0aGUgcHJvZ3JhbSB0aHJvdWdoIGEgc2hlbGwsIHNvIGl0IGlzIG5vdCBuZWNlc3NhcnkgdG8gZXNjYXBlIHNoZWxsIG1ldGFjaGFyYWN0ZXJzIG5vciBhZGQgcXVvdGVzIGFyb3VuZCBhcmd1bWVudHMgY29udGFpbmluZyBzcGFjZXMuXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBxdWVyeToge1xuICAgICAgICAgICAgICAgIHR5cGU6IFtcIm1hcFwiLCBcInN0cmluZ1wiXSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiQSBtYXAgb2Ygc3RyaW5nIHZhbHVlcyB0byBwYXNzIHRvIHRoZSBleHRlcm5hbCBwcm9ncmFtIGFzIHRoZSBxdWVyeSBhcmd1bWVudHMuIElmIG5vdCBzdXBwbGllZCwgdGhlIHByb2dyYW0gd2lsbCByZWNlaXZlIGFuIGVtcHR5IG9iamVjdCBhcyBpdHMgaW5wdXQuXCIsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb25fa2luZDogXCJwbGFpblwiLFxuICAgICAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICByZXN1bHQ6IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgICBcIkEgbWFwIG9mIHN0cmluZyB2YWx1ZXMgcmV0dXJuZWQgZnJvbSB0aGUgZXh0ZXJuYWwgcHJvZ3JhbS5cIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgICAgICAgY29tcHV0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHdvcmtpbmdfZGlyOiB7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgICAgIFwiV29ya2luZyBkaXJlY3Rvcnkgb2YgdGhlIHByb2dyYW0uIElmIG5vdCBzdXBwbGllZCwgdGhlIHByb2dyYW0gd2lsbCBydW4gaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5LlwiLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uX2tpbmQ6IFwicGxhaW5cIixcbiAgICAgICAgICAgICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjpcbiAgICAgICAgICAgICAgJ1RoZSBgZXh0ZXJuYWxgIGRhdGEgc291cmNlIGFsbG93cyBhbiBleHRlcm5hbCBwcm9ncmFtIGltcGxlbWVudGluZyBhIHNwZWNpZmljIHByb3RvY29sIChkZWZpbmVkIGJlbG93KSB0byBhY3QgYXMgYSBkYXRhIHNvdXJjZSwgZXhwb3NpbmcgYXJiaXRyYXJ5IGRhdGEgZm9yIHVzZSBlbHNld2hlcmUgaW4gdGhlIFRlcnJhZm9ybSBjb25maWd1cmF0aW9uLlxcblxcbioqV2FybmluZyoqIFRoaXMgbWVjaGFuaXNtIGlzIHByb3ZpZGVkIGFzIGFuIFwiZXNjYXBlIGhhdGNoXCIgZm9yIGV4Y2VwdGlvbmFsIHNpdHVhdGlvbnMgd2hlcmUgYSBmaXJzdC1jbGFzcyBUZXJyYWZvcm0gcHJvdmlkZXIgaXMgbm90IG1vcmUgYXBwcm9wcmlhdGUuIEl0cyBjYXBhYmlsaXRpZXMgYXJlIGxpbWl0ZWQgaW4gY29tcGFyaXNvbiB0byBhIHRydWUgZGF0YSBzb3VyY2UsIGFuZCBpbXBsZW1lbnRpbmcgYSBkYXRhIHNvdXJjZSB2aWEgYW4gZXh0ZXJuYWwgcHJvZ3JhbSBpcyBsaWtlbHkgdG8gaHVydCB0aGUgcG9ydGFiaWxpdHkgb2YgeW91ciBUZXJyYWZvcm0gY29uZmlndXJhdGlvbiBieSBjcmVhdGluZyBkZXBlbmRlbmNpZXMgb24gZXh0ZXJuYWwgcHJvZ3JhbXMgYW5kIGxpYnJhcmllcyB0aGF0IG1heSBub3QgYmUgYXZhaWxhYmxlIChvciBtYXkgbmVlZCB0byBiZSB1c2VkIGRpZmZlcmVudGx5KSBvbiBkaWZmZXJlbnQgb3BlcmF0aW5nIHN5c3RlbXMuXFxuXFxuKipXYXJuaW5nKiogVGVycmFmb3JtIEVudGVycHJpc2UgZG9lcyBub3QgZ3VhcmFudGVlIGF2YWlsYWJpbGl0eSBvZiBhbnkgcGFydGljdWxhciBsYW5ndWFnZSBydW50aW1lcyBvciBleHRlcm5hbCBwcm9ncmFtcyBiZXlvbmQgc3RhbmRhcmQgc2hlbGwgdXRpbGl0aWVzLCBzbyBpdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gdXNlIHRoaXMgZGF0YSBzb3VyY2Ugd2l0aGluIGNvbmZpZ3VyYXRpb25zIHRoYXQgYXJlIGFwcGxpZWQgd2l0aGluIFRlcnJhZm9ybSBFbnRlcnByaXNlLicsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbl9raW5kOiBcInBsYWluXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn07XG5cbnR5cGUgR2V0U2NvcGVQYXJhbXMgPSB7XG4gIHByb3ZpZGVyPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgcmVzb3VyY2VzPzogc3RyaW5nW107XG4gIGRhdGE/OiBzdHJpbmdbXTtcbiAgdmFyaWFibGVzPzogc3RyaW5nW107XG4gIGxvY2Fscz86IHN0cmluZ1tdO1xuICBmb3JFYWNoSXRlcmF0b3JOYW1lPzogc3RyaW5nO1xuICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24/OiBib29sZWFuO1xuICBzY29wZWRWYXJpYWJsZXM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxuZnVuY3Rpb24gZ2V0U2NvcGUoe1xuICBwcm92aWRlcixcbiAgcmVzb3VyY2VzLFxuICBkYXRhLFxuICB2YXJpYWJsZXMsXG4gIGxvY2FscyxcbiAgZm9yRWFjaEl0ZXJhdG9yTmFtZSxcbiAgc2NvcGVkVmFyaWFibGVzLFxuICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24gPSBmYWxzZSxcbn06IEdldFNjb3BlUGFyYW1zID0ge30pOiBSZXNvdXJjZVNjb3BlIHtcbiAgY29uc3Qgc2NvcGVWYXJpYWJsZXM6IFJlc291cmNlU2NvcGVbXCJ2YXJpYWJsZXNcIl0gPSB7fTtcblxuICByZXNvdXJjZXM/LmZvckVhY2goKHZhck5hbWUpID0+IHtcbiAgICBsZXQgW3Jlc291cmNlVHlwZSwgcmVzb3VyY2VOYW1lXSA9IHZhck5hbWUuc3BsaXQoXCIuXCIpO1xuICAgIGlmICghcmVzb3VyY2VOYW1lKSB7XG4gICAgICByZXNvdXJjZU5hbWUgPSB2YXJOYW1lO1xuICAgICAgcmVzb3VyY2VUeXBlID0gXCJhd3NfczNfYnVja2V0XCI7XG4gICAgfVxuXG4gICAgc2NvcGVWYXJpYWJsZXNbdmFyTmFtZV0gPSB7XG4gICAgICByZXNvdXJjZTogcmVzb3VyY2VUeXBlLFxuICAgICAgdmFyaWFibGVOYW1lOiByZXNvdXJjZU5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgZGF0YT8uZm9yRWFjaCgodmFyTmFtZSkgPT4ge1xuICAgIHNjb3BlVmFyaWFibGVzW3Zhck5hbWVdID0ge1xuICAgICAgcmVzb3VyY2U6IFwiZGF0YS5hd3NfczNfYnVja2V0XCIsXG4gICAgICB2YXJpYWJsZU5hbWU6IHZhck5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgdmFyaWFibGVzPy5mb3JFYWNoKCh2YXJOYW1lKSA9PiB7XG4gICAgc2NvcGVWYXJpYWJsZXNbdmFyTmFtZV0gPSB7XG4gICAgICByZXNvdXJjZTogXCJ2YXJcIixcbiAgICAgIHZhcmlhYmxlTmFtZTogdmFyTmFtZSxcbiAgICB9O1xuICB9KTtcblxuICBsb2NhbHM/LmZvckVhY2goKHZhck5hbWUpID0+IHtcbiAgICBzY29wZVZhcmlhYmxlc1t2YXJOYW1lXSA9IHtcbiAgICAgIHJlc291cmNlOiBcImxvY2FsXCIsXG4gICAgICB2YXJpYWJsZU5hbWU6IHZhck5hbWUsXG4gICAgfTtcbiAgfSk7XG5cbiAgY29uc3Qgc2NvcGUgPSB7XG4gICAgcHJvdmlkZXJTY2hlbWE6IHByb3ZpZGVyID8/IHt9LFxuICAgIHByb3ZpZGVyR2VuZXJhdG9yOiB7fSxcbiAgICBjb25zdHJ1Y3RzOiBuZXcgU2V0PHN0cmluZz4oKSxcbiAgICB2YXJpYWJsZXM6IHNjb3BlVmFyaWFibGVzLFxuICAgIGhhc1Rva2VuQmFzZWRUeXBlQ29lcmNpb246IHRydWUsXG4gICAgc2NvcGVkVmFyaWFibGVzOiBzY29wZWRWYXJpYWJsZXMgfHwge30sXG4gICAgZm9yRWFjaEl0ZXJhdG9yTmFtZSxcbiAgICB3aXRoaW5PdmVycmlkZUV4cHJlc3Npb24sXG4gICAgbm9kZUlkczogW10sXG4gICAgaW1wb3J0YWJsZXM6IFtdLFxuICAgIHRvcExldmVsQ29uZmlnOiB7fSxcbiAgfTtcblxuICByZXR1cm4gc2NvcGU7XG59XG5cbmNvbnN0IGdldFR5cGUgPSAoKTogQXR0cmlidXRlVHlwZSA9PiBcInN0cmluZ1wiO1xuXG5kZXNjcmliZShcImV4cHJlc3Npb25Ub1RzXCIsICgpID0+IHtcbiAgdGVzdChcImNvbnZlcnRzIGEgc2ltcGxlIHN0cmluZyB0byBhIHN0cmluZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiaGVsbG9cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJcImhlbGxvXCJcImApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBzaW1wbGUgZXhwcmVzc2lvbiB3aXRoIGEgdGVtcGxhdGVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7MjJ9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiVG9rZW4uYXNTdHJpbmcoMjIpXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgdmFyaWFibGUgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke3Zhci5mb299XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiZm9vLnN0cmluZ1ZhbHVlXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSB2YXJpYWJsZSByZWZlcmVuY2Ugd2l0aCBzbmFrZSBjYXNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke3Zhci5mb29fYmFyfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcImZvb19iYXJcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGZvb0Jhci52YWx1ZSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBmdW5jdGlvbiBjYWxsXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtyZXBsYWNlKFwiaGVsbG9cIiwgXCJsXCIsIFwid1wiKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ucmVwbGFjZShcImhlbGxvXCIsIFwibFwiLCBcIndcIikpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGZ1bmN0aW9uIGNhbGwgd2l0aCBhbiBleHByZXNzaW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHtyZXBsYWNlKFwiaGVsbG8tXFwkezIyKzIyfVwiLCBcIjQ0XCIsIFwid29ybGRcIil9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLnJlcGxhY2UoXCJoZWxsby1cIiArIFRva2VuLmFzU3RyaW5nKE9wLmFkZCgyMiwgMjIpKSwgXCI0NFwiLCBcIndvcmxkXCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgc3RyaW5nIGNvbmNhdGVuYXRpb24gb2YgaXRlcmF0b3Iga2V5XCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJyR7XCJkeW5hbWljLWluZ3Jlc3MtJHtpbmdyZXNzLmtleX1cIn0nO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgc2NvcGVkVmFyaWFibGVzOiB7XG4gICAgICAgIGluZ3Jlc3M6IFwiZHluYW1pY19pdGVyYXRvcjBcIixcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiZHluYW1pYy1pbmdyZXNzLVxcJHtcIiArIFRva2VuLmFzU3RyaW5nKGR5bmFtaWNfaXRlcmF0b3IwLmtleSkgKyBcIn1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIHZhcmlhYmxlIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7dmFyLmZvb19iYXJ9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJmb29fYmFyXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICAvLyBUT0RPOiBUaGlzIHNlZW1zIGJyb2tlblxuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGZvb0Jhci52YWx1ZSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSByZXNvdXJjZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJzaW1wbGUtXFwke2F3c19zM19idWNrZXQuZm9vLmlkfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwic2ltcGxlLVxcJHtcIiArIGZvby5pZCArIFwifVwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSByZXNvdXJjZSByZWZlcmVuY2Ugd2l0aCBuZXN0ZWQgcHJvcGVydGllc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcInNpbXBsZS1cXCR7YXdzX3MzX2J1Y2tldC5mb28ucHJvcC50ZXN0fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJzaW1wbGUtXFwke1wiICsgZm9vLnByb3AudGVzdCArIFwifVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgbG9jYWwgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwic2ltcGxlLVxcJHtsb2NhbC5mb299XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyBsb2NhbHM6IFtcImZvb1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwic2ltcGxlLVxcJHtcIiArIGZvbyArIFwifVwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcInBsYWluIHJlc291cmNlIHJlZmVyZW5jZXMgaW4gYXJpdGhtZXRpY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPVxuICAgICAgXCIke2F3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5jb3VudCArIGF3c19zM19idWNrZXQub3RoZXJidWNrZXQuY291bnQgfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIiwgXCJhd3NfczNfYnVja2V0Lm90aGVyYnVja2V0XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhPcC5hZGQoZXhhbXBsZWJ1Y2tldC5jb3VudCwgb3RoZXJidWNrZXQuY291bnQpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwidXNlIGZxbiBmb3Igc3BsYXQgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFxcJHthd3NfczNfYnVja2V0LmZvby4qLmlkfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5mb29cIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChmb28sIFtcIipcIiwgXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJ1c2UgZnFuIGlmIHByb3BlcnR5IGlzIHByZXNlbnQgb24gbnVtZXJpYyBhY2Nlc3MgdXNpbmcgZG90IG5vdGF0aW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQubmV0d29ya19pbnRlcmZhY2UuMC5hY2Nlc3NfY29uZmlnLjAuYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInVzZSBmcW4gaWYgcHJvcGVydHkgaXMgcHJlc2VudCBvbiBudW1lcmljIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0Lm5ldHdvcmtfaW50ZXJmYWNlWzBdLmFjY2Vzc19jb25maWdbMF0uYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInVzZSBubyBmcW4gaWYgcHJvcGVydHkgaXMgcHJlc2VudCBvbiBudW1lcmljIGFjY2VzcyB1c2luZyBbXVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0Lm5ldHdvcmtfaW50ZXJmYWNlWzBdLmFjY2Vzc19jb25maWdbMF0uYXNzaWduZWRfbmF0X2lwfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQubmV0d29ya0ludGVyZmFjZSwgW1wiMFwiLCBcImFjY2Vzc19jb25maWdcIiwgXCIwXCIsIFwiYXNzaWduZWRfbmF0X2lwXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImRldGVjdHMgc3BsYXQgcmVmZXJlbmNlIHdpdGhpbiBmdW5jdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHt0b3NldChhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuKil9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi50b3NldChGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiKlwiXSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBjb25kaXRpb25hbFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7YXdzX2ttc19rZXkua2V5LmRlbGV0aW9uX3dpbmRvd19pbl9kYXlzID4gMyA/IGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5pZCA6IFtdfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19rbXNfa2V5LmtleVwiLCBcImV4YW1wbGVidWNrZXRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKGNvbmRpdGlvbmFsKE9wLmd0KGtleS5kZWxldGlvbldpbmRvd0luRGF5cywgMyksIGV4YW1wbGVidWNrZXQuaWQsIFtdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZnVuY3Rpb24gd2l0aCByZWZlcmVuY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke2VsZW1lbnQoYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LCAwKS5pZH1cIjtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChGbi5lbGVtZW50KGV4YW1wbGVidWNrZXQsIDApLCBbXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGZ1bmN0aW9uIHdpdGggc3BsYXQgcmVmZXJlbmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCIke2VsZW1lbnQoYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LiouaWQsIDApfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZWxlbWVudChGbi5sb29rdXBOZXN0ZWQoZXhhbXBsZWJ1Y2tldCwgW1wiKlwiLCBcImlkXCJdKSwgMCkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGZvciBsb29wc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9XG4gICAgICBcIiR7eyBmb3IgbmFtZSwgdXNlciBpbiB2YXIudXNlcnMgOiB1c2VyLnJvbGUgPT4gbmFtZS4uLn19XCI7XG5cbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke3sgZm9yIG5hbWUsIHVzZXIgaW4gXFwke1wiICsgdXNlcnMudmFsdWUgKyBcIn0gOiB1c2VyLnJvbGUgPT4gbmFtZS4uLn19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImZvciBleHByZXNzaW9uc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwie2ZvciBzIGluIHZhci5saXN0IDogcyA9PiB1cHBlcihzKX1cIjtcblxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7eyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogcyA9PiB1cHBlcihzKX19XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImZvciBsaXN0IGV4cHJlc3Npb24gXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gXCJbZm9yIHMgaW4gdmFyLmxpc3QgOiB1cHBlcihzKV1cIjtcblxuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogdXBwZXIocyldfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJmb3IgbGlzdCB3aXRoIGNvbmRpdGlvbmFsXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1tmb3IgcyBpbiB2YXIubGlzdCA6IHVwcGVyKHMpIGlmIHMgIT0gXCJcIl0nO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcyBpbiBcXCR7XCIgKyBsaXN0LnZhbHVlICsgXCJ9IDogdXBwZXIocykgaWYgcyAhPSBcXFxcXCJcXFxcXCJdfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHByb3BlcnR5IGFjY2VzcyByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0WzBdLmlkfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKGV4YW1wbGVidWNrZXQsIFtcIjBcIiwgXCJpZFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IHVuYXJ5IG9wZXJhdG9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7IXZhci5lbmFibGVkfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1wiZW5hYmxlZFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBcImJvb2xcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzQm9vbGVhbihPcC5ub3QoZW5hYmxlZC52YWx1ZSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGZ1bmN0aW9uIHdpdGggYXJyYXlzIGFuZCBjb21tZW50c1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7Y29tcGFjdChbXG4gICAgICAgICAgICAjIFRoZSBleGFtcGxlIFwiYnVja2V0XCJcbiAgICAgICAgICAgIGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCxcbiAgICAgICAgXG4gICAgICAgICAgICAjIFRoZSBcIkxlYXJuXCIgc2luZ2xlIHBhZ2UgYXBwbGljYXRpb24uIFRoaXMgaXMgbm90IGNvbmZpZ3VyZWQgaW4gYWxsIGVudmlyb25tZW50cy5cbiAgICAgICAgICAgIHZhci5pbnB1dCxcbiAgICAgICAgICBdKX1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcmVzb3VyY2VzOiBbXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIl0sXG4gICAgICB2YXJpYWJsZXM6IFtcImlucHV0XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICAvLyBUT0RPOiBTZWUgaWYgd2UgaGF2ZSBhIHdheSB0byBwcmVzZXJ2ZSBjb21tZW50c1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmNvbXBhY3QoVG9rZW4uYXNMaXN0KFtleGFtcGxlYnVja2V0LCBpbnB1dC52YWx1ZV0pKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgcmVmZXJlbmNlcyBmb3Igc2FtZSByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke3Zhci5pbnB1dCA9PSBcInRlc3RcIiA/IFwiYXp1cmUtYWQtaW50XCIgOiBcImF6dXJlLWFkLVxcJHt2YXIuaW5wdXR9XCJ9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJpbnB1dFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoY29uZGl0aW9uYWwoT3AuZXEoaW5wdXQudmFsdWUsIFwidGVzdFwiKSwgXCJhenVyZS1hZC1pbnRcIiwgXCJhenVyZS1hZC1cXCR7XCIgKyBpbnB1dC52YWx1ZSArIFwifVwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcIm5lc3RlZCB2YXJpYWJsZSBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXFwke2VsZW1lbnQodmFyLnRlc3QyW1widmFsMVwiXSwgMCl9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ0ZXN0MlwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZWxlbWVudChGbi5sb29rdXBOZXN0ZWQodGVzdDIudmFsdWUsIFtcIlxcXFxcInZhbDFcXFxcXCJcIl0pLCAwKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbXBsaWNhdGVkIG5lc3RlZCBsb2NhbCB2YWx1ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IFwiJHtmbGF0dGVuKHZhci52bmV0c1sqXS5zdWJuZXRzWypdLm5hbWUpfVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInZuZXRzXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5mbGF0dGVuKEZuLmxvb2t1cE5lc3RlZCh2bmV0cy52YWx1ZSwgW1wiKlwiLCBcInN1Ym5ldHNcIiwgXCIqXCIsIFwibmFtZVwiXSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICAvLyBUT0lNUFJPVkU6IEkgZG9uJ3QgdGhpbmsgd2UgY2FuIGhhbmRsZSB0aGlzIGNhc2UgeWV0LCBzaW5jZSB0aGUgdmFyaWFibGVcbiAgLy8gbmVlZHMgdG8gYmUgd3JhcHBlZCBpbiBhbiBpdGVyYXRvci4gSSdtIGxlYXZpbmcgdGhpcyBpbiwgYnV0IGl0J3MgYnJva2VuXG4gIHRlc3QoXCJjb21wbGljYXRlZCBuZXN0ZWQgdmFyaWFibGUgYWNjZXNzIHdpdGggbWFwXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYHsgXG4gICAgZm9yIHZuZXQgaW4gdmFyLnZuZXRzWypdOlxuICAgICh2bmV0LnZuZXRfbmFtZSkgPT4gdm5ldC5zdWJuZXRzWypdLm5hbWVcbiAgfWA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widm5ldHNcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke3sgZm9yIHZuZXQgaW4gXFwke1wiICsgRm4ubG9va3VwTmVzdGVkKHZuZXRzLnZhbHVlLCBbXCIqXCJdKSArIFwifSA6ICh2bmV0LnZuZXRfbmFtZSkgPT4gdm5ldC5zdWJuZXRzWypdLm5hbWV9fVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb21wbGljYXRlZCBuZXN0ZWQgdmFyaWFibGUgYWNjZXNzIHdpdGggbGlzdFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcXCR7ZmxhdHRlbihbXG4gICAgZm9yIGssIHYgaW4gdmFyLnJvdXRlIDogW1xuICAgICAgZm9yIG4sIHMgaW4gdiA6IFtcbiAgICAgICAge1xuICAgICAgICAgIGtleSA9IGssXG4gICAgICAgICAgbmFtZSA9IG4sXG4gICAgICAgICAgc3ZjX3VybCA9IHNcbiAgICAgICAgfVxuICAgICAgXVxuICAgIF1cbiAgXSl9YDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJyb3V0ZVwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uZmxhdHRlbihcIlxcJHtbIGZvciBrLCB2IGluIFxcJHtcIiArIHJvdXRlLnZhbHVlICsgXCJ9IDogW1xcXFxuICAgICAgZm9yIG4sIHMgaW4gdiA6IFtcXFxcbiAgICAgICAge1xcXFxuICAgICAgICAgIGtleSA9IGssXFxcXG4gICAgICAgICAgbmFtZSA9IG4sXFxcXG4gICAgICAgICAgc3ZjX3VybCA9IHNcXFxcbiAgICAgICAgfVxcXFxuICAgICAgXVxcXFxuICAgIF1dfVwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcInNpbXBsZSBsb2NhbCB2YXJpYWJsZSBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7IWxvY2FsLmVuYWJsZWR9XCI7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IGxvY2FsczogW1wiZW5hYmxlZFwiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoT3Aubm90KGVuYWJsZWQpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwibXVsdGkgbG9jYWwgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgICdcIiR7bG9jYWwuc2VydmljZV9uYW1lfSwke2xvY2FsLm93bmVyfSwke2xvY2FsLmlzX2l0X2dyZWF0fSwke2xvY2FsLmhvd19tYW55fVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIGxvY2FsczogW1wic2VydmljZV9uYW1lXCIsIFwib3duZXJcIiwgXCJpc19pdF9ncmVhdFwiLCBcImhvd19tYW55XCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtcIiArIHNlcnZpY2VOYW1lICsgXCJ9LFxcJHtcIiArIG93bmVyICsgXCJ9LFxcJHtcIiArIGlzSXRHcmVhdCArIFwifSxcXCR7XCIgKyBob3dNYW55ICsgXCJ9XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImJpbmFyeSBvcGVyYXRpb25zIHdpdGhpbiBsaXRlcmFscyBhbmQgdmFyaWFibGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHt2YXIudGVzdH0gKyAxXCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyB2YXJpYWJsZXM6IFtcInRlc3RcIl0gfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiXFwke1wiICsgdGVzdC52YWx1ZSArIFwifSArIDFcIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwibG9jYWwgdmFyaWFibGUgYWNjZXNzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHtsb2NhbC5lbmFibGVkfVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgbG9jYWxzOiBbXCJlbmFibGVkXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwiZW5hYmxlZFwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyB0cmF2ZXJzYWxzIHRoYXQgY2Fubm90IGJlIHJlZmVyZW5jZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBcIiR7c2VsZi5wYXRofVwiO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoVGVycmFmb3JtU2VsZi5nZXRBbnkoXCJwYXRoXCIpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgam9pbiBmdW5jdGlvbiB3aXRoIHZhcmlhYmxlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9ICcke2pvaW4oXCItXCIsIFt2YXIudGFncy5hcHAsIHZhci50YWdzLmVudl0pfSc7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7IHZhcmlhYmxlczogW1widGFnc1wiXSB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4uam9pbihcIi1cIiwgVG9rZW4uYXNMaXN0KFtGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiYXBwXCJdKSwgRm4ubG9va3VwTmVzdGVkKHRhZ3MudmFsdWUsIFtcImVudlwiXSldKSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBqb2luIGZ1bmN0aW9uIHdpdGggbWFueSBhcmd1bWVudHMgdmFyaWFibGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgICcke2pvaW4oXCItXCIsIHZhci50YWdzLmFwcCwgdmFyLnRhZ3MuZW52LCB2YXIudGFncy5vdGhlcil9JztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHsgdmFyaWFibGVzOiBbXCJ0YWdzXCJdIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5qb2luKFwiLVwiLCBUb2tlbi5hc0xpc3QoRm4uY29uY2F0KFtGbi5sb29rdXBOZXN0ZWQodGFncy52YWx1ZSwgW1wiYXBwXCJdKSwgRm4ubG9va3VwTmVzdGVkKHRhZ3MudmFsdWUsIFtcImVudlwiXSksIEZuLmxvb2t1cE5lc3RlZCh0YWdzLnZhbHVlLCBbXCJvdGhlclwiXSldKSkpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiZG9lc24ndCB3cmFwIGFueSBleHRyYSB0ZW1wbGF0ZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJhcHAtXFwke3RlcnJhZm9ybS53b3Jrc3BhY2V9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJhcHAtXFwke3RlcnJhZm9ybS53b3Jrc3BhY2V9XCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIGEgZm9yIGV4cHJlc3Npb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgW2ZvciByZWNvcmQgaW4gYXdzX3JvdXRlNTNfcmVjb3JkLmV4YW1wbGUgOiByZWNvcmQuZnFkbl1gO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiXCJcXCR7WyBmb3IgcmVjb3JkIGluIFxcJHtcIiArIGV4YW1wbGUuZnFuICsgXCJ9IDogcmVjb3JkLmZxZG5dfVwiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0cyBhIGRhdGEgc291cmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2RhdGEuYXdzX3JvdXRlNTNfem9uZS5leGFtcGxlLnpvbmVfaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoZXhhbXBsZS56b25lSWQpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGFuIGVhY2ggZXhwcmVzc2lvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtlYWNoLnZhbHVlLm5hbWV9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoeyBmb3JFYWNoSXRlcmF0b3JOYW1lOiBcIm15SXRlcmF0b3JcIiB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKG15SXRlcmF0b3IudmFsdWUsIFtcIm5hbWVcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydHMgYSBwcm9wZXJ0eSBvZiBhIGZ1bmN0aW9uIGNvbnRhaW5pbmcgYSByZXNvdXJjZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtlbGVtZW50KGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCwgMCkuaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoRm4ubG9va3VwTmVzdGVkKEZuLmVsZW1lbnQoZXhhbXBsZWJ1Y2tldCwgMCksIFtcImlkXCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgYSBmdW5jdGlvbiB3aXRoIHJlZmVyZW5jZXMgd2l0aCBzcGxhdHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7Y29uY2F0KHZhci5wcml2YXRlX3N1Ym5ldHMuKi5pZCwgdmFyLnB1YmxpY19zdWJuZXRzLiouaWQpfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHZhcmlhYmxlczogW1wicHJpdmF0ZV9zdWJuZXRzXCIsIFwicHVibGljX3N1Ym5ldHNcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmNvbmNhdChbRm4ubG9va3VwTmVzdGVkKHByaXZhdGVTdWJuZXRzLnZhbHVlLCBbXCIqXCIsIFwiaWRcIl0pLCBGbi5sb29rdXBOZXN0ZWQocHVibGljU3VibmV0cy52YWx1ZSwgW1wiKlwiLCBcImlkXCJdKV0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGl0ZXJhdG9yIHZhcmlhYmxlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2VhY2gua2V5fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHZhcmlhYmxlczogW1wicHJpdmF0ZV9zdWJuZXRzXCIsIFwicHVibGljX3N1Ym5ldHNcIl0sXG4gICAgICBmb3JFYWNoSXRlcmF0b3JOYW1lOiBcIm15SXRlcmF0b3JcIixcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcobXlJdGVyYXRvci5rZXkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgc2VsZiByZWZlcmVuY2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7c2VsZi5zdWJuZXQuaWR9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgdmFyaWFibGVzOiBbXCJwcml2YXRlX3N1Ym5ldHNcIiwgXCJwdWJsaWNfc3VibmV0c1wiXSxcbiAgICAgIGZvckVhY2hJdGVyYXRvck5hbWU6IFwibXlJdGVyYXRvclwiLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhUZXJyYWZvcm1TZWxmLmdldEFueShcInN1Ym5ldC5pZFwiKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaGVyZWRvY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDxFT0Zcblt7XG4gICAgXCJDb25kaXRpb25cIjoge1xuICAgICAgICBcIktleVByZWZpeEVxdWFsc1wiOiBcImRvY3MvXCJcbiAgICB9LFxuICAgIFwiUmVkaXJlY3RcIjoge1xuICAgICAgICBcIlJlcGxhY2VLZXlQcmVmaXhXaXRoXCI6IFwiZG9jdW1lbnRzL1wiXG4gICAgfVxufV1cbkVPRlxuYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlwiW3tcXFxcbiAgICBcXFxcXCJDb25kaXRpb25cXFxcXCI6IHtcXFxcbiAgICAgICAgXFxcXFwiS2V5UHJlZml4RXF1YWxzXFxcXFwiOiBcXFxcXCJkb2NzL1xcXFxcIlxcXFxuICAgIH0sXFxcXG4gICAgXFxcXFwiUmVkaXJlY3RcXFxcXCI6IHtcXFxcbiAgICAgICAgXFxcXFwiUmVwbGFjZUtleVByZWZpeFdpdGhcXFxcXCI6IFxcXFxcImRvY3VtZW50cy9cXFxcXCJcXFxcbiAgICB9XFxcXG59XVxcXFxuXCJcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaGVyZWRvY3Mgd2l0aG91dCBhIHRyYWlsaW5nIG5ld2xpbmVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDxFT0ZcbmhlbGxvIHdvcmxkXG5FT0ZgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcIlwiaGVsbG8gd29ybGRcXFxcblwiXCJgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgaW5kZW50ZWQgaGVyZWRvY3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgPDwtRU9GXG4gICAgICAgICAgICAgIGhlbGxvIHdvcmxkXG4gICAgICAgICAgRU9GYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgZ2V0VHlwZSxcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJcImhlbGxvIHdvcmxkXFxcXG5cIlwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IG92ZXJyaWRlIGV4cHJlc3Npb25zXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1wiJHtyZXF1aXJlZF9yZXNvdXJjZV9hY2Nlc3MudmFsdWVbXCJyZXNvdXJjZV9hY2Nlc3NcIl19XCInO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgd2l0aGluT3ZlcnJpZGVFeHByZXNzaW9uOiB0cnVlLFxuICAgICAgc2NvcGVkVmFyaWFibGVzOiB7XG4gICAgICAgIHJlcXVpcmVkX3Jlc291cmNlX2FjY2VzczogXCJkeW5hbWljLWJsb2NrXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJcIlxcJHtyZXF1aXJlZF9yZXNvdXJjZV9hY2Nlc3MudmFsdWVbXFxcXFwicmVzb3VyY2VfYWNjZXNzXFxcXFwiXX1cIlwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCB1c2luZyBvcGVyYXRpb25zIHdoaWxlIGNvbnRhaW5pbmcgc3Vic3RyaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID1cbiAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgJ1wiJHtsZW5ndGgodmFyLmltYWdlX2lkKSA+IDQgJiYgc3Vic3RyKHZhci5pbWFnZV9pZCwgMCwgNCkgPT0gXFxcImFtaS1cXFwifVwiJztcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHt9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KFxuICAgICAgYFwiVG9rZW4uYXNTdHJpbmcoT3AuYW5kKE9wLmd0KEZuLmxlbmd0aE9mKGltYWdlSWQudmFsdWUpLCA0KSwgT3AuZXEoRm4uc3Vic3RyKGltYWdlSWQuc3RyaW5nVmFsdWUsIDAsIDQpLCBcImFtaS1cIikpKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhIGRhdGEgc291cmNlIHdpdGggbnVtZXJpYyBhY2Nlc3NcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGV4cHJlc3Npb24gPSBgXCJcXCR7ZGF0YS5hd3NfYXZhaWxhYmlsaXR5X3pvbmVzLmNoYW5nZW1lX2F6X2xpc3RfZWJzX3NuYXBzaG90Lm5hbWVzWzBdfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIGRhdGE6IFtcImF3c19zdWJuZXRfaWRzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVBekxpc3RFYnNTbmFwc2hvdC5uYW1lcywgW1wiMFwiXSkpXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgcmVmZXJlbmNlIHRvIGEgbWFwIGFjY2Vzc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuY2hhbmdlbWVfYXpfbGlzdF9lYnNfc25hcHNob3QudGVzdGluZ19tYXAuZm9vfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIGRhdGE6IFtcImF3c19zdWJuZXRfaWRzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVBekxpc3RFYnNTbmFwc2hvdCwgW1widGVzdGluZ19tYXBcIiwgXCJmb29cIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBhdHRyaWJ1dGUgdXAgdG8gYSBtYXAgYW5kIG5vdCB3aXRoaW4gYXR0cmlidXRlIHJlZmVyZW5jZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuY2hhbmdlbWVfYXpfbGlzdF9lYnNfc25hcHNob3QudGVzdGluZ19tYXB9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoe1xuICAgICAgcHJvdmlkZXI6IGF3c1Byb3ZpZGVyU2NoZW1hLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gW1wibWFwXCIsIFwic3RyaW5nXCJdLFxuICAgICk7XG5cbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZ01hcChjaGFuZ2VtZUF6TGlzdEVic1NuYXBzaG90LnRlc3RpbmdNYXApXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJkb24ndCBjb252ZXJ0IGV4dGVybmFsIHVua25vd24gZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2RhdGEuZXh0ZXJuYWwuY2hhbmdlbWVfZXh0ZXJuYWxfdGh1bWJwcmludF9kYXRhLnJlc3VsdC50aHVtYnByaW50fVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBleHRlcm5hbFByb3ZpZGVyU2NoZW1hLFxuICAgICAgZGF0YTogW1wiYXdzX3N1Ym5ldF9pZHNcIl0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBbXCJtYXBcIiwgXCJzdHJpbmdcIl0sXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZ01hcChGbi5sb29rdXBOZXN0ZWQoY2hhbmdlbWVFeHRlcm5hbFRodW1icHJpbnREYXRhLCBbXCJyZXN1bHRcIiwgXCJ0aHVtYnByaW50XCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnQgcmVzb3VyY2UgcmVmZXJlbmNlIHdpdGggbWFwIGF0dHJpYnV0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuZm9vLmJhcn1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICByZXNvdXJjZXM6IFtcImF3c19zM19idWNrZXRcIl0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY29udmVydFRlcnJhZm9ybUV4cHJlc3Npb25Ub1RzKFxuICAgICAgc2NvcGUsXG4gICAgICBleHByZXNzaW9uLFxuICAgICAgKCkgPT4gXCJzdHJpbmdcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIlRva2VuLmFzU3RyaW5nKEZuLmxvb2t1cE5lc3RlZChleGFtcGxlYnVja2V0LCBbXCJmb29cIiwgXCJiYXJcIl0pKVwiYCxcbiAgICApO1xuICB9KTtcblxuICB0ZXN0KFwiY29udmVydCBjb21wbGV4IHZhcmlhYmxlIHJlZmVyZW5jZSBpbiB0ZW1wbGF0ZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHt2YXIuZGVmYXVsdF90YWdzLnByb2plY3R9LWNsaWVudC10Z1wiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICAgIHJlc291cmNlczogW1wiYXdzX3MzX2J1Y2tldFwiXSxcbiAgICAgIHZhcmlhYmxlczogW1wiZGVmYXVsdF90YWdzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgICgpID0+IFwic3RyaW5nXCIsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoZGVmYXVsdFRhZ3MudmFsdWUsIFtcInByb2plY3RcIl0pKSArIFwiLWNsaWVudC10Z1wiXCJgLFxuICAgICk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGJvb2xlYW4gdmFsdWVzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2ZhbHNlfVwiYDtcbiAgICBjb25zdCBzY29wZSA9IGdldFNjb3BlKHtcbiAgICAgIHByb3ZpZGVyOiBhd3NQcm92aWRlclNjaGVtYSxcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICAoKSA9PiBcImJvb2xcIixcbiAgICApO1xuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChgXCJmYWxzZVwiYCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJjb252ZXJ0IGEgZGF0YSBzb3VyY2Ugd2l0aCBjb3VudFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtkYXRhLmF3c19hdmFpbGFiaWxpdHlfem9uZXMuYXZhaWxhYmxlLm5hbWVzW2NvdW50LmluZGV4XX1cImA7XG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSh7XG4gICAgICBwcm92aWRlcjogYXdzUHJvdmlkZXJTY2hlbWEsXG4gICAgICBkYXRhOiBbXCJhd3NfYXZhaWxhYmlsaXR5X3pvbmVzXCJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5sb29rdXBOZXN0ZWQoYXZhaWxhYmxlLm5hbWVzLCBbXCJcXCR7Y291bnQuaW5kZXh9XCJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImFjY2VwdCBlc2NhcGVkIHF1b3RlcyB3aXRoaW4gc3RyaW5nXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gYFwiXFwke2pzb25lbmNvZGUoe1xuICAgICAgICAgIFwiU3RhdGVtZW50XCIgPSBbe1xuICAgICAgICAgICAgXCJBY3Rpb25cIiA9IFwiczM6KlwiLFxuICAgICAgICAgICAgXCJFZmZlY3RcIiA9IFwiQWxsb3dcIixcbiAgICAgICAgICB9XSxcbiAgICAgICAgfSl9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG4gICAgZXhwZWN0KGNvZGUocmVzdWx0KSkudG9NYXRjaElubGluZVNuYXBzaG90KGBcbiAgICAgIFwiVG9rZW4uYXNTdHJpbmcoRm4uanNvbmVuY29kZSh7XG4gICAgICAgIFwiU3RhdGVtZW50XCI6IFt7XG4gICAgICAgICAgXCJBY3Rpb25cIjogXCJzMzoqXCIsXG4gICAgICAgICAgXCJFZmZlY3RcIjogXCJBbGxvd1wiXG4gICAgICAgIH1dXG4gICAgICB9KSlcIlxuICAgIGApO1xuICB9KTtcblxuICB0ZXN0KFwic3VwcG9ydCB2YXJpYWRpYyBwYXJhbWV0ZXJzIGluIGFueSBwb3NpdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZXhwcmVzc2lvbiA9IGBcIlxcJHtjaWRyc3VibmV0cyhcImZkMDA6ZmQxMjozNDU2Ojc4OTA6Oi81NlwiLCAxNiwgMTYsIDE2LCAzMil9XCJgO1xuICAgIGNvbnN0IHNjb3BlID0gZ2V0U2NvcGUoKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb252ZXJ0VGVycmFmb3JtRXhwcmVzc2lvblRvVHMoXG4gICAgICBzY29wZSxcbiAgICAgIGV4cHJlc3Npb24sXG4gICAgICBnZXRUeXBlLFxuICAgICk7XG5cbiAgICBleHBlY3QoY29kZShyZXN1bHQpKS50b01hdGNoSW5saW5lU25hcHNob3QoXG4gICAgICBgXCJUb2tlbi5hc1N0cmluZyhGbi5jaWRyc3VibmV0cyhcImZkMDA6ZmQxMjozNDU2Ojc4OTA6Oi81NlwiLCBbMTYsIDE2LCAxNiwgMzJdKSlcImAsXG4gICAgKTtcbiAgfSk7XG5cbiAgdGVzdChcImNvbnZlcnRzIHRlbXBsYXRlIGV4cHJlc3Npb24gd2l0aCBlc2NhcGVkICR7fSBleHByZXNzaW9uXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBleHByZXNzaW9uID0gJ1tcIiQke3BhdGg6bmFtZS5naXZlbk5hbWV9XCJdJzsgLy8gZnJvbSBhd3Nfc3NvYWRtaW5faW5zdGFuY2VfYWNjZXNzX2NvbnRyb2xfYXR0cmlidXRlcyBleGFtcGxlXG4gICAgY29uc3Qgc2NvcGUgPSBnZXRTY29wZSgpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNvbnZlcnRUZXJyYWZvcm1FeHByZXNzaW9uVG9UcyhcbiAgICAgIHNjb3BlLFxuICAgICAgZXhwcmVzc2lvbixcbiAgICAgIGdldFR5cGUsXG4gICAgKTtcblxuICAgIGV4cGVjdChjb2RlKHJlc3VsdCkpLnRvTWF0Y2hJbmxpbmVTbmFwc2hvdChcbiAgICAgIGBcIltcIiRcXCR7cGF0aDpuYW1lLmdpdmVuTmFtZX1cIl1cImAsXG4gICAgKTtcbiAgfSk7XG59KTtcbiJdfQ==