@cdklabs/cdk-appmod-catalog-blueprints 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.jsii +2579 -194
  2. package/lib/document-processing/adapter/adapter.d.ts +4 -2
  3. package/lib/document-processing/adapter/adapter.js +1 -1
  4. package/lib/document-processing/adapter/queued-s3-adapter.d.ts +9 -2
  5. package/lib/document-processing/adapter/queued-s3-adapter.js +29 -15
  6. package/lib/document-processing/agentic-document-processing.d.ts +4 -0
  7. package/lib/document-processing/agentic-document-processing.js +20 -10
  8. package/lib/document-processing/base-document-processing.d.ts +54 -2
  9. package/lib/document-processing/base-document-processing.js +136 -82
  10. package/lib/document-processing/bedrock-document-processing.d.ts +202 -2
  11. package/lib/document-processing/bedrock-document-processing.js +717 -77
  12. package/lib/document-processing/chunking-config.d.ts +614 -0
  13. package/lib/document-processing/chunking-config.js +5 -0
  14. package/lib/document-processing/default-document-processing-config.js +1 -1
  15. package/lib/document-processing/index.d.ts +1 -0
  16. package/lib/document-processing/index.js +2 -1
  17. package/lib/document-processing/resources/aggregation/handler.py +567 -0
  18. package/lib/document-processing/resources/aggregation/requirements.txt +7 -0
  19. package/lib/document-processing/resources/aggregation/test_handler.py +362 -0
  20. package/lib/document-processing/resources/cleanup/handler.py +276 -0
  21. package/lib/document-processing/resources/cleanup/requirements.txt +5 -0
  22. package/lib/document-processing/resources/cleanup/test_handler.py +436 -0
  23. package/lib/document-processing/resources/default-bedrock-invoke/index.py +85 -3
  24. package/lib/document-processing/resources/default-bedrock-invoke/test_index.py +622 -0
  25. package/lib/document-processing/resources/pdf-chunking/README.md +313 -0
  26. package/lib/document-processing/resources/pdf-chunking/chunking_strategies.py +460 -0
  27. package/lib/document-processing/resources/pdf-chunking/error_handling.py +491 -0
  28. package/lib/document-processing/resources/pdf-chunking/handler.py +958 -0
  29. package/lib/document-processing/resources/pdf-chunking/metrics.py +435 -0
  30. package/lib/document-processing/resources/pdf-chunking/requirements.txt +3 -0
  31. package/lib/document-processing/resources/pdf-chunking/strategy_selection.py +420 -0
  32. package/lib/document-processing/resources/pdf-chunking/structured_logging.py +457 -0
  33. package/lib/document-processing/resources/pdf-chunking/test_chunking_strategies.py +353 -0
  34. package/lib/document-processing/resources/pdf-chunking/test_error_handling.py +487 -0
  35. package/lib/document-processing/resources/pdf-chunking/test_handler.py +609 -0
  36. package/lib/document-processing/resources/pdf-chunking/test_integration.py +694 -0
  37. package/lib/document-processing/resources/pdf-chunking/test_metrics.py +532 -0
  38. package/lib/document-processing/resources/pdf-chunking/test_strategy_selection.py +471 -0
  39. package/lib/document-processing/resources/pdf-chunking/test_structured_logging.py +449 -0
  40. package/lib/document-processing/resources/pdf-chunking/test_token_estimation.py +374 -0
  41. package/lib/document-processing/resources/pdf-chunking/token_estimation.py +189 -0
  42. package/lib/document-processing/tests/agentic-document-processing-nag.test.js +4 -3
  43. package/lib/document-processing/tests/agentic-document-processing.test.js +488 -4
  44. package/lib/document-processing/tests/base-document-processing-nag.test.js +9 -2
  45. package/lib/document-processing/tests/base-document-processing-schema.test.d.ts +1 -0
  46. package/lib/document-processing/tests/base-document-processing-schema.test.js +337 -0
  47. package/lib/document-processing/tests/base-document-processing.test.js +114 -8
  48. package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.d.ts +1 -0
  49. package/lib/document-processing/tests/bedrock-document-processing-chunking-nag.test.js +382 -0
  50. package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +4 -3
  51. package/lib/document-processing/tests/bedrock-document-processing-security.test.d.ts +1 -0
  52. package/lib/document-processing/tests/bedrock-document-processing-security.test.js +389 -0
  53. package/lib/document-processing/tests/bedrock-document-processing.test.js +808 -8
  54. package/lib/document-processing/tests/chunking-config.test.d.ts +1 -0
  55. package/lib/document-processing/tests/chunking-config.test.js +238 -0
  56. package/lib/document-processing/tests/queued-s3-adapter-nag.test.js +9 -2
  57. package/lib/document-processing/tests/queued-s3-adapter.test.js +17 -6
  58. package/lib/framework/agents/base-agent.js +1 -1
  59. package/lib/framework/agents/batch-agent.js +1 -1
  60. package/lib/framework/agents/default-agent-config.js +1 -1
  61. package/lib/framework/bedrock/bedrock.js +1 -1
  62. package/lib/framework/custom-resource/default-runtimes.js +1 -1
  63. package/lib/framework/foundation/access-log.js +1 -1
  64. package/lib/framework/foundation/eventbridge-broker.js +1 -1
  65. package/lib/framework/foundation/network.d.ts +4 -2
  66. package/lib/framework/foundation/network.js +52 -41
  67. package/lib/framework/tests/access-log.test.js +5 -2
  68. package/lib/framework/tests/batch-agent.test.js +5 -2
  69. package/lib/framework/tests/bedrock.test.js +5 -2
  70. package/lib/framework/tests/eventbridge-broker.test.js +5 -2
  71. package/lib/framework/tests/framework-nag.test.js +26 -7
  72. package/lib/framework/tests/network.test.js +30 -2
  73. package/lib/tsconfig.tsbuildinfo +1 -1
  74. package/lib/utilities/data-loader.js +1 -1
  75. package/lib/utilities/lambda-iam-utils.js +1 -1
  76. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +1 -1
  77. package/lib/utilities/observability/default-observability-config.js +1 -1
  78. package/lib/utilities/observability/lambda-observability-property-injector.js +1 -1
  79. package/lib/utilities/observability/log-group-data-protection-utils.js +1 -1
  80. package/lib/utilities/observability/powertools-config.d.ts +10 -1
  81. package/lib/utilities/observability/powertools-config.js +19 -3
  82. package/lib/utilities/observability/state-machine-observability-property-injector.js +1 -1
  83. package/lib/utilities/test-utils.d.ts +43 -0
  84. package/lib/utilities/test-utils.js +56 -0
  85. package/lib/utilities/tests/data-loader-nag.test.js +3 -2
  86. package/lib/utilities/tests/data-loader.test.js +3 -2
  87. package/lib/webapp/frontend-construct.js +1 -1
  88. package/lib/webapp/tests/frontend-construct-nag.test.js +3 -2
  89. package/lib/webapp/tests/frontend-construct.test.js +3 -2
  90. package/package.json +6 -5
  91. package/lib/document-processing/resources/default-error-handler/index.js +0 -46
  92. package/lib/document-processing/resources/default-pdf-processor/index.js +0 -46
  93. package/lib/document-processing/resources/default-pdf-validator/index.js +0 -36
@@ -5,8 +5,10 @@ const assertions_1 = require("aws-cdk-lib/assertions");
5
5
  const aws_bedrock_1 = require("aws-cdk-lib/aws-bedrock");
6
6
  const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
7
7
  const framework_1 = require("../../framework");
8
+ const test_utils_1 = require("../../utilities/test-utils");
8
9
  const bedrock_document_processing_1 = require("../bedrock-document-processing");
9
10
  describe('BedrockDocumentProcessing', () => {
11
+ let app;
10
12
  let defaultStack;
11
13
  let customStack;
12
14
  let crossRegionStack;
@@ -14,6 +16,7 @@ describe('BedrockDocumentProcessing', () => {
14
16
  let postProcessingStack;
15
17
  let customPromptsStack;
16
18
  let customTimeoutStack;
19
+ let chunkingStack;
17
20
  let defaultTemplate;
18
21
  let customTemplate;
19
22
  let crossRegionTemplate;
@@ -21,10 +24,13 @@ describe('BedrockDocumentProcessing', () => {
21
24
  let postProcessingTemplate;
22
25
  let customPromptsTemplate;
23
26
  let customTimeoutTemplate;
27
+ let chunkingTemplate;
24
28
  beforeAll(() => {
25
- defaultStack = new aws_cdk_lib_1.Stack();
29
+ // Use createTestApp() to skip bundling and speed up tests
30
+ app = (0, test_utils_1.createTestApp)();
31
+ defaultStack = new aws_cdk_lib_1.Stack(app, 'DefaultStack');
26
32
  new bedrock_document_processing_1.BedrockDocumentProcessing(defaultStack, 'DefaultTest', {});
27
- customStack = new aws_cdk_lib_1.Stack();
33
+ customStack = new aws_cdk_lib_1.Stack(app, 'CustomStack');
28
34
  new bedrock_document_processing_1.BedrockDocumentProcessing(customStack, 'CustomTest', {
29
35
  classificationBedrockModel: {
30
36
  fmModelId: aws_bedrock_1.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_HAIKU_20240307_V1_0,
@@ -35,14 +41,14 @@ describe('BedrockDocumentProcessing', () => {
35
41
  useCrossRegionInference: false,
36
42
  },
37
43
  });
38
- crossRegionStack = new aws_cdk_lib_1.Stack();
44
+ crossRegionStack = new aws_cdk_lib_1.Stack(app, 'CrossRegionStack');
39
45
  new bedrock_document_processing_1.BedrockDocumentProcessing(crossRegionStack, 'CrossRegionTest', {
40
46
  classificationBedrockModel: {
41
47
  useCrossRegionInference: true,
42
48
  crossRegionInferencePrefix: framework_1.BedrockCrossRegionInferencePrefix.EU,
43
49
  },
44
50
  });
45
- enrichmentStack = new aws_cdk_lib_1.Stack();
51
+ enrichmentStack = new aws_cdk_lib_1.Stack(app, 'EnrichmentStack');
46
52
  const enrichmentFn = new aws_lambda_1.Function(enrichmentStack, 'EnrichmentFn', {
47
53
  runtime: aws_lambda_1.Runtime.NODEJS_20_X,
48
54
  handler: 'index.handler',
@@ -51,7 +57,7 @@ describe('BedrockDocumentProcessing', () => {
51
57
  new bedrock_document_processing_1.BedrockDocumentProcessing(enrichmentStack, 'EnrichmentTest', {
52
58
  enrichmentLambdaFunction: enrichmentFn,
53
59
  });
54
- postProcessingStack = new aws_cdk_lib_1.Stack();
60
+ postProcessingStack = new aws_cdk_lib_1.Stack(app, 'PostProcessingStack');
55
61
  const postProcessingFn = new aws_lambda_1.Function(postProcessingStack, 'PostProcessingFn', {
56
62
  runtime: aws_lambda_1.Runtime.NODEJS_20_X,
57
63
  handler: 'index.handler',
@@ -60,15 +66,28 @@ describe('BedrockDocumentProcessing', () => {
60
66
  new bedrock_document_processing_1.BedrockDocumentProcessing(postProcessingStack, 'PostProcessingTest', {
61
67
  postProcessingLambdaFunction: postProcessingFn,
62
68
  });
63
- customPromptsStack = new aws_cdk_lib_1.Stack();
69
+ customPromptsStack = new aws_cdk_lib_1.Stack(app, 'CustomPromptsStack');
64
70
  new bedrock_document_processing_1.BedrockDocumentProcessing(customPromptsStack, 'CustomPromptsTest', {
65
71
  classificationPrompt: 'Custom classification prompt',
66
72
  processingPrompt: 'Custom processing prompt',
67
73
  });
68
- customTimeoutStack = new aws_cdk_lib_1.Stack();
74
+ customTimeoutStack = new aws_cdk_lib_1.Stack(app, 'CustomTimeoutStack');
69
75
  new bedrock_document_processing_1.BedrockDocumentProcessing(customTimeoutStack, 'CustomTimeoutTest', {
70
76
  stepTimeouts: aws_cdk_lib_1.Duration.minutes(10),
71
77
  });
78
+ chunkingStack = new aws_cdk_lib_1.Stack(app, 'ChunkingStack');
79
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'ChunkingTest', {
80
+ enableChunking: true,
81
+ chunkingConfig: {
82
+ strategy: 'hybrid',
83
+ maxPagesPerChunk: 100,
84
+ targetTokensPerChunk: 80000,
85
+ pageThreshold: 100,
86
+ tokenThreshold: 150000,
87
+ processingMode: 'parallel',
88
+ maxConcurrency: 10,
89
+ },
90
+ });
72
91
  defaultTemplate = assertions_1.Template.fromStack(defaultStack);
73
92
  customTemplate = assertions_1.Template.fromStack(customStack);
74
93
  crossRegionTemplate = assertions_1.Template.fromStack(crossRegionStack);
@@ -76,6 +95,7 @@ describe('BedrockDocumentProcessing', () => {
76
95
  postProcessingTemplate = assertions_1.Template.fromStack(postProcessingStack);
77
96
  customPromptsTemplate = assertions_1.Template.fromStack(customPromptsStack);
78
97
  customTimeoutTemplate = assertions_1.Template.fromStack(customTimeoutStack);
98
+ chunkingTemplate = assertions_1.Template.fromStack(chunkingStack);
79
99
  });
80
100
  describe('Basic infrastructure', () => {
81
101
  test('creates basic infrastructure', () => {
@@ -256,5 +276,785 @@ describe('BedrockDocumentProcessing', () => {
256
276
  });
257
277
  });
258
278
  });
279
+ describe('Chunking configuration', () => {
280
+ test('accepts enableChunking prop', () => {
281
+ // This test verifies that the BedrockDocumentProcessingProps interface
282
+ // correctly accepts the enableChunking boolean flag
283
+ expect(chunkingStack).toBeDefined();
284
+ });
285
+ test('accepts chunkingConfig prop with all strategy options', () => {
286
+ // This test verifies that the BedrockDocumentProcessingProps interface
287
+ // correctly accepts the chunkingConfig with all configuration options
288
+ chunkingTemplate.hasResourceProperties('AWS::S3::Bucket', {});
289
+ chunkingTemplate.hasResourceProperties('AWS::SQS::Queue', {});
290
+ chunkingTemplate.hasResourceProperties('AWS::DynamoDB::Table', { BillingMode: 'PAY_PER_REQUEST' });
291
+ });
292
+ test('accepts fixed-pages strategy configuration', () => {
293
+ const testApp = (0, test_utils_1.createTestApp)();
294
+ const fixedPagesStack = new aws_cdk_lib_1.Stack(testApp, 'FixedPagesStack');
295
+ new bedrock_document_processing_1.BedrockDocumentProcessing(fixedPagesStack, 'FixedPagesTest', {
296
+ enableChunking: true,
297
+ chunkingConfig: {
298
+ strategy: 'fixed-pages',
299
+ pageThreshold: 100,
300
+ chunkSize: 50,
301
+ overlapPages: 5,
302
+ },
303
+ });
304
+ // Verify stack is created successfully
305
+ expect(fixedPagesStack).toBeDefined();
306
+ });
307
+ test('accepts token-based strategy configuration', () => {
308
+ const testApp = (0, test_utils_1.createTestApp)();
309
+ const tokenBasedStack = new aws_cdk_lib_1.Stack(testApp, 'TokenBasedStack');
310
+ new bedrock_document_processing_1.BedrockDocumentProcessing(tokenBasedStack, 'TokenBasedTest', {
311
+ enableChunking: true,
312
+ chunkingConfig: {
313
+ strategy: 'token-based',
314
+ tokenThreshold: 150000,
315
+ maxTokensPerChunk: 100000,
316
+ overlapTokens: 5000,
317
+ },
318
+ });
319
+ // Verify stack is created successfully
320
+ expect(tokenBasedStack).toBeDefined();
321
+ });
322
+ test('accepts hybrid strategy configuration', () => {
323
+ const testApp = (0, test_utils_1.createTestApp)();
324
+ const hybridStack = new aws_cdk_lib_1.Stack(testApp, 'HybridStack');
325
+ new bedrock_document_processing_1.BedrockDocumentProcessing(hybridStack, 'HybridTest', {
326
+ enableChunking: true,
327
+ chunkingConfig: {
328
+ strategy: 'hybrid',
329
+ maxPagesPerChunk: 100,
330
+ targetTokensPerChunk: 80000,
331
+ pageThreshold: 100,
332
+ tokenThreshold: 150000,
333
+ overlapTokens: 5000,
334
+ },
335
+ });
336
+ // Verify stack is created successfully
337
+ expect(hybridStack).toBeDefined();
338
+ });
339
+ test('accepts default chunking configuration', () => {
340
+ const testApp = (0, test_utils_1.createTestApp)();
341
+ const defaultChunkingStack = new aws_cdk_lib_1.Stack(testApp, 'DefaultChunkingStack');
342
+ new bedrock_document_processing_1.BedrockDocumentProcessing(defaultChunkingStack, 'DefaultChunkingTest', {
343
+ enableChunking: true,
344
+ });
345
+ // Verify stack is created successfully with default config
346
+ expect(defaultChunkingStack).toBeDefined();
347
+ });
348
+ test('does not enable chunking when enableChunking is false', () => {
349
+ // Verify that the default stack (without chunking) works as expected
350
+ expect(defaultStack).toBeDefined();
351
+ defaultTemplate.hasResourceProperties('AWS::S3::Bucket', {});
352
+ defaultTemplate.hasResourceProperties('AWS::SQS::Queue', {});
353
+ });
354
+ });
355
+ describe('Workflow branching for chunking', () => {
356
+ test('creates state machine with chunking workflow', () => {
357
+ // Verify that a state machine is created when chunking is enabled
358
+ chunkingTemplate.resourceCountIs('AWS::StepFunctions::StateMachine', 1);
359
+ // Verify the state machine has the expected configuration
360
+ chunkingTemplate.hasResourceProperties('AWS::StepFunctions::StateMachine', {
361
+ EncryptionConfiguration: assertions_1.Match.objectLike({
362
+ Type: 'CUSTOMER_MANAGED_KMS_KEY',
363
+ }),
364
+ });
365
+ });
366
+ test('standard workflow is used when chunking is disabled', () => {
367
+ // Verify that when enableChunking is false, the standard workflow is used
368
+ const testApp = (0, test_utils_1.createTestApp)();
369
+ const noChunkingStack = new aws_cdk_lib_1.Stack(testApp, 'NoChunkingStack');
370
+ new bedrock_document_processing_1.BedrockDocumentProcessing(noChunkingStack, 'NoChunkingTest', {
371
+ enableChunking: false,
372
+ });
373
+ const noChunkingTemplate = assertions_1.Template.fromStack(noChunkingStack);
374
+ // Should have state machine
375
+ noChunkingTemplate.resourceCountIs('AWS::StepFunctions::StateMachine', 1);
376
+ // Should NOT have PDF chunking Lambda (Python 3.13 with 2048 MB)
377
+ const lambdas = noChunkingTemplate.findResources('AWS::Lambda::Function');
378
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
379
+ lambda.Properties.MemorySize === 2048);
380
+ expect(chunkingLambda).toBeUndefined();
381
+ });
382
+ test('creates PDF chunking Lambda when chunking is enabled', () => {
383
+ // Verify that the PDF chunking Lambda is created
384
+ const lambdas = chunkingTemplate.findResources('AWS::Lambda::Function');
385
+ // Find the chunking Lambda by its characteristics (Python 3.13, 2048 MB memory)
386
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
387
+ lambda.Properties.MemorySize === 2048 &&
388
+ lambda.Properties.Timeout === 600);
389
+ expect(chunkingLambda).toBeDefined();
390
+ expect(chunkingLambda).toHaveProperty('Properties.Handler', 'handler.handler');
391
+ });
392
+ test('PDF chunking Lambda has correct environment variables for hybrid strategy', () => {
393
+ // Verify chunking configuration is passed via environment variables
394
+ // Find the chunking Lambda specifically
395
+ const lambdas = chunkingTemplate.findResources('AWS::Lambda::Function');
396
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
397
+ lambda.Properties.MemorySize === 2048);
398
+ expect(chunkingLambda).toBeDefined();
399
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNKING_STRATEGY', 'hybrid');
400
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.MAX_PAGES_PER_CHUNK', '100');
401
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TARGET_TOKENS_PER_CHUNK', '80000');
402
+ });
403
+ test('PDF chunking Lambda has S3 access permissions', () => {
404
+ // Verify that the chunking Lambda has S3 permissions
405
+ chunkingTemplate.hasResourceProperties('AWS::IAM::Role', {
406
+ Policies: assertions_1.Match.arrayWith([
407
+ assertions_1.Match.objectLike({
408
+ PolicyDocument: assertions_1.Match.objectLike({
409
+ Statement: assertions_1.Match.arrayWith([
410
+ assertions_1.Match.objectLike({
411
+ Action: assertions_1.Match.arrayWith([
412
+ 's3:GetObject',
413
+ 's3:PutObject',
414
+ ]),
415
+ }),
416
+ ]),
417
+ }),
418
+ }),
419
+ ]),
420
+ });
421
+ });
422
+ test('state machine can invoke PDF chunking Lambda', () => {
423
+ // Verify that the state machine role has permission to invoke the chunking Lambda
424
+ chunkingTemplate.hasResourceProperties('AWS::IAM::Policy', {
425
+ PolicyDocument: assertions_1.Match.objectLike({
426
+ Statement: assertions_1.Match.arrayWith([
427
+ assertions_1.Match.objectLike({
428
+ Action: 'lambda:InvokeFunction',
429
+ Effect: 'Allow',
430
+ }),
431
+ ]),
432
+ }),
433
+ });
434
+ });
435
+ });
436
+ });
437
+ describe('Chunk-aware classification integration', () => {
438
+ describe('Classification Lambda chunk context', () => {
439
+ test('classification Lambda receives chunk metadata in Map State', () => {
440
+ // Verify that the Map State passes chunk metadata to the classification Lambda
441
+ const testApp = (0, test_utils_1.createTestApp)();
442
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'ChunkContextStack');
443
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'ChunkContextTest', {
444
+ enableChunking: true,
445
+ chunkingConfig: {
446
+ strategy: 'hybrid',
447
+ maxPagesPerChunk: 100,
448
+ targetTokensPerChunk: 80000,
449
+ },
450
+ });
451
+ const template = assertions_1.Template.fromStack(chunkingStack);
452
+ // Verify state machine is created with Map State
453
+ template.hasResourceProperties('AWS::StepFunctions::StateMachine', {
454
+ DefinitionString: assertions_1.Match.objectLike({
455
+ 'Fn::Join': assertions_1.Match.arrayWith(['']),
456
+ }),
457
+ });
458
+ // Verify the state machine definition includes Map state with chunk parameters
459
+ const stateMachines = template.findResources('AWS::StepFunctions::StateMachine');
460
+ const stateMachineDefinition = Object.values(stateMachines)[0];
461
+ expect(stateMachineDefinition).toBeDefined();
462
+ });
463
+ test('non-chunked workflow does not include chunk context', () => {
464
+ // Verify that when chunking is disabled, no chunk context is added
465
+ const testApp = (0, test_utils_1.createTestApp)();
466
+ const noChunkingStack = new aws_cdk_lib_1.Stack(testApp, 'NoChunkContextStack');
467
+ new bedrock_document_processing_1.BedrockDocumentProcessing(noChunkingStack, 'NoChunkContextTest', {
468
+ enableChunking: false,
469
+ });
470
+ const template = assertions_1.Template.fromStack(noChunkingStack);
471
+ // Should have state machine
472
+ template.resourceCountIs('AWS::StepFunctions::StateMachine', 1);
473
+ // Should NOT have PDF chunking Lambda
474
+ const lambdas = template.findResources('AWS::Lambda::Function');
475
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
476
+ lambda.Properties.MemorySize === 2048);
477
+ expect(chunkingLambda).toBeUndefined();
478
+ });
479
+ test('chunked workflow includes Map State for parallel chunk processing', () => {
480
+ const testApp = (0, test_utils_1.createTestApp)();
481
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'MapStateStack');
482
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'MapStateTest', {
483
+ enableChunking: true,
484
+ chunkingConfig: {
485
+ strategy: 'hybrid',
486
+ processingMode: 'parallel',
487
+ maxConcurrency: 5,
488
+ },
489
+ });
490
+ const template = assertions_1.Template.fromStack(chunkingStack);
491
+ // Verify state machine is created
492
+ template.resourceCountIs('AWS::StepFunctions::StateMachine', 1);
493
+ // Verify classification Lambda exists
494
+ template.hasResourceProperties('AWS::Lambda::Function', {
495
+ Environment: {
496
+ Variables: {
497
+ INVOKE_TYPE: 'classification',
498
+ },
499
+ },
500
+ });
501
+ });
502
+ test('classification Lambda is reused for both chunked and non-chunked paths', () => {
503
+ const testApp = (0, test_utils_1.createTestApp)();
504
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'ReuseStack');
505
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'ReuseTest', {
506
+ enableChunking: true,
507
+ });
508
+ const template = assertions_1.Template.fromStack(chunkingStack);
509
+ // Count classification Lambdas (should be 1, reused for both paths)
510
+ const lambdas = template.findResources('AWS::Lambda::Function');
511
+ const classificationLambdas = Object.values(lambdas).filter((lambda) => lambda.Properties.Environment?.Variables?.INVOKE_TYPE === 'classification');
512
+ // Should have exactly 1 classification Lambda (reused)
513
+ expect(classificationLambdas.length).toBe(1);
514
+ });
515
+ test('workflow maintains backward compatibility for small documents', () => {
516
+ // When chunking is enabled but document is small, it should use standard workflow
517
+ const testApp = (0, test_utils_1.createTestApp)();
518
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'BackwardCompatStack');
519
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'BackwardCompatTest', {
520
+ enableChunking: true,
521
+ chunkingConfig: {
522
+ strategy: 'hybrid',
523
+ pageThreshold: 100,
524
+ tokenThreshold: 150000,
525
+ },
526
+ });
527
+ const template = assertions_1.Template.fromStack(chunkingStack);
528
+ // Verify both classification and processing Lambdas exist
529
+ template.hasResourceProperties('AWS::Lambda::Function', {
530
+ Environment: {
531
+ Variables: {
532
+ INVOKE_TYPE: 'classification',
533
+ },
534
+ },
535
+ });
536
+ template.hasResourceProperties('AWS::Lambda::Function', {
537
+ Environment: {
538
+ Variables: {
539
+ INVOKE_TYPE: 'processing',
540
+ },
541
+ },
542
+ });
543
+ // Verify state machine has Choice state for branching
544
+ template.resourceCountIs('AWS::StepFunctions::StateMachine', 1);
545
+ });
546
+ });
547
+ describe('Accuracy comparison between chunked and non-chunked', () => {
548
+ test('both workflows use same classification Lambda function', () => {
549
+ // This ensures accuracy is maintained because the same model and prompt are used
550
+ const testApp = (0, test_utils_1.createTestApp)();
551
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'AccuracyStack');
552
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'AccuracyTest', {
553
+ enableChunking: true,
554
+ classificationBedrockModel: {
555
+ fmModelId: aws_bedrock_1.FoundationModelIdentifier.ANTHROPIC_CLAUDE_3_HAIKU_20240307_V1_0,
556
+ useCrossRegionInference: false,
557
+ },
558
+ });
559
+ const template = assertions_1.Template.fromStack(chunkingStack);
560
+ // Verify the classification Lambda uses the specified model
561
+ template.hasResourceProperties('AWS::Lambda::Function', {
562
+ Environment: {
563
+ Variables: {
564
+ MODEL_ID: 'anthropic.claude-3-haiku-20240307-v1:0',
565
+ INVOKE_TYPE: 'classification',
566
+ },
567
+ },
568
+ });
569
+ });
570
+ test('custom classification prompt is used for both chunked and non-chunked', () => {
571
+ const customPrompt = 'Custom classification prompt for testing';
572
+ const testApp = (0, test_utils_1.createTestApp)();
573
+ const chunkingStack = new aws_cdk_lib_1.Stack(testApp, 'CustomPromptStack');
574
+ new bedrock_document_processing_1.BedrockDocumentProcessing(chunkingStack, 'CustomPromptTest', {
575
+ enableChunking: true,
576
+ classificationPrompt: customPrompt,
577
+ });
578
+ const template = assertions_1.Template.fromStack(chunkingStack);
579
+ // Verify the custom prompt is set
580
+ template.hasResourceProperties('AWS::Lambda::Function', {
581
+ Environment: {
582
+ Variables: {
583
+ PROMPT: customPrompt,
584
+ INVOKE_TYPE: 'classification',
585
+ },
586
+ },
587
+ });
588
+ });
589
+ });
590
+ });
591
+ describe('Configuration validation', () => {
592
+ describe('Invalid configuration rejection', () => {
593
+ test('throws error for chunkSize <= 0', () => {
594
+ const testApp = (0, test_utils_1.createTestApp)();
595
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidChunkSizeStack');
596
+ expect(() => {
597
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidChunkSizeTest', {
598
+ enableChunking: true,
599
+ chunkingConfig: {
600
+ strategy: 'fixed-pages',
601
+ chunkSize: 0,
602
+ },
603
+ });
604
+ }).toThrow('ChunkingConfig validation error: chunkSize must be greater than 0');
605
+ });
606
+ test('throws error for negative chunkSize', () => {
607
+ const testApp = (0, test_utils_1.createTestApp)();
608
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'NegativeChunkSizeStack');
609
+ expect(() => {
610
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'NegativeChunkSizeTest', {
611
+ enableChunking: true,
612
+ chunkingConfig: {
613
+ strategy: 'fixed-pages',
614
+ chunkSize: -10,
615
+ },
616
+ });
617
+ }).toThrow('ChunkingConfig validation error: chunkSize must be greater than 0');
618
+ });
619
+ test('throws error for negative overlapPages', () => {
620
+ const testApp = (0, test_utils_1.createTestApp)();
621
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'NegativeOverlapStack');
622
+ expect(() => {
623
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'NegativeOverlapTest', {
624
+ enableChunking: true,
625
+ chunkingConfig: {
626
+ strategy: 'fixed-pages',
627
+ chunkSize: 50,
628
+ overlapPages: -5,
629
+ },
630
+ });
631
+ }).toThrow('ChunkingConfig validation error: overlapPages must be non-negative');
632
+ });
633
+ test('throws error for overlapPages >= chunkSize', () => {
634
+ const testApp = (0, test_utils_1.createTestApp)();
635
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'OverlapTooLargeStack');
636
+ expect(() => {
637
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'OverlapTooLargeTest', {
638
+ enableChunking: true,
639
+ chunkingConfig: {
640
+ strategy: 'fixed-pages',
641
+ chunkSize: 50,
642
+ overlapPages: 50,
643
+ },
644
+ });
645
+ }).toThrow('ChunkingConfig validation error: overlapPages must be less than chunkSize');
646
+ });
647
+ test('throws error for pageThreshold <= 0', () => {
648
+ const testApp = (0, test_utils_1.createTestApp)();
649
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidPageThresholdStack');
650
+ expect(() => {
651
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidPageThresholdTest', {
652
+ enableChunking: true,
653
+ chunkingConfig: {
654
+ strategy: 'fixed-pages',
655
+ pageThreshold: 0,
656
+ },
657
+ });
658
+ }).toThrow('ChunkingConfig validation error: pageThreshold must be greater than 0');
659
+ });
660
+ test('throws error for tokenThreshold <= 0', () => {
661
+ const testApp = (0, test_utils_1.createTestApp)();
662
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidTokenThresholdStack');
663
+ expect(() => {
664
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidTokenThresholdTest', {
665
+ enableChunking: true,
666
+ chunkingConfig: {
667
+ strategy: 'token-based',
668
+ tokenThreshold: -100,
669
+ },
670
+ });
671
+ }).toThrow('ChunkingConfig validation error: tokenThreshold must be greater than 0');
672
+ });
673
+ test('throws error for maxTokensPerChunk <= 0', () => {
674
+ const testApp = (0, test_utils_1.createTestApp)();
675
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidMaxTokensStack');
676
+ expect(() => {
677
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidMaxTokensTest', {
678
+ enableChunking: true,
679
+ chunkingConfig: {
680
+ strategy: 'token-based',
681
+ maxTokensPerChunk: 0,
682
+ },
683
+ });
684
+ }).toThrow('ChunkingConfig validation error: maxTokensPerChunk must be greater than 0');
685
+ });
686
+ test('throws error for negative overlapTokens', () => {
687
+ const testApp = (0, test_utils_1.createTestApp)();
688
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'NegativeOverlapTokensStack');
689
+ expect(() => {
690
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'NegativeOverlapTokensTest', {
691
+ enableChunking: true,
692
+ chunkingConfig: {
693
+ strategy: 'token-based',
694
+ overlapTokens: -1000,
695
+ },
696
+ });
697
+ }).toThrow('ChunkingConfig validation error: overlapTokens must be non-negative');
698
+ });
699
+ test('throws error for overlapTokens >= maxTokensPerChunk', () => {
700
+ const testApp = (0, test_utils_1.createTestApp)();
701
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'OverlapTokensTooLargeStack');
702
+ expect(() => {
703
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'OverlapTokensTooLargeTest', {
704
+ enableChunking: true,
705
+ chunkingConfig: {
706
+ strategy: 'token-based',
707
+ maxTokensPerChunk: 50000,
708
+ overlapTokens: 50000,
709
+ },
710
+ });
711
+ }).toThrow('ChunkingConfig validation error: overlapTokens must be less than maxTokensPerChunk');
712
+ });
713
+ test('throws error for maxPagesPerChunk <= 0', () => {
714
+ const testApp = (0, test_utils_1.createTestApp)();
715
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidMaxPagesStack');
716
+ expect(() => {
717
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidMaxPagesTest', {
718
+ enableChunking: true,
719
+ chunkingConfig: {
720
+ strategy: 'hybrid',
721
+ maxPagesPerChunk: 0,
722
+ },
723
+ });
724
+ }).toThrow('ChunkingConfig validation error: maxPagesPerChunk must be greater than 0');
725
+ });
726
+ test('throws error for targetTokensPerChunk <= 0', () => {
727
+ const testApp = (0, test_utils_1.createTestApp)();
728
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidTargetTokensStack');
729
+ expect(() => {
730
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidTargetTokensTest', {
731
+ enableChunking: true,
732
+ chunkingConfig: {
733
+ strategy: 'hybrid',
734
+ targetTokensPerChunk: -1,
735
+ },
736
+ });
737
+ }).toThrow('ChunkingConfig validation error: targetTokensPerChunk must be greater than 0');
738
+ });
739
+ test('throws error for maxConcurrency <= 0', () => {
740
+ const testApp = (0, test_utils_1.createTestApp)();
741
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidMaxConcurrencyStack');
742
+ expect(() => {
743
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidMaxConcurrencyTest', {
744
+ enableChunking: true,
745
+ chunkingConfig: {
746
+ maxConcurrency: 0,
747
+ },
748
+ });
749
+ }).toThrow('ChunkingConfig validation error: maxConcurrency must be greater than 0');
750
+ });
751
+ test('throws error for minSuccessThreshold < 0', () => {
752
+ const testApp = (0, test_utils_1.createTestApp)();
753
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidMinThresholdLowStack');
754
+ expect(() => {
755
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidMinThresholdLowTest', {
756
+ enableChunking: true,
757
+ chunkingConfig: {
758
+ minSuccessThreshold: -0.1,
759
+ },
760
+ });
761
+ }).toThrow('ChunkingConfig validation error: minSuccessThreshold must be between 0 and 1');
762
+ });
763
+ test('throws error for minSuccessThreshold > 1', () => {
764
+ const testApp = (0, test_utils_1.createTestApp)();
765
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'InvalidMinThresholdHighStack');
766
+ expect(() => {
767
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'InvalidMinThresholdHighTest', {
768
+ enableChunking: true,
769
+ chunkingConfig: {
770
+ minSuccessThreshold: 1.5,
771
+ },
772
+ });
773
+ }).toThrow('ChunkingConfig validation error: minSuccessThreshold must be between 0 and 1');
774
+ });
775
+ });
776
+ describe('Valid configuration acceptance', () => {
777
+ test('accepts valid boundary values', () => {
778
+ const testApp = (0, test_utils_1.createTestApp)();
779
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'ValidBoundaryStack');
780
+ // Should not throw
781
+ expect(() => {
782
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'ValidBoundaryTest', {
783
+ enableChunking: true,
784
+ chunkingConfig: {
785
+ strategy: 'fixed-pages',
786
+ chunkSize: 1, // minimum valid
787
+ overlapPages: 0, // minimum valid
788
+ pageThreshold: 1, // minimum valid
789
+ },
790
+ });
791
+ }).not.toThrow();
792
+ });
793
+ test('accepts minSuccessThreshold at boundaries', () => {
794
+ const testApp = (0, test_utils_1.createTestApp)();
795
+ const stack1 = new aws_cdk_lib_1.Stack(testApp, 'MinThreshold0Stack');
796
+ const stack2 = new aws_cdk_lib_1.Stack(testApp, 'MinThreshold1Stack');
797
+ // Should not throw for 0
798
+ expect(() => {
799
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack1, 'MinThreshold0Test', {
800
+ enableChunking: true,
801
+ chunkingConfig: {
802
+ minSuccessThreshold: 0,
803
+ },
804
+ });
805
+ }).not.toThrow();
806
+ // Should not throw for 1
807
+ expect(() => {
808
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack2, 'MinThreshold1Test', {
809
+ enableChunking: true,
810
+ chunkingConfig: {
811
+ minSuccessThreshold: 1,
812
+ },
813
+ });
814
+ }).not.toThrow();
815
+ });
816
+ });
817
+ describe('Validation skipped when chunking disabled', () => {
818
+ test('does not validate config when enableChunking is false', () => {
819
+ const testApp = (0, test_utils_1.createTestApp)();
820
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'ChunkingDisabledStack');
821
+ // Should not throw even with invalid config because chunking is disabled
822
+ expect(() => {
823
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'ChunkingDisabledTest', {
824
+ enableChunking: false,
825
+ chunkingConfig: {
826
+ chunkSize: -10, // Invalid but should be ignored
827
+ },
828
+ });
829
+ }).not.toThrow();
830
+ });
831
+ test('does not validate config when enableChunking is undefined', () => {
832
+ const testApp = (0, test_utils_1.createTestApp)();
833
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'ChunkingUndefinedStack');
834
+ // Should not throw even with invalid config because chunking is not enabled
835
+ expect(() => {
836
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'ChunkingUndefinedTest', {
837
+ chunkingConfig: {
838
+ chunkSize: 0, // Invalid but should be ignored
839
+ },
840
+ });
841
+ }).not.toThrow();
842
+ });
843
+ });
844
+ });
845
+ describe('Configuration precedence', () => {
846
+ describe('Default values applied', () => {
847
+ test('uses default strategy when not specified', () => {
848
+ const testApp = (0, test_utils_1.createTestApp)();
849
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'DefaultStrategyStack');
850
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'DefaultStrategyTest', {
851
+ enableChunking: true,
852
+ chunkingConfig: {}, // Empty config, should use defaults
853
+ });
854
+ const template = assertions_1.Template.fromStack(stack);
855
+ const lambdas = template.findResources('AWS::Lambda::Function');
856
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
857
+ lambda.Properties.MemorySize === 2048);
858
+ expect(chunkingLambda).toBeDefined();
859
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNKING_STRATEGY', 'hybrid');
860
+ });
861
+ test('uses default pageThreshold when not specified', () => {
862
+ const testApp = (0, test_utils_1.createTestApp)();
863
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'DefaultPageThresholdStack');
864
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'DefaultPageThresholdTest', {
865
+ enableChunking: true,
866
+ chunkingConfig: {
867
+ strategy: 'fixed-pages',
868
+ },
869
+ });
870
+ const template = assertions_1.Template.fromStack(stack);
871
+ const lambdas = template.findResources('AWS::Lambda::Function');
872
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
873
+ lambda.Properties.MemorySize === 2048);
874
+ expect(chunkingLambda).toBeDefined();
875
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.PAGE_THRESHOLD', '100');
876
+ });
877
+ test('uses default tokenThreshold when not specified', () => {
878
+ const testApp = (0, test_utils_1.createTestApp)();
879
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'DefaultTokenThresholdStack');
880
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'DefaultTokenThresholdTest', {
881
+ enableChunking: true,
882
+ chunkingConfig: {
883
+ strategy: 'token-based',
884
+ },
885
+ });
886
+ const template = assertions_1.Template.fromStack(stack);
887
+ const lambdas = template.findResources('AWS::Lambda::Function');
888
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
889
+ lambda.Properties.MemorySize === 2048);
890
+ expect(chunkingLambda).toBeDefined();
891
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TOKEN_THRESHOLD', '150000');
892
+ });
893
+ test('uses default maxConcurrency when not specified', () => {
894
+ const testApp = (0, test_utils_1.createTestApp)();
895
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'DefaultConcurrencyStack');
896
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'DefaultConcurrencyTest', {
897
+ enableChunking: true,
898
+ chunkingConfig: {
899
+ processingMode: 'parallel',
900
+ },
901
+ });
902
+ // Verify stack is created successfully with default maxConcurrency of 10
903
+ expect(stack).toBeDefined();
904
+ });
905
+ });
906
+ describe('Custom configuration overrides defaults', () => {
907
+ test('custom strategy overrides default', () => {
908
+ const testApp = (0, test_utils_1.createTestApp)();
909
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomStrategyStack');
910
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomStrategyTest', {
911
+ enableChunking: true,
912
+ chunkingConfig: {
913
+ strategy: 'token-based',
914
+ },
915
+ });
916
+ const template = assertions_1.Template.fromStack(stack);
917
+ const lambdas = template.findResources('AWS::Lambda::Function');
918
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
919
+ lambda.Properties.MemorySize === 2048);
920
+ expect(chunkingLambda).toBeDefined();
921
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNKING_STRATEGY', 'token-based');
922
+ });
923
+ test('custom pageThreshold overrides default', () => {
924
+ const testApp = (0, test_utils_1.createTestApp)();
925
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomPageThresholdStack');
926
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomPageThresholdTest', {
927
+ enableChunking: true,
928
+ chunkingConfig: {
929
+ pageThreshold: 50,
930
+ },
931
+ });
932
+ const template = assertions_1.Template.fromStack(stack);
933
+ const lambdas = template.findResources('AWS::Lambda::Function');
934
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
935
+ lambda.Properties.MemorySize === 2048);
936
+ expect(chunkingLambda).toBeDefined();
937
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.PAGE_THRESHOLD', '50');
938
+ });
939
+ test('custom tokenThreshold overrides default', () => {
940
+ const testApp = (0, test_utils_1.createTestApp)();
941
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomTokenThresholdStack');
942
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomTokenThresholdTest', {
943
+ enableChunking: true,
944
+ chunkingConfig: {
945
+ tokenThreshold: 200000,
946
+ },
947
+ });
948
+ const template = assertions_1.Template.fromStack(stack);
949
+ const lambdas = template.findResources('AWS::Lambda::Function');
950
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
951
+ lambda.Properties.MemorySize === 2048);
952
+ expect(chunkingLambda).toBeDefined();
953
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TOKEN_THRESHOLD', '200000');
954
+ });
955
+ test('custom chunkSize overrides default', () => {
956
+ const testApp = (0, test_utils_1.createTestApp)();
957
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomChunkSizeStack');
958
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomChunkSizeTest', {
959
+ enableChunking: true,
960
+ chunkingConfig: {
961
+ strategy: 'fixed-pages',
962
+ chunkSize: 25,
963
+ },
964
+ });
965
+ const template = assertions_1.Template.fromStack(stack);
966
+ const lambdas = template.findResources('AWS::Lambda::Function');
967
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
968
+ lambda.Properties.MemorySize === 2048);
969
+ expect(chunkingLambda).toBeDefined();
970
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNK_SIZE', '25');
971
+ });
972
+ test('custom maxPagesPerChunk overrides default', () => {
973
+ const testApp = (0, test_utils_1.createTestApp)();
974
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomMaxPagesStack');
975
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomMaxPagesTest', {
976
+ enableChunking: true,
977
+ chunkingConfig: {
978
+ strategy: 'hybrid',
979
+ maxPagesPerChunk: 75,
980
+ },
981
+ });
982
+ const template = assertions_1.Template.fromStack(stack);
983
+ const lambdas = template.findResources('AWS::Lambda::Function');
984
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
985
+ lambda.Properties.MemorySize === 2048);
986
+ expect(chunkingLambda).toBeDefined();
987
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.MAX_PAGES_PER_CHUNK', '75');
988
+ });
989
+ test('default maxPagesPerChunk is 99 to stay under Bedrock 100-page limit', () => {
990
+ const testApp = (0, test_utils_1.createTestApp)();
991
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'DefaultMaxPagesStack');
992
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'DefaultMaxPagesTest', {
993
+ enableChunking: true,
994
+ chunkingConfig: {
995
+ strategy: 'hybrid',
996
+ // maxPagesPerChunk not specified - should default to 99
997
+ },
998
+ });
999
+ const template = assertions_1.Template.fromStack(stack);
1000
+ const lambdas = template.findResources('AWS::Lambda::Function');
1001
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
1002
+ lambda.Properties.MemorySize === 2048);
1003
+ expect(chunkingLambda).toBeDefined();
1004
+ // Default should be 99, not 100, because Bedrock has a hard limit of 100 pages per PDF
1005
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.MAX_PAGES_PER_CHUNK', '99');
1006
+ });
1007
+ test('custom targetTokensPerChunk overrides default', () => {
1008
+ const testApp = (0, test_utils_1.createTestApp)();
1009
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'CustomTargetTokensStack');
1010
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'CustomTargetTokensTest', {
1011
+ enableChunking: true,
1012
+ chunkingConfig: {
1013
+ strategy: 'hybrid',
1014
+ targetTokensPerChunk: 60000,
1015
+ },
1016
+ });
1017
+ const template = assertions_1.Template.fromStack(stack);
1018
+ const lambdas = template.findResources('AWS::Lambda::Function');
1019
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
1020
+ lambda.Properties.MemorySize === 2048);
1021
+ expect(chunkingLambda).toBeDefined();
1022
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TARGET_TOKENS_PER_CHUNK', '60000');
1023
+ });
1024
+ test('all custom values override all defaults', () => {
1025
+ const testApp = (0, test_utils_1.createTestApp)();
1026
+ const stack = new aws_cdk_lib_1.Stack(testApp, 'AllCustomStack');
1027
+ new bedrock_document_processing_1.BedrockDocumentProcessing(stack, 'AllCustomTest', {
1028
+ enableChunking: true,
1029
+ chunkingConfig: {
1030
+ strategy: 'fixed-pages',
1031
+ pageThreshold: 200,
1032
+ tokenThreshold: 300000,
1033
+ chunkSize: 75,
1034
+ overlapPages: 10,
1035
+ maxTokensPerChunk: 150000,
1036
+ overlapTokens: 10000,
1037
+ targetTokensPerChunk: 120000,
1038
+ maxPagesPerChunk: 150,
1039
+ processingMode: 'sequential',
1040
+ maxConcurrency: 5,
1041
+ },
1042
+ });
1043
+ const template = assertions_1.Template.fromStack(stack);
1044
+ const lambdas = template.findResources('AWS::Lambda::Function');
1045
+ const chunkingLambda = Object.values(lambdas).find((lambda) => lambda.Properties.Runtime === 'python3.13' &&
1046
+ lambda.Properties.MemorySize === 2048);
1047
+ expect(chunkingLambda).toBeDefined();
1048
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNKING_STRATEGY', 'fixed-pages');
1049
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.PAGE_THRESHOLD', '200');
1050
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TOKEN_THRESHOLD', '300000');
1051
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.CHUNK_SIZE', '75');
1052
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.OVERLAP_PAGES', '10');
1053
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.MAX_TOKENS_PER_CHUNK', '150000');
1054
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.OVERLAP_TOKENS', '10000');
1055
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.TARGET_TOKENS_PER_CHUNK', '120000');
1056
+ expect(chunkingLambda).toHaveProperty('Properties.Environment.Variables.MAX_PAGES_PER_CHUNK', '150');
1057
+ });
1058
+ });
259
1059
  });
260
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi91c2UtY2FzZXMvZG9jdW1lbnQtcHJvY2Vzc2luZy90ZXN0cy9iZWRyb2NrLWRvY3VtZW50LXByb2Nlc3NpbmcudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDZDQUE4QztBQUM5Qyx1REFBeUQ7QUFDekQseURBQW9FO0FBQ3BFLHVEQUFpRTtBQUNqRSwrQ0FBb0U7QUFDcEUsZ0ZBQTJFO0FBRTNFLFFBQVEsQ0FBQywyQkFBMkIsRUFBRSxHQUFHLEVBQUU7SUFDekMsSUFBSSxZQUFtQixDQUFDO0lBQ3hCLElBQUksV0FBa0IsQ0FBQztJQUN2QixJQUFJLGdCQUF1QixDQUFDO0lBQzVCLElBQUksZUFBc0IsQ0FBQztJQUMzQixJQUFJLG1CQUEwQixDQUFDO0lBQy9CLElBQUksa0JBQXlCLENBQUM7SUFDOUIsSUFBSSxrQkFBeUIsQ0FBQztJQUM5QixJQUFJLGVBQXlCLENBQUM7SUFDOUIsSUFBSSxjQUF3QixDQUFDO0lBQzdCLElBQUksbUJBQTZCLENBQUM7SUFDbEMsSUFBSSxrQkFBNEIsQ0FBQztJQUNqQyxJQUFJLHNCQUFnQyxDQUFDO0lBQ3JDLElBQUkscUJBQStCLENBQUM7SUFDcEMsSUFBSSxxQkFBK0IsQ0FBQztJQUVwQyxTQUFTLENBQUMsR0FBRyxFQUFFO1FBQ2IsWUFBWSxHQUFHLElBQUksbUJBQUssRUFBRSxDQUFDO1FBQzNCLElBQUksdURBQXlCLENBQUMsWUFBWSxFQUFFLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUUvRCxXQUFXLEdBQUcsSUFBSSxtQkFBSyxFQUFFLENBQUM7UUFDMUIsSUFBSSx1REFBeUIsQ0FBQyxXQUFXLEVBQUUsWUFBWSxFQUFFO1lBQ3ZELDBCQUEwQixFQUFFO2dCQUMxQixTQUFTLEVBQUUsdUNBQXlCLENBQUMsc0NBQXNDO2dCQUMzRSx1QkFBdUIsRUFBRSxL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O0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO1FBQ3BDLElBQUksQ0FBQyxzQ0FBc0MsRUFBRSxHQUFHLEVBQUU7WUFDaEQsZUFBZSxDQUFDLHFCQUFxQixDQUFDLHVCQUF1QixFQUFFO2dCQUM3RCxVQUFVLEVBQUUsR0FBRztnQkFDZixPQUFPLEVBQUUsR0FBRzthQUNiLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtZQUN2RCxlQUFlLENBQUMscUJBQXFCLENBQUMsdUJBQXVCLEVBQUU7Z0JBQzdELFdBQVcsRUFBRTtvQkFDWCxTQUFTLEVBQUU7d0JBQ1QsV0FBVyxFQUFFLGdCQUFnQjtxQkFDOUI7aUJBQ0Y7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyx5Q0FBeUMsRUFBRSxHQUFHLEVBQUU7WUFDbkQsZUFBZSxDQUFDLHFCQUFxQixDQUFDLHVCQUF1QixFQUFFO2dCQUM3RCxXQUFXLEVBQUU7b0JBQ1gsU0FBUyxFQUFFO3dCQUNULFdBQVcsRUFBRSxZQUFZO3FCQUMxQjtpQkFDRjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER1cmF0aW9uLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IE1hdGNoLCBUZW1wbGF0ZSB9IGZyb20gJ2F3cy1jZGstbGliL2Fzc2VydGlvbnMnO1xuaW1wb3J0IHsgRm91bmRhdGlvbk1vZGVsSWRlbnRpZmllciB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1iZWRyb2NrJztcbmltcG9ydCB7IENvZGUsIEZ1bmN0aW9uLCBSdW50aW1lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBCZWRyb2NrQ3Jvc3NSZWdpb25JbmZlcmVuY2VQcmVmaXggfSBmcm9tICcuLi8uLi9mcmFtZXdvcmsnO1xuaW1wb3J0IHsgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyB9IGZyb20gJy4uL2JlZHJvY2stZG9jdW1lbnQtcHJvY2Vzc2luZyc7XG5cbmRlc2NyaWJlKCdCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nJywgKCkgPT4ge1xuICBsZXQgZGVmYXVsdFN0YWNrOiBTdGFjaztcbiAgbGV0IGN1c3RvbVN0YWNrOiBTdGFjaztcbiAgbGV0IGNyb3NzUmVnaW9uU3RhY2s6IFN0YWNrO1xuICBsZXQgZW5yaWNobWVudFN0YWNrOiBTdGFjaztcbiAgbGV0IHBvc3RQcm9jZXNzaW5nU3RhY2s6IFN0YWNrO1xuICBsZXQgY3VzdG9tUHJvbXB0c1N0YWNrOiBTdGFjaztcbiAgbGV0IGN1c3RvbVRpbWVvdXRTdGFjazogU3RhY2s7XG4gIGxldCBkZWZhdWx0VGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3VzdG9tVGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3Jvc3NSZWdpb25UZW1wbGF0ZTogVGVtcGxhdGU7XG4gIGxldCBlbnJpY2htZW50VGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgcG9zdFByb2Nlc3NpbmdUZW1wbGF0ZTogVGVtcGxhdGU7XG4gIGxldCBjdXN0b21Qcm9tcHRzVGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3VzdG9tVGltZW91dFRlbXBsYXRlOiBUZW1wbGF0ZTtcblxuICBiZWZvcmVBbGwoKCkgPT4ge1xuICAgIGRlZmF1bHRTdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGRlZmF1bHRTdGFjaywgJ0RlZmF1bHRUZXN0Jywge30pO1xuXG4gICAgY3VzdG9tU3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjdXN0b21TdGFjaywgJ0N1c3RvbVRlc3QnLCB7XG4gICAgICBjbGFzc2lmaWNhdGlvbkJlZHJvY2tNb2RlbDoge1xuICAgICAgICBmbU1vZGVsSWQ6IEZvdW5kYXRpb25Nb2RlbElkZW50aWZpZXIuQU5USFJPUElDX0NMQVVERV8zX0hBSUtVXzIwMjQwMzA3X1YxXzAsXG4gICAgICAgIHVzZUNyb3NzUmVnaW9uSW5mZXJlbmNlOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBwcm9jZXNzaW5nQmVkcm9ja01vZGVsOiB7XG4gICAgICAgIGZtTW9kZWxJZDogRm91bmRhdGlvbk1vZGVsSWRlbnRpZmllci5BTlRIUk9QSUNfQ0xBVURFXzNfSEFJS1VfMjAyNDAzMDdfVjFfMCxcbiAgICAgICAgdXNlQ3Jvc3NSZWdpb25JbmZlcmVuY2U6IGZhbHNlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNyb3NzUmVnaW9uU3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjcm9zc1JlZ2lvblN0YWNrLCAnQ3Jvc3NSZWdpb25UZXN0Jywge1xuICAgICAgY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWw6IHtcbiAgICAgICAgdXNlQ3Jvc3NSZWdpb25JbmZlcmVuY2U6IHRydWUsXG4gICAgICAgIGNyb3NzUmVnaW9uSW5mZXJlbmNlUHJlZml4OiBCZWRyb2NrQ3Jvc3NSZWdpb25JbmZlcmVuY2VQcmVmaXguRVUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgZW5yaWNobWVudFN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgZW5yaWNobWVudEZuID0gbmV3IEZ1bmN0aW9uKGVucmljaG1lbnRTdGFjaywgJ0VucmljaG1lbnRGbicsIHtcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoJ2V4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+ICh7IGVucmljaGVkOiB0cnVlIH0pOycpLFxuICAgIH0pO1xuICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGVucmljaG1lbnRTdGFjaywgJ0VucmljaG1lbnRUZXN0Jywge1xuICAgICAgZW5yaWNobWVudExhbWJkYUZ1bmN0aW9uOiBlbnJpY2htZW50Rm4sXG4gICAgfSk7XG5cbiAgICBwb3N0UHJvY2Vzc2luZ1N0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgY29uc3QgcG9zdFByb2Nlc3NpbmdGbiA9IG5ldyBGdW5jdGlvbihwb3N0UHJvY2Vzc2luZ1N0YWNrLCAnUG9zdFByb2Nlc3NpbmdGbicsIHtcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoJ2V4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+ICh7IHByb2Nlc3NlZDogdHJ1ZSB9KTsnKSxcbiAgICB9KTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhwb3N0UHJvY2Vzc2luZ1N0YWNrLCAnUG9zdFByb2Nlc3NpbmdUZXN0Jywge1xuICAgICAgcG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbjogcG9zdFByb2Nlc3NpbmdGbixcbiAgICB9KTtcblxuICAgIGN1c3RvbVByb21wdHNTdGFjayA9IG5ldyBTdGFjaygpO1xuICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGN1c3RvbVByb21wdHNTdGFjaywgJ0N1c3RvbVByb21wdHNUZXN0Jywge1xuICAgICAgY2xhc3NpZmljYXRpb25Qcm9tcHQ6ICdDdXN0b20gY2xhc3NpZmljYXRpb24gcHJvbXB0JyxcbiAgICAgIHByb2Nlc3NpbmdQcm9tcHQ6ICdDdXN0b20gcHJvY2Vzc2luZyBwcm9tcHQnLFxuICAgIH0pO1xuXG4gICAgY3VzdG9tVGltZW91dFN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoY3VzdG9tVGltZW91dFN0YWNrLCAnQ3VzdG9tVGltZW91dFRlc3QnLCB7XG4gICAgICBzdGVwVGltZW91dHM6IER1cmF0aW9uLm1pbnV0ZXMoMTApLFxuICAgIH0pO1xuXG4gICAgZGVmYXVsdFRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGRlZmF1bHRTdGFjayk7XG4gICAgY3VzdG9tVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tU3RhY2spO1xuICAgIGNyb3NzUmVnaW9uVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3Jvc3NSZWdpb25TdGFjayk7XG4gICAgZW5yaWNobWVudFRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGVucmljaG1lbnRTdGFjayk7XG4gICAgcG9zdFByb2Nlc3NpbmdUZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhwb3N0UHJvY2Vzc2luZ1N0YWNrKTtcbiAgICBjdXN0b21Qcm9tcHRzVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tUHJvbXB0c1N0YWNrKTtcbiAgICBjdXN0b21UaW1lb3V0VGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tVGltZW91dFN0YWNrKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0Jhc2ljIGluZnJhc3RydWN0dXJlJywgKCkgPT4ge1xuICAgIHRlc3QoJ2NyZWF0ZXMgYmFzaWMgaW5mcmFzdHJ1Y3R1cmUnLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlMzOjpCdWNrZXQnLCB7fSk7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlNRUzo6UXVldWUnLCB7fSk7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkR5bmFtb0RCOjpUYWJsZScsIHsgQmlsbGluZ01vZGU6ICdQQVlfUEVSX1JFUVVFU1QnIH0pO1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTdGVwRnVuY3Rpb25zOjpTdGF0ZU1hY2hpbmUnLCB7fSk7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCA1KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2NyZWF0ZXMgY2xhc3NpZmljYXRpb24gYW5kIHByb2Nlc3NpbmcgTGFtYmRhIGZ1bmN0aW9ucycsICgpID0+IHtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnTW9kZWwgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICB0ZXN0KCd1c2VzIGRlZmF1bHQgbW9kZWwgd2l0aCBjcm9zcy1yZWdpb24gcHJlZml4IGRpc2FibGVkJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgTU9ERUxfSUQ6ICdhbnRocm9waWMuY2xhdWRlLXNvbm5ldC00LTIwMjUwNTE0LXYxOjAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3VzZXMgY3VzdG9tIG1vZGVsIHdpdGhvdXQgY3Jvc3MtcmVnaW9uIHByZWZpeCcsICgpID0+IHtcbiAgICAgIGN1c3RvbVRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgTU9ERUxfSUQ6ICdhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY29uZmlndXJlcyBjdXN0b20gY3Jvc3MtcmVnaW9uIHByZWZpeCcsICgpID0+IHtcbiAgICAgIGNyb3NzUmVnaW9uVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBNT0RFTF9JRDogJ2V1LmFudGhyb3BpYy5jbGF1ZGUtc29ubmV0LTQtMjAyNTA1MTQtdjE6MCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY29uZmlndXJlcyBkaWZmZXJlbnQgbW9kZWxzIGZvciBjbGFzc2lmaWNhdGlvbiBhbmQgcHJvY2Vzc2luZycsICgpID0+IHtcbiAgICAgIGN1c3RvbVRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgTU9ERUxfSUQ6ICdhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MCcsXG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjdXN0b21UZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgICAgIE1PREVMX0lEOiAnYW50aHJvcGljLmNsYXVkZS0zLWhhaWt1LTIwMjQwMzA3LXYxOjAnLFxuICAgICAgICAgICAgSU5WT0tFX1RZUEU6ICdwcm9jZXNzaW5nJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdJQU0gcGVybWlzc2lvbnMnLCAoKSA9PiB7XG4gICAgdGVzdCgnY3JlYXRlcyBiZWRyb2NrIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpJQU06OlJvbGUnLCB7XG4gICAgICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudDoge1xuICAgICAgICAgIFN0YXRlbWVudDogW3tcbiAgICAgICAgICAgIEFjdGlvbjogJ3N0czpBc3N1bWVSb2xlJyxcbiAgICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICAgIFByaW5jaXBhbDogeyBTZXJ2aWNlOiAnbGFtYmRhLmFtYXpvbmF3cy5jb20nIH0sXG4gICAgICAgICAgfV0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2dyYW50cyBCZWRyb2NrIGludm9rZSBwZXJtaXNzaW9ucycsICgpID0+IHtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6SUFNOjpSb2xlJywge1xuICAgICAgICBQb2xpY2llczogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAgIFBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgICAgIFN0YXRlbWVudDogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAgICAgICAgIEFjdGlvbjogWydiZWRyb2NrOkludm9rZU1vZGVsJywgJ2JlZHJvY2s6SW52b2tlTW9kZWxXaXRoUmVzcG9uc2VTdHJlYW0nXSxcbiAgICAgICAgICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgXSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICBdKSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnZ3JhbnRzIFMzIGFjY2VzcyBwZXJtaXNzaW9ucycsICgpID0+IHtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6SUFNOjpSb2xlJywge1xuICAgICAgICBQb2xpY2llczogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAgIFBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgICAgIFN0YXRlbWVudDogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAgICAgICAgIEFjdGlvbjogTWF0Y2guYXJyYXlXaXRoKFsnczM6R2V0T2JqZWN0J10pLFxuICAgICAgICAgICAgICAgICAgRWZmZWN0OiAnQWxsb3cnLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIF0pLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdPcHRpb25hbCB3b3JrZmxvdyBzdGVwcycsICgpID0+IHtcbiAgICB0ZXN0KCdpbmNsdWRlcyBlbnJpY2htZW50IExhbWJkYSB3aGVuIHByb3ZpZGVkJywgKCkgPT4ge1xuICAgICAgZW5yaWNobWVudFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBIYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICB9KTtcbiAgICAgIGVucmljaG1lbnRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywge1xuICAgICAgICBEZWZpbml0aW9uU3RyaW5nOiBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAnRm46OkpvaW4nOiBNYXRjaC5hcnJheVdpdGgoWycnXSksXG4gICAgICAgIH0pLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdpbmNsdWRlcyBwb3N0LXByb2Nlc3NpbmcgTGFtYmRhIHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICBwb3N0UHJvY2Vzc2luZ1RlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBIYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICB9KTtcbiAgICAgIHBvc3RQcm9jZXNzaW5nVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlN0ZXBGdW5jdGlvbnM6OlN0YXRlTWFjaGluZScsIHtcbiAgICAgICAgRGVmaW5pdGlvblN0cmluZzogTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgJ0ZuOjpKb2luJzogTWF0Y2guYXJyYXlXaXRoKFsnJ10pLFxuICAgICAgICB9KSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ3VzdG9tIGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gICAgdGVzdCgndXNlcyBjdXN0b20gY2xhc3NpZmljYXRpb24gcHJvbXB0JywgKCkgPT4ge1xuICAgICAgY3VzdG9tUHJvbXB0c1RlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgUFJPTVBUOiAnQ3VzdG9tIGNsYXNzaWZpY2F0aW9uIHByb21wdCcsXG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd1c2VzIGN1c3RvbSBwcm9jZXNzaW5nIHByb21wdCcsICgpID0+IHtcbiAgICAgIGN1c3RvbVByb21wdHNUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgICAgIFBST01QVDogJ0N1c3RvbSBwcm9jZXNzaW5nIHByb21wdCcsXG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2NvbmZpZ3VyZXMgY3VzdG9tIHN0ZXAgdGltZW91dCcsICgpID0+IHtcbiAgICAgIGN1c3RvbVRpbWVvdXRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgVGltZW91dDogNjAwLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdMYW1iZGEgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICB0ZXN0KCdjb25maWd1cmVzIExhbWJkYSBtZW1vcnkgYW5kIHRpbWVvdXQnLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIE1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgVGltZW91dDogMzAwLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdzZXRzIGNvcnJlY3QgaW52b2tlIHR5cGUgZm9yIGNsYXNzaWZpY2F0aW9uJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgSU5WT0tFX1RZUEU6ICdjbGFzc2lmaWNhdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnc2V0cyBjb3JyZWN0IGludm9rZSB0eXBlIGZvciBwcm9jZXNzaW5nJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgSU5WT0tFX1RZUEU6ICdwcm9jZXNzaW5nJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
1060
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi91c2UtY2FzZXMvZG9jdW1lbnQtcHJvY2Vzc2luZy90ZXN0cy9iZWRyb2NrLWRvY3VtZW50LXByb2Nlc3NpbmcudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDZDQUFtRDtBQUNuRCx1REFBeUQ7QUFDekQseURBQW9FO0FBQ3BFLHVEQUFpRTtBQUNqRSwrQ0FBb0U7QUFDcEUsMkRBQTJEO0FBQzNELGdGQUEyRTtBQUUzRSxRQUFRLENBQUMsMkJBQTJCLEVBQUUsR0FBRyxFQUFFO0lBQ3pDLElBQUksR0FBUSxDQUFDO0lBQ2IsSUFBSSxZQUFtQixDQUFDO0lBQ3hCLElBQUksV0FBa0IsQ0FBQztJQUN2QixJQUFJLGdCQUF1QixDQUFDO0lBQzVCLElBQUksZUFBc0IsQ0FBQztJQUMzQixJQUFJLG1CQUEwQixDQUFDO0lBQy9CLElBQUksa0JBQXlCLENBQUM7SUFDOUIsSUFBSSxrQkFBeUIsQ0FBQztJQUM5QixJQUFJLGFBQW9CLENBQUM7SUFDekIsSUFBSSxlQUF5QixDQUFDO0lBQzlCLElBQUksY0FBd0IsQ0FBQztJQUM3QixJQUFJLG1CQUE2QixDQUFDO0lBQ2xDLElBQUksa0JBQTRCLENBQUM7SUFDakMsSUFBSSxzQkFBZ0MsQ0FBQztJQUNyQyxJQUFJLHFCQUErQixDQUFDO0lBQ3BDLElBQUkscUJBQStCLENBQUM7SUFDcEMsSUFBSSxnQkFBMEIsQ0FBQztJQUUvQixTQUFTLENBQUMsR0FBRyxFQUFFO1FBQ2IsMERBQTBEO1FBQzFELEdBQUcsR0FBRyxJQUFBLDBCQUFhLEdBQUUsQ0FBQztRQUV0QixZQUFZLEdBQUcsSUFBSSxtQkFBSyxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUM5QyxJQUFJLHVEQUF5QixDQUFDLFlBQVksRUFBRSxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFL0Qs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QUFhLENBQUMsQ0FBQztZQUMzRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsY0FBYyxDQUFDLGlEQUFpRCxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2hHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxjQUFjLENBQUMsa0RBQWtELEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyw2Q0FBNkMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUMzRixNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsY0FBYyxDQUFDLGdEQUFnRCxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzlGLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxjQUFjLENBQUMsdURBQXVELEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDekcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxpREFBaUQsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNsRyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsY0FBYyxDQUFDLDBEQUEwRCxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzVHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxjQUFjLENBQUMsc0RBQXNELEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkcsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXBwLCBEdXJhdGlvbiwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBNYXRjaCwgVGVtcGxhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hc3NlcnRpb25zJztcbmltcG9ydCB7IEZvdW5kYXRpb25Nb2RlbElkZW50aWZpZXIgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtYmVkcm9jayc7XG5pbXBvcnQgeyBDb2RlLCBGdW5jdGlvbiwgUnVudGltZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgQmVkcm9ja0Nyb3NzUmVnaW9uSW5mZXJlbmNlUHJlZml4IH0gZnJvbSAnLi4vLi4vZnJhbWV3b3JrJztcbmltcG9ydCB7IGNyZWF0ZVRlc3RBcHAgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvdGVzdC11dGlscyc7XG5pbXBvcnQgeyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nIH0gZnJvbSAnLi4vYmVkcm9jay1kb2N1bWVudC1wcm9jZXNzaW5nJztcblxuZGVzY3JpYmUoJ0JlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcnLCAoKSA9PiB7XG4gIGxldCBhcHA6IEFwcDtcbiAgbGV0IGRlZmF1bHRTdGFjazogU3RhY2s7XG4gIGxldCBjdXN0b21TdGFjazogU3RhY2s7XG4gIGxldCBjcm9zc1JlZ2lvblN0YWNrOiBTdGFjaztcbiAgbGV0IGVucmljaG1lbnRTdGFjazogU3RhY2s7XG4gIGxldCBwb3N0UHJvY2Vzc2luZ1N0YWNrOiBTdGFjaztcbiAgbGV0IGN1c3RvbVByb21wdHNTdGFjazogU3RhY2s7XG4gIGxldCBjdXN0b21UaW1lb3V0U3RhY2s6IFN0YWNrO1xuICBsZXQgY2h1bmtpbmdTdGFjazogU3RhY2s7XG4gIGxldCBkZWZhdWx0VGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3VzdG9tVGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3Jvc3NSZWdpb25UZW1wbGF0ZTogVGVtcGxhdGU7XG4gIGxldCBlbnJpY2htZW50VGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgcG9zdFByb2Nlc3NpbmdUZW1wbGF0ZTogVGVtcGxhdGU7XG4gIGxldCBjdXN0b21Qcm9tcHRzVGVtcGxhdGU6IFRlbXBsYXRlO1xuICBsZXQgY3VzdG9tVGltZW91dFRlbXBsYXRlOiBUZW1wbGF0ZTtcbiAgbGV0IGNodW5raW5nVGVtcGxhdGU6IFRlbXBsYXRlO1xuXG4gIGJlZm9yZUFsbCgoKSA9PiB7XG4gICAgLy8gVXNlIGNyZWF0ZVRlc3RBcHAoKSB0byBza2lwIGJ1bmRsaW5nIGFuZCBzcGVlZCB1cCB0ZXN0c1xuICAgIGFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcblxuICAgIGRlZmF1bHRTdGFjayA9IG5ldyBTdGFjayhhcHAsICdEZWZhdWx0U3RhY2snKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhkZWZhdWx0U3RhY2ssICdEZWZhdWx0VGVzdCcsIHt9KTtcblxuICAgIGN1c3RvbVN0YWNrID0gbmV3IFN0YWNrKGFwcCwgJ0N1c3RvbVN0YWNrJyk7XG4gICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoY3VzdG9tU3RhY2ssICdDdXN0b21UZXN0Jywge1xuICAgICAgY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWw6IHtcbiAgICAgICAgZm1Nb2RlbElkOiBGb3VuZGF0aW9uTW9kZWxJZGVudGlmaWVyLkFOVEhST1BJQ19DTEFVREVfM19IQUlLVV8yMDI0MDMwN19WMV8wLFxuICAgICAgICB1c2VDcm9zc1JlZ2lvbkluZmVyZW5jZTogZmFsc2UsXG4gICAgICB9LFxuICAgICAgcHJvY2Vzc2luZ0JlZHJvY2tNb2RlbDoge1xuICAgICAgICBmbU1vZGVsSWQ6IEZvdW5kYXRpb25Nb2RlbElkZW50aWZpZXIuQU5USFJPUElDX0NMQVVERV8zX0hBSUtVXzIwMjQwMzA3X1YxXzAsXG4gICAgICAgIHVzZUNyb3NzUmVnaW9uSW5mZXJlbmNlOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjcm9zc1JlZ2lvblN0YWNrID0gbmV3IFN0YWNrKGFwcCwgJ0Nyb3NzUmVnaW9uU3RhY2snKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjcm9zc1JlZ2lvblN0YWNrLCAnQ3Jvc3NSZWdpb25UZXN0Jywge1xuICAgICAgY2xhc3NpZmljYXRpb25CZWRyb2NrTW9kZWw6IHtcbiAgICAgICAgdXNlQ3Jvc3NSZWdpb25JbmZlcmVuY2U6IHRydWUsXG4gICAgICAgIGNyb3NzUmVnaW9uSW5mZXJlbmNlUHJlZml4OiBCZWRyb2NrQ3Jvc3NSZWdpb25JbmZlcmVuY2VQcmVmaXguRVUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgZW5yaWNobWVudFN0YWNrID0gbmV3IFN0YWNrKGFwcCwgJ0VucmljaG1lbnRTdGFjaycpO1xuICAgIGNvbnN0IGVucmljaG1lbnRGbiA9IG5ldyBGdW5jdGlvbihlbnJpY2htZW50U3RhY2ssICdFbnJpY2htZW50Rm4nLCB7XG4gICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMF9YLFxuICAgICAgaGFuZGxlcjogJ2luZGV4LmhhbmRsZXInLFxuICAgICAgY29kZTogQ29kZS5mcm9tSW5saW5lKCdleHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoKSA9PiAoeyBlbnJpY2hlZDogdHJ1ZSB9KTsnKSxcbiAgICB9KTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhlbnJpY2htZW50U3RhY2ssICdFbnJpY2htZW50VGVzdCcsIHtcbiAgICAgIGVucmljaG1lbnRMYW1iZGFGdW5jdGlvbjogZW5yaWNobWVudEZuLFxuICAgIH0pO1xuXG4gICAgcG9zdFByb2Nlc3NpbmdTdGFjayA9IG5ldyBTdGFjayhhcHAsICdQb3N0UHJvY2Vzc2luZ1N0YWNrJyk7XG4gICAgY29uc3QgcG9zdFByb2Nlc3NpbmdGbiA9IG5ldyBGdW5jdGlvbihwb3N0UHJvY2Vzc2luZ1N0YWNrLCAnUG9zdFByb2Nlc3NpbmdGbicsIHtcbiAgICAgIHJ1bnRpbWU6IFJ1bnRpbWUuTk9ERUpTXzIwX1gsXG4gICAgICBoYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICBjb2RlOiBDb2RlLmZyb21JbmxpbmUoJ2V4cG9ydHMuaGFuZGxlciA9IGFzeW5jICgpID0+ICh7IHByb2Nlc3NlZDogdHJ1ZSB9KTsnKSxcbiAgICB9KTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhwb3N0UHJvY2Vzc2luZ1N0YWNrLCAnUG9zdFByb2Nlc3NpbmdUZXN0Jywge1xuICAgICAgcG9zdFByb2Nlc3NpbmdMYW1iZGFGdW5jdGlvbjogcG9zdFByb2Nlc3NpbmdGbixcbiAgICB9KTtcblxuICAgIGN1c3RvbVByb21wdHNTdGFjayA9IG5ldyBTdGFjayhhcHAsICdDdXN0b21Qcm9tcHRzU3RhY2snKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjdXN0b21Qcm9tcHRzU3RhY2ssICdDdXN0b21Qcm9tcHRzVGVzdCcsIHtcbiAgICAgIGNsYXNzaWZpY2F0aW9uUHJvbXB0OiAnQ3VzdG9tIGNsYXNzaWZpY2F0aW9uIHByb21wdCcsXG4gICAgICBwcm9jZXNzaW5nUHJvbXB0OiAnQ3VzdG9tIHByb2Nlc3NpbmcgcHJvbXB0JyxcbiAgICB9KTtcblxuICAgIGN1c3RvbVRpbWVvdXRTdGFjayA9IG5ldyBTdGFjayhhcHAsICdDdXN0b21UaW1lb3V0U3RhY2snKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjdXN0b21UaW1lb3V0U3RhY2ssICdDdXN0b21UaW1lb3V0VGVzdCcsIHtcbiAgICAgIHN0ZXBUaW1lb3V0czogRHVyYXRpb24ubWludXRlcygxMCksXG4gICAgfSk7XG5cbiAgICBjaHVua2luZ1N0YWNrID0gbmV3IFN0YWNrKGFwcCwgJ0NodW5raW5nU3RhY2snKTtcbiAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhjaHVua2luZ1N0YWNrLCAnQ2h1bmtpbmdUZXN0Jywge1xuICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgIG1heFBhZ2VzUGVyQ2h1bms6IDEwMCxcbiAgICAgICAgdGFyZ2V0VG9rZW5zUGVyQ2h1bms6IDgwMDAwLFxuICAgICAgICBwYWdlVGhyZXNob2xkOiAxMDAsXG4gICAgICAgIHRva2VuVGhyZXNob2xkOiAxNTAwMDAsXG4gICAgICAgIHByb2Nlc3NpbmdNb2RlOiAncGFyYWxsZWwnLFxuICAgICAgICBtYXhDb25jdXJyZW5jeTogMTAsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgZGVmYXVsdFRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGRlZmF1bHRTdGFjayk7XG4gICAgY3VzdG9tVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tU3RhY2spO1xuICAgIGNyb3NzUmVnaW9uVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3Jvc3NSZWdpb25TdGFjayk7XG4gICAgZW5yaWNobWVudFRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGVucmljaG1lbnRTdGFjayk7XG4gICAgcG9zdFByb2Nlc3NpbmdUZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhwb3N0UHJvY2Vzc2luZ1N0YWNrKTtcbiAgICBjdXN0b21Qcm9tcHRzVGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tUHJvbXB0c1N0YWNrKTtcbiAgICBjdXN0b21UaW1lb3V0VGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY3VzdG9tVGltZW91dFN0YWNrKTtcbiAgICBjaHVua2luZ1RlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGNodW5raW5nU3RhY2spO1xuICB9KTtcblxuICBkZXNjcmliZSgnQmFzaWMgaW5mcmFzdHJ1Y3R1cmUnLCAoKSA9PiB7XG4gICAgdGVzdCgnY3JlYXRlcyBiYXNpYyBpbmZyYXN0cnVjdHVyZScsICgpID0+IHtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHt9KTtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U1FTOjpRdWV1ZScsIHt9KTtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6RHluYW1vREI6OlRhYmxlJywgeyBCaWxsaW5nTW9kZTogJ1BBWV9QRVJfUkVRVUVTVCcgfSk7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlN0ZXBGdW5jdGlvbnM6OlN0YXRlTWFjaGluZScsIHt9KTtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIDUpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY3JlYXRlcyBjbGFzc2lmaWNhdGlvbiBhbmQgcHJvY2Vzc2luZyBMYW1iZGEgZnVuY3Rpb25zJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLnJlc291cmNlQ291bnRJcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywgNSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdNb2RlbCBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICAgIHRlc3QoJ3VzZXMgZGVmYXVsdCBtb2RlbCB3aXRoIGNyb3NzLXJlZ2lvbiBwcmVmaXggZGlzYWJsZWQnLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBNT0RFTF9JRDogJ2FudGhyb3BpYy5jbGF1ZGUtc29ubmV0LTQtMjAyNTA1MTQtdjE6MCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgndXNlcyBjdXN0b20gbW9kZWwgd2l0aG91dCBjcm9zcy1yZWdpb24gcHJlZml4JywgKCkgPT4ge1xuICAgICAgY3VzdG9tVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBNT0RFTF9JRDogJ2FudGhyb3BpYy5jbGF1ZGUtMy1oYWlrdS0yMDI0MDMwNy12MTowJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdjb25maWd1cmVzIGN1c3RvbSBjcm9zcy1yZWdpb24gcHJlZml4JywgKCkgPT4ge1xuICAgICAgY3Jvc3NSZWdpb25UZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgICAgIE1PREVMX0lEOiAnZXUuYW50aHJvcGljLmNsYXVkZS1zb25uZXQtNC0yMDI1MDUxNC12MTowJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdjb25maWd1cmVzIGRpZmZlcmVudCBtb2RlbHMgZm9yIGNsYXNzaWZpY2F0aW9uIGFuZCBwcm9jZXNzaW5nJywgKCkgPT4ge1xuICAgICAgY3VzdG9tVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBNT0RFTF9JRDogJ2FudGhyb3BpYy5jbGF1ZGUtMy1oYWlrdS0yMDI0MDMwNy12MTowJyxcbiAgICAgICAgICAgIElOVk9LRV9UWVBFOiAnY2xhc3NpZmljYXRpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGN1c3RvbVRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgTU9ERUxfSUQ6ICdhbnRocm9waWMuY2xhdWRlLTMtaGFpa3UtMjAyNDAzMDctdjE6MCcsXG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0lBTSBwZXJtaXNzaW9ucycsICgpID0+IHtcbiAgICB0ZXN0KCdjcmVhdGVzIGJlZHJvY2sgcGVybWlzc2lvbnMnLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OklBTTo6Um9sZScsIHtcbiAgICAgICAgQXNzdW1lUm9sZVBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgU3RhdGVtZW50OiBbe1xuICAgICAgICAgICAgQWN0aW9uOiAnc3RzOkFzc3VtZVJvbGUnLFxuICAgICAgICAgICAgRWZmZWN0OiAnQWxsb3cnLFxuICAgICAgICAgICAgUHJpbmNpcGFsOiB7IFNlcnZpY2U6ICdsYW1iZGEuYW1hem9uYXdzLmNvbScgfSxcbiAgICAgICAgICB9XSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnZ3JhbnRzIEJlZHJvY2sgaW52b2tlIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpJQU06OlJvbGUnLCB7XG4gICAgICAgIFBvbGljaWVzOiBNYXRjaC5hcnJheVdpdGgoW1xuICAgICAgICAgIE1hdGNoLm9iamVjdExpa2Uoe1xuICAgICAgICAgICAgUG9saWN5RG9jdW1lbnQ6IHtcbiAgICAgICAgICAgICAgU3RhdGVtZW50OiBNYXRjaC5hcnJheVdpdGgoW1xuICAgICAgICAgICAgICAgIE1hdGNoLm9iamVjdExpa2Uoe1xuICAgICAgICAgICAgICAgICAgQWN0aW9uOiBbJ2JlZHJvY2s6SW52b2tlTW9kZWwnLCAnYmVkcm9jazpJbnZva2VNb2RlbFdpdGhSZXNwb25zZVN0cmVhbSddLFxuICAgICAgICAgICAgICAgICAgRWZmZWN0OiAnQWxsb3cnLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgIF0pLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdncmFudHMgUzMgYWNjZXNzIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgICAgZGVmYXVsdFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpJQU06OlJvbGUnLCB7XG4gICAgICAgIFBvbGljaWVzOiBNYXRjaC5hcnJheVdpdGgoW1xuICAgICAgICAgIE1hdGNoLm9iamVjdExpa2Uoe1xuICAgICAgICAgICAgUG9saWN5RG9jdW1lbnQ6IHtcbiAgICAgICAgICAgICAgU3RhdGVtZW50OiBNYXRjaC5hcnJheVdpdGgoW1xuICAgICAgICAgICAgICAgIE1hdGNoLm9iamVjdExpa2Uoe1xuICAgICAgICAgICAgICAgICAgQWN0aW9uOiBNYXRjaC5hcnJheVdpdGgoWydzMzpHZXRPYmplY3QnXSksXG4gICAgICAgICAgICAgICAgICBFZmZlY3Q6ICdBbGxvdycsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXSksXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ09wdGlvbmFsIHdvcmtmbG93IHN0ZXBzJywgKCkgPT4ge1xuICAgIHRlc3QoJ2luY2x1ZGVzIGVucmljaG1lbnQgTGFtYmRhIHdoZW4gcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICBlbnJpY2htZW50VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIH0pO1xuICAgICAgZW5yaWNobWVudFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTdGVwRnVuY3Rpb25zOjpTdGF0ZU1hY2hpbmUnLCB7XG4gICAgICAgIERlZmluaXRpb25TdHJpbmc6IE1hdGNoLm9iamVjdExpa2Uoe1xuICAgICAgICAgICdGbjo6Sm9pbic6IE1hdGNoLmFycmF5V2l0aChbJyddKSxcbiAgICAgICAgfSksXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2luY2x1ZGVzIHBvc3QtcHJvY2Vzc2luZyBMYW1iZGEgd2hlbiBwcm92aWRlZCcsICgpID0+IHtcbiAgICAgIHBvc3RQcm9jZXNzaW5nVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIH0pO1xuICAgICAgcG9zdFByb2Nlc3NpbmdUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywge1xuICAgICAgICBEZWZpbml0aW9uU3RyaW5nOiBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAnRm46OkpvaW4nOiBNYXRjaC5hcnJheVdpdGgoWycnXSksXG4gICAgICAgIH0pLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDdXN0b20gY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICB0ZXN0KCd1c2VzIGN1c3RvbSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQnLCAoKSA9PiB7XG4gICAgICBjdXN0b21Qcm9tcHRzVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBQUk9NUFQ6ICdDdXN0b20gY2xhc3NpZmljYXRpb24gcHJvbXB0JyxcbiAgICAgICAgICAgIElOVk9LRV9UWVBFOiAnY2xhc3NpZmljYXRpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3VzZXMgY3VzdG9tIHByb2Nlc3NpbmcgcHJvbXB0JywgKCkgPT4ge1xuICAgICAgY3VzdG9tUHJvbXB0c1RlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgUFJPTVBUOiAnQ3VzdG9tIHByb2Nlc3NpbmcgcHJvbXB0JyxcbiAgICAgICAgICAgIElOVk9LRV9UWVBFOiAncHJvY2Vzc2luZycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY29uZmlndXJlcyBjdXN0b20gc3RlcCB0aW1lb3V0JywgKCkgPT4ge1xuICAgICAgY3VzdG9tVGltZW91dFRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBUaW1lb3V0OiA2MDAsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0xhbWJkYSBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICAgIHRlc3QoJ2NvbmZpZ3VyZXMgTGFtYmRhIG1lbW9yeSBhbmQgdGltZW91dCcsICgpID0+IHtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgTWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICBUaW1lb3V0OiAzMDAsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3NldHMgY29ycmVjdCBpbnZva2UgdHlwZSBmb3IgY2xhc3NpZmljYXRpb24nLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdzZXRzIGNvcnJlY3QgaW52b2tlIHR5cGUgZm9yIHByb2Nlc3NpbmcnLCAoKSA9PiB7XG4gICAgICBkZWZhdWx0VGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ3Byb2Nlc3NpbmcnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0NodW5raW5nIGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gICAgdGVzdCgnYWNjZXB0cyBlbmFibGVDaHVua2luZyBwcm9wJywgKCkgPT4ge1xuICAgICAgLy8gVGhpcyB0ZXN0IHZlcmlmaWVzIHRoYXQgdGhlIEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmdQcm9wcyBpbnRlcmZhY2VcbiAgICAgIC8vIGNvcnJlY3RseSBhY2NlcHRzIHRoZSBlbmFibGVDaHVua2luZyBib29sZWFuIGZsYWdcbiAgICAgIGV4cGVjdChjaHVua2luZ1N0YWNrKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnYWNjZXB0cyBjaHVua2luZ0NvbmZpZyBwcm9wIHdpdGggYWxsIHN0cmF0ZWd5IG9wdGlvbnMnLCAoKSA9PiB7XG4gICAgICAvLyBUaGlzIHRlc3QgdmVyaWZpZXMgdGhhdCB0aGUgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZ1Byb3BzIGludGVyZmFjZVxuICAgICAgLy8gY29ycmVjdGx5IGFjY2VwdHMgdGhlIGNodW5raW5nQ29uZmlnIHdpdGggYWxsIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgY2h1bmtpbmdUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHt9KTtcbiAgICAgIGNodW5raW5nVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlNRUzo6UXVldWUnLCB7fSk7XG4gICAgICBjaHVua2luZ1RlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpEeW5hbW9EQjo6VGFibGUnLCB7IEJpbGxpbmdNb2RlOiAnUEFZX1BFUl9SRVFVRVNUJyB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2FjY2VwdHMgZml4ZWQtcGFnZXMgc3RyYXRlZ3kgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBmaXhlZFBhZ2VzU3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0ZpeGVkUGFnZXNTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoZml4ZWRQYWdlc1N0YWNrLCAnRml4ZWRQYWdlc1Rlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnZml4ZWQtcGFnZXMnLFxuICAgICAgICAgIHBhZ2VUaHJlc2hvbGQ6IDEwMCxcbiAgICAgICAgICBjaHVua1NpemU6IDUwLFxuICAgICAgICAgIG92ZXJsYXBQYWdlczogNSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBWZXJpZnkgc3RhY2sgaXMgY3JlYXRlZCBzdWNjZXNzZnVsbHlcbiAgICAgIGV4cGVjdChmaXhlZFBhZ2VzU3RhY2spLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdhY2NlcHRzIHRva2VuLWJhc2VkIHN0cmF0ZWd5IGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3QgdG9rZW5CYXNlZFN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdUb2tlbkJhc2VkU3RhY2snKTtcbiAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHRva2VuQmFzZWRTdGFjaywgJ1Rva2VuQmFzZWRUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBzdHJhdGVneTogJ3Rva2VuLWJhc2VkJyxcbiAgICAgICAgICB0b2tlblRocmVzaG9sZDogMTUwMDAwLFxuICAgICAgICAgIG1heFRva2Vuc1BlckNodW5rOiAxMDAwMDAsXG4gICAgICAgICAgb3ZlcmxhcFRva2VuczogNTAwMCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBWZXJpZnkgc3RhY2sgaXMgY3JlYXRlZCBzdWNjZXNzZnVsbHlcbiAgICAgIGV4cGVjdCh0b2tlbkJhc2VkU3RhY2spLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdhY2NlcHRzIGh5YnJpZCBzdHJhdGVneSBjb25maWd1cmF0aW9uJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IGh5YnJpZFN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdIeWJyaWRTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoaHlicmlkU3RhY2ssICdIeWJyaWRUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgICAgbWF4UGFnZXNQZXJDaHVuazogMTAwLFxuICAgICAgICAgIHRhcmdldFRva2Vuc1BlckNodW5rOiA4MDAwMCxcbiAgICAgICAgICBwYWdlVGhyZXNob2xkOiAxMDAsXG4gICAgICAgICAgdG9rZW5UaHJlc2hvbGQ6IDE1MDAwMCxcbiAgICAgICAgICBvdmVybGFwVG9rZW5zOiA1MDAwLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBzdGFjayBpcyBjcmVhdGVkIHN1Y2Nlc3NmdWxseVxuICAgICAgZXhwZWN0KGh5YnJpZFN0YWNrKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnYWNjZXB0cyBkZWZhdWx0IGNodW5raW5nIGNvbmZpZ3VyYXRpb24nLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3QgZGVmYXVsdENodW5raW5nU3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0RlZmF1bHRDaHVua2luZ1N0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhkZWZhdWx0Q2h1bmtpbmdTdGFjaywgJ0RlZmF1bHRDaHVua2luZ1Rlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBzdGFjayBpcyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSB3aXRoIGRlZmF1bHQgY29uZmlnXG4gICAgICBleHBlY3QoZGVmYXVsdENodW5raW5nU3RhY2spLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdkb2VzIG5vdCBlbmFibGUgY2h1bmtpbmcgd2hlbiBlbmFibGVDaHVua2luZyBpcyBmYWxzZScsICgpID0+IHtcbiAgICAgIC8vIFZlcmlmeSB0aGF0IHRoZSBkZWZhdWx0IHN0YWNrICh3aXRob3V0IGNodW5raW5nKSB3b3JrcyBhcyBleHBlY3RlZFxuICAgICAgZXhwZWN0KGRlZmF1bHRTdGFjaykudG9CZURlZmluZWQoKTtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHt9KTtcbiAgICAgIGRlZmF1bHRUZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U1FTOjpRdWV1ZScsIHt9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1dvcmtmbG93IGJyYW5jaGluZyBmb3IgY2h1bmtpbmcnLCAoKSA9PiB7XG4gICAgdGVzdCgnY3JlYXRlcyBzdGF0ZSBtYWNoaW5lIHdpdGggY2h1bmtpbmcgd29ya2Zsb3cnLCAoKSA9PiB7XG4gICAgICAvLyBWZXJpZnkgdGhhdCBhIHN0YXRlIG1hY2hpbmUgaXMgY3JlYXRlZCB3aGVuIGNodW5raW5nIGlzIGVuYWJsZWRcbiAgICAgIGNodW5raW5nVGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OlN0ZXBGdW5jdGlvbnM6OlN0YXRlTWFjaGluZScsIDEpO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIHN0YXRlIG1hY2hpbmUgaGFzIHRoZSBleHBlY3RlZCBjb25maWd1cmF0aW9uXG4gICAgICBjaHVua2luZ1RlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpTdGVwRnVuY3Rpb25zOjpTdGF0ZU1hY2hpbmUnLCB7XG4gICAgICAgIEVuY3J5cHRpb25Db25maWd1cmF0aW9uOiBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICBUeXBlOiAnQ1VTVE9NRVJfTUFOQUdFRF9LTVNfS0VZJyxcbiAgICAgICAgfSksXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3N0YW5kYXJkIHdvcmtmbG93IGlzIHVzZWQgd2hlbiBjaHVua2luZyBpcyBkaXNhYmxlZCcsICgpID0+IHtcbiAgICAgIC8vIFZlcmlmeSB0aGF0IHdoZW4gZW5hYmxlQ2h1bmtpbmcgaXMgZmFsc2UsIHRoZSBzdGFuZGFyZCB3b3JrZmxvdyBpcyB1c2VkXG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgbm9DaHVua2luZ1N0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdOb0NodW5raW5nU3RhY2snKTtcbiAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKG5vQ2h1bmtpbmdTdGFjaywgJ05vQ2h1bmtpbmdUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogZmFsc2UsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgbm9DaHVua2luZ1RlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKG5vQ2h1bmtpbmdTdGFjayk7XG5cbiAgICAgIC8vIFNob3VsZCBoYXZlIHN0YXRlIG1hY2hpbmVcbiAgICAgIG5vQ2h1bmtpbmdUZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywgMSk7XG5cbiAgICAgIC8vIFNob3VsZCBOT1QgaGF2ZSBQREYgY2h1bmtpbmcgTGFtYmRhIChQeXRob24gMy4xMyB3aXRoIDIwNDggTUIpXG4gICAgICBjb25zdCBsYW1iZGFzID0gbm9DaHVua2luZ1RlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVVbmRlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2NyZWF0ZXMgUERGIGNodW5raW5nIExhbWJkYSB3aGVuIGNodW5raW5nIGlzIGVuYWJsZWQnLCAoKSA9PiB7XG4gICAgICAvLyBWZXJpZnkgdGhhdCB0aGUgUERGIGNodW5raW5nIExhbWJkYSBpcyBjcmVhdGVkXG4gICAgICBjb25zdCBsYW1iZGFzID0gY2h1bmtpbmdUZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcblxuICAgICAgLy8gRmluZCB0aGUgY2h1bmtpbmcgTGFtYmRhIGJ5IGl0cyBjaGFyYWN0ZXJpc3RpY3MgKFB5dGhvbiAzLjEzLCAyMDQ4IE1CIG1lbW9yeSlcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDggJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuVGltZW91dCA9PT0gNjAwLFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0hhdmVQcm9wZXJ0eSgnUHJvcGVydGllcy5IYW5kbGVyJywgJ2hhbmRsZXIuaGFuZGxlcicpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnUERGIGNodW5raW5nIExhbWJkYSBoYXMgY29ycmVjdCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgZm9yIGh5YnJpZCBzdHJhdGVneScsICgpID0+IHtcbiAgICAgIC8vIFZlcmlmeSBjaHVua2luZyBjb25maWd1cmF0aW9uIGlzIHBhc3NlZCB2aWEgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAgICAvLyBGaW5kIHRoZSBjaHVua2luZyBMYW1iZGEgc3BlY2lmaWNhbGx5XG4gICAgICBjb25zdCBsYW1iZGFzID0gY2h1bmtpbmdUZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDgsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5DSFVOS0lOR19TVFJBVEVHWScsICdoeWJyaWQnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLk1BWF9QQUdFU19QRVJfQ0hVTksnLCAnMTAwJyk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5UQVJHRVRfVE9LRU5TX1BFUl9DSFVOSycsICc4MDAwMCcpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnUERGIGNodW5raW5nIExhbWJkYSBoYXMgUzMgYWNjZXNzIHBlcm1pc3Npb25zJywgKCkgPT4ge1xuICAgICAgLy8gVmVyaWZ5IHRoYXQgdGhlIGNodW5raW5nIExhbWJkYSBoYXMgUzMgcGVybWlzc2lvbnNcbiAgICAgIGNodW5raW5nVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OklBTTo6Um9sZScsIHtcbiAgICAgICAgUG9saWNpZXM6IE1hdGNoLmFycmF5V2l0aChbXG4gICAgICAgICAgTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgICBQb2xpY3lEb2N1bWVudDogTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgICAgIFN0YXRlbWVudDogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICAgICAgICBNYXRjaC5vYmplY3RMaWtlKHtcbiAgICAgICAgICAgICAgICAgIEFjdGlvbjogTWF0Y2guYXJyYXlXaXRoKFtcbiAgICAgICAgICAgICAgICAgICAgJ3MzOkdldE9iamVjdCcsXG4gICAgICAgICAgICAgICAgICAgICdzMzpQdXRPYmplY3QnLFxuICAgICAgICAgICAgICAgICAgXSksXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgfSksXG4gICAgICAgIF0pLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdzdGF0ZSBtYWNoaW5lIGNhbiBpbnZva2UgUERGIGNodW5raW5nIExhbWJkYScsICgpID0+IHtcbiAgICAgIC8vIFZlcmlmeSB0aGF0IHRoZSBzdGF0ZSBtYWNoaW5lIHJvbGUgaGFzIHBlcm1pc3Npb24gdG8gaW52b2tlIHRoZSBjaHVua2luZyBMYW1iZGFcbiAgICAgIGNodW5raW5nVGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OklBTTo6UG9saWN5Jywge1xuICAgICAgICBQb2xpY3lEb2N1bWVudDogTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgU3RhdGVtZW50OiBNYXRjaC5hcnJheVdpdGgoW1xuICAgICAgICAgICAgTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgICAgIEFjdGlvbjogJ2xhbWJkYTpJbnZva2VGdW5jdGlvbicsXG4gICAgICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0pLFxuICAgICAgICB9KSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5cbmRlc2NyaWJlKCdDaHVuay1hd2FyZSBjbGFzc2lmaWNhdGlvbiBpbnRlZ3JhdGlvbicsICgpID0+IHtcbiAgZGVzY3JpYmUoJ0NsYXNzaWZpY2F0aW9uIExhbWJkYSBjaHVuayBjb250ZXh0JywgKCkgPT4ge1xuICAgIHRlc3QoJ2NsYXNzaWZpY2F0aW9uIExhbWJkYSByZWNlaXZlcyBjaHVuayBtZXRhZGF0YSBpbiBNYXAgU3RhdGUnLCAoKSA9PiB7XG4gICAgICAvLyBWZXJpZnkgdGhhdCB0aGUgTWFwIFN0YXRlIHBhc3NlcyBjaHVuayBtZXRhZGF0YSB0byB0aGUgY2xhc3NpZmljYXRpb24gTGFtYmRhXG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3QgY2h1bmtpbmdTdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnQ2h1bmtDb250ZXh0U3RhY2snKTtcbiAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGNodW5raW5nU3RhY2ssICdDaHVua0NvbnRleHRUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgICAgbWF4UGFnZXNQZXJDaHVuazogMTAwLFxuICAgICAgICAgIHRhcmdldFRva2Vuc1BlckNodW5rOiA4MDAwMCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhjaHVua2luZ1N0YWNrKTtcblxuICAgICAgLy8gVmVyaWZ5IHN0YXRlIG1hY2hpbmUgaXMgY3JlYXRlZCB3aXRoIE1hcCBTdGF0ZVxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OlN0ZXBGdW5jdGlvbnM6OlN0YXRlTWFjaGluZScsIHtcbiAgICAgICAgRGVmaW5pdGlvblN0cmluZzogTWF0Y2gub2JqZWN0TGlrZSh7XG4gICAgICAgICAgJ0ZuOjpKb2luJzogTWF0Y2guYXJyYXlXaXRoKFsnJ10pLFxuICAgICAgICB9KSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIHN0YXRlIG1hY2hpbmUgZGVmaW5pdGlvbiBpbmNsdWRlcyBNYXAgc3RhdGUgd2l0aCBjaHVuayBwYXJhbWV0ZXJzXG4gICAgICBjb25zdCBzdGF0ZU1hY2hpbmVzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcygnQVdTOjpTdGVwRnVuY3Rpb25zOjpTdGF0ZU1hY2hpbmUnKTtcbiAgICAgIGNvbnN0IHN0YXRlTWFjaGluZURlZmluaXRpb24gPSBPYmplY3QudmFsdWVzKHN0YXRlTWFjaGluZXMpWzBdO1xuICAgICAgZXhwZWN0KHN0YXRlTWFjaGluZURlZmluaXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdub24tY2h1bmtlZCB3b3JrZmxvdyBkb2VzIG5vdCBpbmNsdWRlIGNodW5rIGNvbnRleHQnLCAoKSA9PiB7XG4gICAgICAvLyBWZXJpZnkgdGhhdCB3aGVuIGNodW5raW5nIGlzIGRpc2FibGVkLCBubyBjaHVuayBjb250ZXh0IGlzIGFkZGVkXG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgbm9DaHVua2luZ1N0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdOb0NodW5rQ29udGV4dFN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhub0NodW5raW5nU3RhY2ssICdOb0NodW5rQ29udGV4dFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiBmYWxzZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhub0NodW5raW5nU3RhY2spO1xuXG4gICAgICAvLyBTaG91bGQgaGF2ZSBzdGF0ZSBtYWNoaW5lXG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywgMSk7XG5cbiAgICAgIC8vIFNob3VsZCBOT1QgaGF2ZSBQREYgY2h1bmtpbmcgTGFtYmRhXG4gICAgICBjb25zdCBsYW1iZGFzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyk7XG4gICAgICBjb25zdCBjaHVua2luZ0xhbWJkYSA9IE9iamVjdC52YWx1ZXMobGFtYmRhcykuZmluZCgobGFtYmRhOiBhbnkpID0+XG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLlJ1bnRpbWUgPT09ICdweXRob24zLjEzJyAmJlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5NZW1vcnlTaXplID09PSAyMDQ4LFxuICAgICAgKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZVVuZGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY2h1bmtlZCB3b3JrZmxvdyBpbmNsdWRlcyBNYXAgU3RhdGUgZm9yIHBhcmFsbGVsIGNodW5rIHByb2Nlc3NpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3QgY2h1bmtpbmdTdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnTWFwU3RhdGVTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoY2h1bmtpbmdTdGFjaywgJ01hcFN0YXRlVGVzdCcsIHtcbiAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgc3RyYXRlZ3k6ICdoeWJyaWQnLFxuICAgICAgICAgIHByb2Nlc3NpbmdNb2RlOiAncGFyYWxsZWwnLFxuICAgICAgICAgIG1heENvbmN1cnJlbmN5OiA1LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGNodW5raW5nU3RhY2spO1xuXG4gICAgICAvLyBWZXJpZnkgc3RhdGUgbWFjaGluZSBpcyBjcmVhdGVkXG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywgMSk7XG5cbiAgICAgIC8vIFZlcmlmeSBjbGFzc2lmaWNhdGlvbiBMYW1iZGEgZXhpc3RzXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgICAgIElOVk9LRV9UWVBFOiAnY2xhc3NpZmljYXRpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2NsYXNzaWZpY2F0aW9uIExhbWJkYSBpcyByZXVzZWQgZm9yIGJvdGggY2h1bmtlZCBhbmQgbm9uLWNodW5rZWQgcGF0aHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3QgY2h1bmtpbmdTdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnUmV1c2VTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoY2h1bmtpbmdTdGFjaywgJ1JldXNlVGVzdCcsIHtcbiAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY2h1bmtpbmdTdGFjayk7XG5cbiAgICAgIC8vIENvdW50IGNsYXNzaWZpY2F0aW9uIExhbWJkYXMgKHNob3VsZCBiZSAxLCByZXVzZWQgZm9yIGJvdGggcGF0aHMpXG4gICAgICBjb25zdCBsYW1iZGFzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyk7XG4gICAgICBjb25zdCBjbGFzc2lmaWNhdGlvbkxhbWJkYXMgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbHRlcigobGFtYmRhOiBhbnkpID0+XG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLkVudmlyb25tZW50Py5WYXJpYWJsZXM/LklOVk9LRV9UWVBFID09PSAnY2xhc3NpZmljYXRpb24nLFxuICAgICAgKTtcblxuICAgICAgLy8gU2hvdWxkIGhhdmUgZXhhY3RseSAxIGNsYXNzaWZpY2F0aW9uIExhbWJkYSAocmV1c2VkKVxuICAgICAgZXhwZWN0KGNsYXNzaWZpY2F0aW9uTGFtYmRhcy5sZW5ndGgpLnRvQmUoMSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd3b3JrZmxvdyBtYWludGFpbnMgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBmb3Igc21hbGwgZG9jdW1lbnRzJywgKCkgPT4ge1xuICAgICAgLy8gV2hlbiBjaHVua2luZyBpcyBlbmFibGVkIGJ1dCBkb2N1bWVudCBpcyBzbWFsbCwgaXQgc2hvdWxkIHVzZSBzdGFuZGFyZCB3b3JrZmxvd1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IGNodW5raW5nU3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0JhY2t3YXJkQ29tcGF0U3RhY2snKTtcbiAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGNodW5raW5nU3RhY2ssICdCYWNrd2FyZENvbXBhdFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnaHlicmlkJyxcbiAgICAgICAgICBwYWdlVGhyZXNob2xkOiAxMDAsXG4gICAgICAgICAgdG9rZW5UaHJlc2hvbGQ6IDE1MDAwMCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhjaHVua2luZ1N0YWNrKTtcblxuICAgICAgLy8gVmVyaWZ5IGJvdGggY2xhc3NpZmljYXRpb24gYW5kIHByb2Nlc3NpbmcgTGFtYmRhcyBleGlzdFxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBJTlZPS0VfVFlQRTogJ2NsYXNzaWZpY2F0aW9uJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJywge1xuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgIFZhcmlhYmxlczoge1xuICAgICAgICAgICAgSU5WT0tFX1RZUEU6ICdwcm9jZXNzaW5nJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFZlcmlmeSBzdGF0ZSBtYWNoaW5lIGhhcyBDaG9pY2Ugc3RhdGUgZm9yIGJyYW5jaGluZ1xuICAgICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKCdBV1M6OlN0ZXBGdW5jdGlvbnM6OlN0YXRlTWFjaGluZScsIDEpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQWNjdXJhY3kgY29tcGFyaXNvbiBiZXR3ZWVuIGNodW5rZWQgYW5kIG5vbi1jaHVua2VkJywgKCkgPT4ge1xuICAgIHRlc3QoJ2JvdGggd29ya2Zsb3dzIHVzZSBzYW1lIGNsYXNzaWZpY2F0aW9uIExhbWJkYSBmdW5jdGlvbicsICgpID0+IHtcbiAgICAgIC8vIFRoaXMgZW5zdXJlcyBhY2N1cmFjeSBpcyBtYWludGFpbmVkIGJlY2F1c2UgdGhlIHNhbWUgbW9kZWwgYW5kIHByb21wdCBhcmUgdXNlZFxuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IGNodW5raW5nU3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0FjY3VyYWN5U3RhY2snKTtcbiAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKGNodW5raW5nU3RhY2ssICdBY2N1cmFjeVRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjbGFzc2lmaWNhdGlvbkJlZHJvY2tNb2RlbDoge1xuICAgICAgICAgIGZtTW9kZWxJZDogRm91bmRhdGlvbk1vZGVsSWRlbnRpZmllci5BTlRIUk9QSUNfQ0xBVURFXzNfSEFJS1VfMjAyNDAzMDdfVjFfMCxcbiAgICAgICAgICB1c2VDcm9zc1JlZ2lvbkluZmVyZW5jZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soY2h1bmtpbmdTdGFjayk7XG5cbiAgICAgIC8vIFZlcmlmeSB0aGUgY2xhc3NpZmljYXRpb24gTGFtYmRhIHVzZXMgdGhlIHNwZWNpZmllZCBtb2RlbFxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLCB7XG4gICAgICAgIEVudmlyb25tZW50OiB7XG4gICAgICAgICAgVmFyaWFibGVzOiB7XG4gICAgICAgICAgICBNT0RFTF9JRDogJ2FudGhyb3BpYy5jbGF1ZGUtMy1oYWlrdS0yMDI0MDMwNy12MTowJyxcbiAgICAgICAgICAgIElOVk9LRV9UWVBFOiAnY2xhc3NpZmljYXRpb24nLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2N1c3RvbSBjbGFzc2lmaWNhdGlvbiBwcm9tcHQgaXMgdXNlZCBmb3IgYm90aCBjaHVua2VkIGFuZCBub24tY2h1bmtlZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGN1c3RvbVByb21wdCA9ICdDdXN0b20gY2xhc3NpZmljYXRpb24gcHJvbXB0IGZvciB0ZXN0aW5nJztcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBjaHVua2luZ1N0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdDdXN0b21Qcm9tcHRTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3NpbmcoY2h1bmtpbmdTdGFjaywgJ0N1c3RvbVByb21wdFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjbGFzc2lmaWNhdGlvblByb21wdDogY3VzdG9tUHJvbXB0LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKGNodW5raW5nU3RhY2spO1xuXG4gICAgICAvLyBWZXJpZnkgdGhlIGN1c3RvbSBwcm9tcHQgaXMgc2V0XG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICAgICAgRW52aXJvbm1lbnQ6IHtcbiAgICAgICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgICAgIFBST01QVDogY3VzdG9tUHJvbXB0LFxuICAgICAgICAgICAgSU5WT0tFX1RZUEU6ICdjbGFzc2lmaWNhdGlvbicsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5cbmRlc2NyaWJlKCdDb25maWd1cmF0aW9uIHZhbGlkYXRpb24nLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdJbnZhbGlkIGNvbmZpZ3VyYXRpb24gcmVqZWN0aW9uJywgKCkgPT4ge1xuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgY2h1bmtTaXplIDw9IDAnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0ludmFsaWRDaHVua1NpemVTdGFjaycpO1xuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0ludmFsaWRDaHVua1NpemVUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ2ZpeGVkLXBhZ2VzJyxcbiAgICAgICAgICAgIGNodW5rU2l6ZTogMCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IGNodW5rU2l6ZSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG5lZ2F0aXZlIGNodW5rU2l6ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnTmVnYXRpdmVDaHVua1NpemVTdGFjaycpO1xuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ05lZ2F0aXZlQ2h1bmtTaXplVGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgc3RyYXRlZ3k6ICdmaXhlZC1wYWdlcycsXG4gICAgICAgICAgICBjaHVua1NpemU6IC0xMCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IGNodW5rU2l6ZSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG5lZ2F0aXZlIG92ZXJsYXBQYWdlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnTmVnYXRpdmVPdmVybGFwU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdOZWdhdGl2ZU92ZXJsYXBUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ2ZpeGVkLXBhZ2VzJyxcbiAgICAgICAgICAgIGNodW5rU2l6ZTogNTAsXG4gICAgICAgICAgICBvdmVybGFwUGFnZXM6IC01LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkudG9UaHJvdygnQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogb3ZlcmxhcFBhZ2VzIG11c3QgYmUgbm9uLW5lZ2F0aXZlJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG92ZXJsYXBQYWdlcyA+PSBjaHVua1NpemUnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ092ZXJsYXBUb29MYXJnZVN0YWNrJyk7XG5cbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHN0YWNrLCAnT3ZlcmxhcFRvb0xhcmdlVGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgc3RyYXRlZ3k6ICdmaXhlZC1wYWdlcycsXG4gICAgICAgICAgICBjaHVua1NpemU6IDUwLFxuICAgICAgICAgICAgb3ZlcmxhcFBhZ2VzOiA1MCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG92ZXJsYXBQYWdlcyBtdXN0IGJlIGxlc3MgdGhhbiBjaHVua1NpemUnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgcGFnZVRocmVzaG9sZCA8PSAwJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdJbnZhbGlkUGFnZVRocmVzaG9sZFN0YWNrJyk7XG5cbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHN0YWNrLCAnSW52YWxpZFBhZ2VUaHJlc2hvbGRUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ2ZpeGVkLXBhZ2VzJyxcbiAgICAgICAgICAgIHBhZ2VUaHJlc2hvbGQ6IDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBwYWdlVGhyZXNob2xkIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgdG9rZW5UaHJlc2hvbGQgPD0gMCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnSW52YWxpZFRva2VuVGhyZXNob2xkU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdJbnZhbGlkVG9rZW5UaHJlc2hvbGRUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ3Rva2VuLWJhc2VkJyxcbiAgICAgICAgICAgIHRva2VuVGhyZXNob2xkOiAtMTAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkudG9UaHJvdygnQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogdG9rZW5UaHJlc2hvbGQgbXVzdCBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgndGhyb3dzIGVycm9yIGZvciBtYXhUb2tlbnNQZXJDaHVuayA8PSAwJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdJbnZhbGlkTWF4VG9rZW5zU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdJbnZhbGlkTWF4VG9rZW5zVGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgc3RyYXRlZ3k6ICd0b2tlbi1iYXNlZCcsXG4gICAgICAgICAgICBtYXhUb2tlbnNQZXJDaHVuazogMCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1heFRva2Vuc1BlckNodW5rIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgbmVnYXRpdmUgb3ZlcmxhcFRva2VucycsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnTmVnYXRpdmVPdmVybGFwVG9rZW5zU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdOZWdhdGl2ZU92ZXJsYXBUb2tlbnNUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ3Rva2VuLWJhc2VkJyxcbiAgICAgICAgICAgIG92ZXJsYXBUb2tlbnM6IC0xMDAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkudG9UaHJvdygnQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogb3ZlcmxhcFRva2VucyBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgndGhyb3dzIGVycm9yIGZvciBvdmVybGFwVG9rZW5zID49IG1heFRva2Vuc1BlckNodW5rJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdPdmVybGFwVG9rZW5zVG9vTGFyZ2VTdGFjaycpO1xuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ092ZXJsYXBUb2tlbnNUb29MYXJnZVRlc3QnLCB7XG4gICAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICAgIHN0cmF0ZWd5OiAndG9rZW4tYmFzZWQnLFxuICAgICAgICAgICAgbWF4VG9rZW5zUGVyQ2h1bms6IDUwMDAwLFxuICAgICAgICAgICAgb3ZlcmxhcFRva2VuczogNTAwMDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBvdmVybGFwVG9rZW5zIG11c3QgYmUgbGVzcyB0aGFuIG1heFRva2Vuc1BlckNodW5rJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG1heFBhZ2VzUGVyQ2h1bmsgPD0gMCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnSW52YWxpZE1heFBhZ2VzU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdJbnZhbGlkTWF4UGFnZXNUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgICAgICBtYXhQYWdlc1BlckNodW5rOiAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfSkudG9UaHJvdygnQ2h1bmtpbmdDb25maWcgdmFsaWRhdGlvbiBlcnJvcjogbWF4UGFnZXNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIHRhcmdldFRva2Vuc1BlckNodW5rIDw9IDAnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0ludmFsaWRUYXJnZXRUb2tlbnNTdGFjaycpO1xuXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0ludmFsaWRUYXJnZXRUb2tlbnNUZXN0Jywge1xuICAgICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgICAgICB0YXJnZXRUb2tlbnNQZXJDaHVuazogLTEsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiB0YXJnZXRUb2tlbnNQZXJDaHVuayBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG1heENvbmN1cnJlbmN5IDw9IDAnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0ludmFsaWRNYXhDb25jdXJyZW5jeVN0YWNrJyk7XG5cbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHN0YWNrLCAnSW52YWxpZE1heENvbmN1cnJlbmN5VGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgbWF4Q29uY3VycmVuY3k6IDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KS50b1Rocm93KCdDaHVua2luZ0NvbmZpZyB2YWxpZGF0aW9uIGVycm9yOiBtYXhDb25jdXJyZW5jeSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd0aHJvd3MgZXJyb3IgZm9yIG1pblN1Y2Nlc3NUaHJlc2hvbGQgPCAwJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdJbnZhbGlkTWluVGhyZXNob2xkTG93U3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdJbnZhbGlkTWluVGhyZXNob2xkTG93VGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgbWluU3VjY2Vzc1RocmVzaG9sZDogLTAuMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1pblN1Y2Nlc3NUaHJlc2hvbGQgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgbWluU3VjY2Vzc1RocmVzaG9sZCA+IDEnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0ludmFsaWRNaW5UaHJlc2hvbGRIaWdoU3RhY2snKTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdJbnZhbGlkTWluVGhyZXNob2xkSGlnaFRlc3QnLCB7XG4gICAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICAgIG1pblN1Y2Nlc3NUaHJlc2hvbGQ6IDEuNSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLnRvVGhyb3coJ0NodW5raW5nQ29uZmlnIHZhbGlkYXRpb24gZXJyb3I6IG1pblN1Y2Nlc3NUaHJlc2hvbGQgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZhbGlkIGNvbmZpZ3VyYXRpb24gYWNjZXB0YW5jZScsICgpID0+IHtcbiAgICB0ZXN0KCdhY2NlcHRzIHZhbGlkIGJvdW5kYXJ5IHZhbHVlcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnVmFsaWRCb3VuZGFyeVN0YWNrJyk7XG5cbiAgICAgIC8vIFNob3VsZCBub3QgdGhyb3dcbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHN0YWNrLCAnVmFsaWRCb3VuZGFyeVRlc3QnLCB7XG4gICAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICAgIHN0cmF0ZWd5OiAnZml4ZWQtcGFnZXMnLFxuICAgICAgICAgICAgY2h1bmtTaXplOiAxLCAvLyBtaW5pbXVtIHZhbGlkXG4gICAgICAgICAgICBvdmVybGFwUGFnZXM6IDAsIC8vIG1pbmltdW0gdmFsaWRcbiAgICAgICAgICAgIHBhZ2VUaHJlc2hvbGQ6IDEsIC8vIG1pbmltdW0gdmFsaWRcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdhY2NlcHRzIG1pblN1Y2Nlc3NUaHJlc2hvbGQgYXQgYm91bmRhcmllcycsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjazEgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ01pblRocmVzaG9sZDBTdGFjaycpO1xuICAgICAgY29uc3Qgc3RhY2syID0gbmV3IFN0YWNrKHRlc3RBcHAsICdNaW5UaHJlc2hvbGQxU3RhY2snKTtcblxuICAgICAgLy8gU2hvdWxkIG5vdCB0aHJvdyBmb3IgMFxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2sxLCAnTWluVGhyZXNob2xkMFRlc3QnLCB7XG4gICAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICAgIG1pblN1Y2Nlc3NUaHJlc2hvbGQ6IDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICB9KS5ub3QudG9UaHJvdygpO1xuXG4gICAgICAvLyBTaG91bGQgbm90IHRocm93IGZvciAxXG4gICAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjazIsICdNaW5UaHJlc2hvbGQxVGVzdCcsIHtcbiAgICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgICAgbWluU3VjY2Vzc1RocmVzaG9sZDogMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdWYWxpZGF0aW9uIHNraXBwZWQgd2hlbiBjaHVua2luZyBkaXNhYmxlZCcsICgpID0+IHtcbiAgICB0ZXN0KCdkb2VzIG5vdCB2YWxpZGF0ZSBjb25maWcgd2hlbiBlbmFibGVDaHVua2luZyBpcyBmYWxzZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnQ2h1bmtpbmdEaXNhYmxlZFN0YWNrJyk7XG5cbiAgICAgIC8vIFNob3VsZCBub3QgdGhyb3cgZXZlbiB3aXRoIGludmFsaWQgY29uZmlnIGJlY2F1c2UgY2h1bmtpbmcgaXMgZGlzYWJsZWRcbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBCZWRyb2NrRG9jdW1lbnRQcm9jZXNzaW5nKHN0YWNrLCAnQ2h1bmtpbmdEaXNhYmxlZFRlc3QnLCB7XG4gICAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IGZhbHNlLFxuICAgICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBjaHVua1NpemU6IC0xMCwgLy8gSW52YWxpZCBidXQgc2hvdWxkIGJlIGlnbm9yZWRcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdkb2VzIG5vdCB2YWxpZGF0ZSBjb25maWcgd2hlbiBlbmFibGVDaHVua2luZyBpcyB1bmRlZmluZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0NodW5raW5nVW5kZWZpbmVkU3RhY2snKTtcblxuICAgICAgLy8gU2hvdWxkIG5vdCB0aHJvdyBldmVuIHdpdGggaW52YWxpZCBjb25maWcgYmVjYXVzZSBjaHVua2luZyBpcyBub3QgZW5hYmxlZFxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdDaHVua2luZ1VuZGVmaW5lZFRlc3QnLCB7XG4gICAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICAgIGNodW5rU2l6ZTogMCwgLy8gSW52YWxpZCBidXQgc2hvdWxkIGJlIGlnbm9yZWRcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdDb25maWd1cmF0aW9uIHByZWNlZGVuY2UnLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdEZWZhdWx0IHZhbHVlcyBhcHBsaWVkJywgKCkgPT4ge1xuICAgIHRlc3QoJ3VzZXMgZGVmYXVsdCBzdHJhdGVneSB3aGVuIG5vdCBzcGVjaWZpZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0RlZmF1bHRTdHJhdGVneVN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0RlZmF1bHRTdHJhdGVneVRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge30sIC8vIEVtcHR5IGNvbmZpZywgc2hvdWxkIHVzZSBkZWZhdWx0c1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICAgIGNvbnN0IGxhbWJkYXMgPSB0ZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDgsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5DSFVOS0lOR19TVFJBVEVHWScsICdoeWJyaWQnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3VzZXMgZGVmYXVsdCBwYWdlVGhyZXNob2xkIHdoZW4gbm90IHNwZWNpZmllZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnRGVmYXVsdFBhZ2VUaHJlc2hvbGRTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdEZWZhdWx0UGFnZVRocmVzaG9sZFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnZml4ZWQtcGFnZXMnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICAgIGNvbnN0IGxhbWJkYXMgPSB0ZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDgsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5QQUdFX1RIUkVTSE9MRCcsICcxMDAnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3VzZXMgZGVmYXVsdCB0b2tlblRocmVzaG9sZCB3aGVuIG5vdCBzcGVjaWZpZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0RlZmF1bHRUb2tlblRocmVzaG9sZFN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0RlZmF1bHRUb2tlblRocmVzaG9sZFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAndG9rZW4tYmFzZWQnLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICAgIGNvbnN0IGxhbWJkYXMgPSB0ZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDgsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5UT0tFTl9USFJFU0hPTEQnLCAnMTUwMDAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd1c2VzIGRlZmF1bHQgbWF4Q29uY3VycmVuY3kgd2hlbiBub3Qgc3BlY2lmaWVkJywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdEZWZhdWx0Q29uY3VycmVuY3lTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdEZWZhdWx0Q29uY3VycmVuY3lUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBwcm9jZXNzaW5nTW9kZTogJ3BhcmFsbGVsJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBWZXJpZnkgc3RhY2sgaXMgY3JlYXRlZCBzdWNjZXNzZnVsbHkgd2l0aCBkZWZhdWx0IG1heENvbmN1cnJlbmN5IG9mIDEwXG4gICAgICBleHBlY3Qoc3RhY2spLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdDdXN0b20gY29uZmlndXJhdGlvbiBvdmVycmlkZXMgZGVmYXVsdHMnLCAoKSA9PiB7XG4gICAgdGVzdCgnY3VzdG9tIHN0cmF0ZWd5IG92ZXJyaWRlcyBkZWZhdWx0JywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdDdXN0b21TdHJhdGVneVN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0N1c3RvbVN0cmF0ZWd5VGVzdCcsIHtcbiAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgc3RyYXRlZ3k6ICd0b2tlbi1iYXNlZCcsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgbGFtYmRhcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLkNIVU5LSU5HX1NUUkFURUdZJywgJ3Rva2VuLWJhc2VkJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdjdXN0b20gcGFnZVRocmVzaG9sZCBvdmVycmlkZXMgZGVmYXVsdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnQ3VzdG9tUGFnZVRocmVzaG9sZFN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0N1c3RvbVBhZ2VUaHJlc2hvbGRUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBwYWdlVGhyZXNob2xkOiA1MCxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gICAgICBjb25zdCBsYW1iZGFzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyk7XG4gICAgICBjb25zdCBjaHVua2luZ0xhbWJkYSA9IE9iamVjdC52YWx1ZXMobGFtYmRhcykuZmluZCgobGFtYmRhOiBhbnkpID0+XG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLlJ1bnRpbWUgPT09ICdweXRob24zLjEzJyAmJlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5NZW1vcnlTaXplID09PSAyMDQ4LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0hhdmVQcm9wZXJ0eSgnUHJvcGVydGllcy5FbnZpcm9ubWVudC5WYXJpYWJsZXMuUEFHRV9USFJFU0hPTEQnLCAnNTAnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2N1c3RvbSB0b2tlblRocmVzaG9sZCBvdmVycmlkZXMgZGVmYXVsdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHRlc3RBcHAgPSBjcmVhdGVUZXN0QXBwKCk7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjayh0ZXN0QXBwLCAnQ3VzdG9tVG9rZW5UaHJlc2hvbGRTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdDdXN0b21Ub2tlblRocmVzaG9sZFRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHRva2VuVGhyZXNob2xkOiAyMDAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgbGFtYmRhcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLlRPS0VOX1RIUkVTSE9MRCcsICcyMDAwMDAnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2N1c3RvbSBjaHVua1NpemUgb3ZlcnJpZGVzIGRlZmF1bHQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0N1c3RvbUNodW5rU2l6ZVN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0N1c3RvbUNodW5rU2l6ZVRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnZml4ZWQtcGFnZXMnLFxuICAgICAgICAgIGNodW5rU2l6ZTogMjUsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgbGFtYmRhcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLkNIVU5LX1NJWkUnLCAnMjUnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2N1c3RvbSBtYXhQYWdlc1BlckNodW5rIG92ZXJyaWRlcyBkZWZhdWx0JywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdDdXN0b21NYXhQYWdlc1N0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0N1c3RvbU1heFBhZ2VzVGVzdCcsIHtcbiAgICAgICAgZW5hYmxlQ2h1bmtpbmc6IHRydWUsXG4gICAgICAgIGNodW5raW5nQ29uZmlnOiB7XG4gICAgICAgICAgc3RyYXRlZ3k6ICdoeWJyaWQnLFxuICAgICAgICAgIG1heFBhZ2VzUGVyQ2h1bms6IDc1LFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICAgIGNvbnN0IGxhbWJkYXMgPSB0ZW1wbGF0ZS5maW5kUmVzb3VyY2VzKCdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nKTtcbiAgICAgIGNvbnN0IGNodW5raW5nTGFtYmRhID0gT2JqZWN0LnZhbHVlcyhsYW1iZGFzKS5maW5kKChsYW1iZGE6IGFueSkgPT5cbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuUnVudGltZSA9PT0gJ3B5dGhvbjMuMTMnICYmXG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLk1lbW9yeVNpemUgPT09IDIwNDgsXG4gICAgICApO1xuXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5NQVhfUEFHRVNfUEVSX0NIVU5LJywgJzc1Jyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdkZWZhdWx0IG1heFBhZ2VzUGVyQ2h1bmsgaXMgOTkgdG8gc3RheSB1bmRlciBCZWRyb2NrIDEwMC1wYWdlIGxpbWl0JywgKCkgPT4ge1xuICAgICAgY29uc3QgdGVzdEFwcCA9IGNyZWF0ZVRlc3RBcHAoKTtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICdEZWZhdWx0TWF4UGFnZXNTdGFjaycpO1xuICAgICAgbmV3IEJlZHJvY2tEb2N1bWVudFByb2Nlc3Npbmcoc3RhY2ssICdEZWZhdWx0TWF4UGFnZXNUZXN0Jywge1xuICAgICAgICBlbmFibGVDaHVua2luZzogdHJ1ZSxcbiAgICAgICAgY2h1bmtpbmdDb25maWc6IHtcbiAgICAgICAgICBzdHJhdGVneTogJ2h5YnJpZCcsXG4gICAgICAgICAgLy8gbWF4UGFnZXNQZXJDaHVuayBub3Qgc3BlY2lmaWVkIC0gc2hvdWxkIGRlZmF1bHQgdG8gOTlcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gICAgICBjb25zdCBsYW1iZGFzID0gdGVtcGxhdGUuZmluZFJlc291cmNlcygnQVdTOjpMYW1iZGE6OkZ1bmN0aW9uJyk7XG4gICAgICBjb25zdCBjaHVua2luZ0xhbWJkYSA9IE9iamVjdC52YWx1ZXMobGFtYmRhcykuZmluZCgobGFtYmRhOiBhbnkpID0+XG4gICAgICAgIGxhbWJkYS5Qcm9wZXJ0aWVzLlJ1bnRpbWUgPT09ICdweXRob24zLjEzJyAmJlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5NZW1vcnlTaXplID09PSAyMDQ4LFxuICAgICAgKTtcblxuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0JlRGVmaW5lZCgpO1xuICAgICAgLy8gRGVmYXVsdCBzaG91bGQgYmUgOTksIG5vdCAxMDAsIGJlY2F1c2UgQmVkcm9jayBoYXMgYSBoYXJkIGxpbWl0IG9mIDEwMCBwYWdlcyBwZXIgUERGXG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5NQVhfUEFHRVNfUEVSX0NIVU5LJywgJzk5Jyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdjdXN0b20gdGFyZ2V0VG9rZW5zUGVyQ2h1bmsgb3ZlcnJpZGVzIGRlZmF1bHQnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0N1c3RvbVRhcmdldFRva2Vuc1N0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0N1c3RvbVRhcmdldFRva2Vuc1Rlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnaHlicmlkJyxcbiAgICAgICAgICB0YXJnZXRUb2tlbnNQZXJDaHVuazogNjAwMDAsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgbGFtYmRhcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLlRBUkdFVF9UT0tFTlNfUEVSX0NIVU5LJywgJzYwMDAwJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdhbGwgY3VzdG9tIHZhbHVlcyBvdmVycmlkZSBhbGwgZGVmYXVsdHMnLCAoKSA9PiB7XG4gICAgICBjb25zdCB0ZXN0QXBwID0gY3JlYXRlVGVzdEFwcCgpO1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodGVzdEFwcCwgJ0FsbEN1c3RvbVN0YWNrJyk7XG4gICAgICBuZXcgQmVkcm9ja0RvY3VtZW50UHJvY2Vzc2luZyhzdGFjaywgJ0FsbEN1c3RvbVRlc3QnLCB7XG4gICAgICAgIGVuYWJsZUNodW5raW5nOiB0cnVlLFxuICAgICAgICBjaHVua2luZ0NvbmZpZzoge1xuICAgICAgICAgIHN0cmF0ZWd5OiAnZml4ZWQtcGFnZXMnLFxuICAgICAgICAgIHBhZ2VUaHJlc2hvbGQ6IDIwMCxcbiAgICAgICAgICB0b2tlblRocmVzaG9sZDogMzAwMDAwLFxuICAgICAgICAgIGNodW5rU2l6ZTogNzUsXG4gICAgICAgICAgb3ZlcmxhcFBhZ2VzOiAxMCxcbiAgICAgICAgICBtYXhUb2tlbnNQZXJDaHVuazogMTUwMDAwLFxuICAgICAgICAgIG92ZXJsYXBUb2tlbnM6IDEwMDAwLFxuICAgICAgICAgIHRhcmdldFRva2Vuc1BlckNodW5rOiAxMjAwMDAsXG4gICAgICAgICAgbWF4UGFnZXNQZXJDaHVuazogMTUwLFxuICAgICAgICAgIHByb2Nlc3NpbmdNb2RlOiAnc2VxdWVudGlhbCcsXG4gICAgICAgICAgbWF4Q29uY3VycmVuY3k6IDUsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgY29uc3QgbGFtYmRhcyA9IHRlbXBsYXRlLmZpbmRSZXNvdXJjZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicpO1xuICAgICAgY29uc3QgY2h1bmtpbmdMYW1iZGEgPSBPYmplY3QudmFsdWVzKGxhbWJkYXMpLmZpbmQoKGxhbWJkYTogYW55KSA9PlxuICAgICAgICBsYW1iZGEuUHJvcGVydGllcy5SdW50aW1lID09PSAncHl0aG9uMy4xMycgJiZcbiAgICAgICAgbGFtYmRhLlByb3BlcnRpZXMuTWVtb3J5U2l6ZSA9PT0gMjA0OCxcbiAgICAgICk7XG5cbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLkNIVU5LSU5HX1NUUkFURUdZJywgJ2ZpeGVkLXBhZ2VzJyk7XG4gICAgICBleHBlY3QoY2h1bmtpbmdMYW1iZGEpLnRvSGF2ZVByb3BlcnR5KCdQcm9wZXJ0aWVzLkVudmlyb25tZW50LlZhcmlhYmxlcy5QQUdFX1RIUkVTSE9MRCcsICcyMDAnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLlRPS0VOX1RIUkVTSE9MRCcsICczMDAwMDAnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLkNIVU5LX1NJWkUnLCAnNzUnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLk9WRVJMQVBfUEFHRVMnLCAnMTAnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLk1BWF9UT0tFTlNfUEVSX0NIVU5LJywgJzE1MDAwMCcpO1xuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0hhdmVQcm9wZXJ0eSgnUHJvcGVydGllcy5FbnZpcm9ubWVudC5WYXJpYWJsZXMuT1ZFUkxBUF9UT0tFTlMnLCAnMTAwMDAnKTtcbiAgICAgIGV4cGVjdChjaHVua2luZ0xhbWJkYSkudG9IYXZlUHJvcGVydHkoJ1Byb3BlcnRpZXMuRW52aXJvbm1lbnQuVmFyaWFibGVzLlRBUkdFVF9UT0tFTlNfUEVSX0NIVU5LJywgJzEyMDAwMCcpO1xuICAgICAgZXhwZWN0KGNodW5raW5nTGFtYmRhKS50b0hhdmVQcm9wZXJ0eSgnUHJvcGVydGllcy5FbnZpcm9ubWVudC5WYXJpYWJsZXMuTUFYX1BBR0VTX1BFUl9DSFVOSycsICcxNTAnKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==