@aws-cdk/integ-runner 2.202.2 → 2.203.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_LICENSES +26 -0
- package/lib/cli.d.ts.map +1 -1
- package/lib/cli.js +3 -2
- package/lib/engines/toolkit-lib.d.ts +1 -1
- package/lib/engines/toolkit-lib.d.ts.map +1 -1
- package/lib/engines/toolkit-lib.js +11 -11
- package/lib/files.d.ts +9 -0
- package/lib/files.d.ts.map +1 -0
- package/lib/files.js +51 -0
- package/lib/index.js +218 -182
- package/lib/runner/{cdk-integ-helper.d.ts → cdk-test-app.d.ts} +90 -114
- package/lib/runner/cdk-test-app.d.ts.map +1 -0
- package/lib/runner/cdk-test-app.js +584 -0
- package/lib/runner/engine.d.ts +2 -2
- package/lib/runner/engine.d.ts.map +1 -1
- package/lib/runner/engine.js +2 -2
- package/lib/runner/index.d.ts +1 -1
- package/lib/runner/index.d.ts.map +1 -1
- package/lib/runner/index.js +2 -2
- package/lib/runner/integ-test-runner.d.ts +36 -36
- package/lib/runner/integ-test-runner.d.ts.map +1 -1
- package/lib/runner/integ-test-runner.js +172 -235
- package/lib/runner/integ-test-suite.d.ts +6 -11
- package/lib/runner/integ-test-suite.d.ts.map +1 -1
- package/lib/runner/integ-test-suite.js +14 -20
- package/lib/runner/integration-tests.d.ts +12 -3
- package/lib/runner/integration-tests.d.ts.map +1 -1
- package/lib/runner/integration-tests.js +32 -8
- package/lib/runner/snapshot-test-runner.d.ts +19 -22
- package/lib/runner/snapshot-test-runner.d.ts.map +1 -1
- package/lib/runner/snapshot-test-runner.js +47 -75
- package/lib/workers/extract/extract_worker.d.ts.map +1 -1
- package/lib/workers/extract/extract_worker.js +65 -78
- package/lib/workers/extract/index.js +228344 -227587
- package/lib/workers/integ-test-worker.d.ts.map +1 -1
- package/lib/workers/integ-test-worker.js +3 -2
- package/package.json +5 -5
- package/lib/runner/cdk-integ-helper.d.ts.map +0 -1
- package/lib/runner/cdk-integ-helper.js +0 -525
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DEFAULT_ARGS = exports.DEFAULT_SYNTH_OPTIONS = exports.CdkTestApp = void 0;
|
|
37
|
+
exports.currentlyRecommendedAwsCdkLibFlags = currentlyRecommendedAwsCdkLibFlags;
|
|
38
|
+
/* eslint-disable @cdklabs/no-literal-partition */
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const cloud_assembly_api_1 = require("@aws-cdk/cloud-assembly-api");
|
|
41
|
+
const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema");
|
|
42
|
+
const fs = __importStar(require("fs-extra"));
|
|
43
|
+
const integ_test_suite_1 = require("./integ-test-suite");
|
|
44
|
+
const logger = __importStar(require("../logger"));
|
|
45
|
+
const recommendedFlagsFile = __importStar(require("../recommended-feature-flags.json"));
|
|
46
|
+
const utils_1 = require("../utils");
|
|
47
|
+
const cloud_assembly_1 = require("./private/cloud-assembly");
|
|
48
|
+
const integ_manifest_1 = require("./private/integ-manifest");
|
|
49
|
+
const test_specific_context_1 = require("./private/test-specific-context");
|
|
50
|
+
const toolkit_lib_1 = require("../engines/toolkit-lib");
|
|
51
|
+
const files_1 = require("../files");
|
|
52
|
+
const DESTRUCTIVE_CHANGES = '!!DESTRUCTIVE_CHANGES:';
|
|
53
|
+
/**
|
|
54
|
+
* Class with some helper routines for running CDK snapshots and integration tests.
|
|
55
|
+
*
|
|
56
|
+
* A "golden snapshot" is the snapshot that is stored permanently in version
|
|
57
|
+
* control, that new runs are compared against (stored in a directory named
|
|
58
|
+
* `<test-name>.snapshot`).
|
|
59
|
+
*
|
|
60
|
+
* This is as opposed to other snapshots, which can be generated for example
|
|
61
|
+
* temporarily in a temporary directory, to compare agains the golden snapshot.
|
|
62
|
+
*/
|
|
63
|
+
class CdkTestApp {
|
|
64
|
+
options;
|
|
65
|
+
testSpecificContext;
|
|
66
|
+
static async forGoldenSnapshot(options) {
|
|
67
|
+
return CdkTestApp.create({
|
|
68
|
+
...options,
|
|
69
|
+
outputDirectoryNameTemplate: '{testBaseName}.snapshot',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
static async forComparison(options) {
|
|
73
|
+
return CdkTestApp.create({
|
|
74
|
+
...options,
|
|
75
|
+
outputDirectoryNameTemplate: 'cdk-integ.out.{testBaseName}.snapshot',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
static async forSpecificDirectory(options) {
|
|
79
|
+
return CdkTestApp.create(options);
|
|
80
|
+
}
|
|
81
|
+
static async forDeployment(options) {
|
|
82
|
+
return CdkTestApp.create({
|
|
83
|
+
...options,
|
|
84
|
+
outputDirectoryNameTemplate: 'cdk-integ.out.deploy.{testBaseName}.snapshot',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
static async create(options) {
|
|
88
|
+
const ctx = await (0, test_specific_context_1.findTestSpecificContext)(options.test.absoluteFileName);
|
|
89
|
+
const app = new CdkTestApp(options, ctx);
|
|
90
|
+
return app;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* An instance of the CDK CLI
|
|
94
|
+
*/
|
|
95
|
+
cdk;
|
|
96
|
+
outputDirectory;
|
|
97
|
+
/**
|
|
98
|
+
* Default options to pass to the CDK CLI
|
|
99
|
+
*/
|
|
100
|
+
defaultArgs = {
|
|
101
|
+
pathMetadata: false,
|
|
102
|
+
assetMetadata: false,
|
|
103
|
+
versionReporting: false,
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* The profile to use for the CDK CLI calls
|
|
107
|
+
*/
|
|
108
|
+
profile;
|
|
109
|
+
/**
|
|
110
|
+
* Show output from the integ test run.
|
|
111
|
+
*/
|
|
112
|
+
showOutput;
|
|
113
|
+
test;
|
|
114
|
+
synthReproCommand = '';
|
|
115
|
+
_destructiveChanges;
|
|
116
|
+
legacyContext;
|
|
117
|
+
_testSuite;
|
|
118
|
+
_legacyEnableLookups;
|
|
119
|
+
appCommand;
|
|
120
|
+
hasValidRegion;
|
|
121
|
+
constructor(options, testSpecificContext) {
|
|
122
|
+
this.options = options;
|
|
123
|
+
this.testSpecificContext = testSpecificContext;
|
|
124
|
+
this.hasValidRegion = options.region !== cloud_assembly_api_1.UNKNOWN_REGION;
|
|
125
|
+
this.test = options.test;
|
|
126
|
+
const outputDirectoryNameTemplate = options.outputDirectoryNameTemplate;
|
|
127
|
+
this.outputDirectory = (0, files_1.absAwareJoin)(this.test.testDirectory, this.test.specializeTemplate(outputDirectoryNameTemplate));
|
|
128
|
+
this.profile = options.profile;
|
|
129
|
+
this.showOutput = options.showOutput ?? false;
|
|
130
|
+
this.cdk = options.cdk ?? new toolkit_lib_1.ToolkitLibRunnerEngine({
|
|
131
|
+
workingDirectory: this.test.workingDirectory,
|
|
132
|
+
showOutput: options.showOutput,
|
|
133
|
+
env: options.env,
|
|
134
|
+
region: options.region,
|
|
135
|
+
profile: options.profile,
|
|
136
|
+
proxy: options.proxy,
|
|
137
|
+
caBundlePath: options.caBundlePath,
|
|
138
|
+
});
|
|
139
|
+
this.appCommand = this.test.specializeTemplate(this.test.appCommandTemplate);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Configure the legacy enableLookups value to use when generating the actual snapshot.
|
|
143
|
+
*
|
|
144
|
+
* Must be set before using snapshot methods.
|
|
145
|
+
*/
|
|
146
|
+
configureLegacyEnableLookups(enableLookups) {
|
|
147
|
+
this._legacyEnableLookups = enableLookups;
|
|
148
|
+
}
|
|
149
|
+
async hasOutput() {
|
|
150
|
+
return (await fs.pathExists(this.outputDirectory)) && (await fs.pathExists(path.join(this.outputDirectory, 'manifest.json')));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Return the test cases inside the output
|
|
154
|
+
*/
|
|
155
|
+
testCases() {
|
|
156
|
+
return this.testSuite.testSuite;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The test suite from the output
|
|
160
|
+
*/
|
|
161
|
+
get testSuite() {
|
|
162
|
+
if (!this._testSuite) {
|
|
163
|
+
throw new Error('Synthesize first!');
|
|
164
|
+
}
|
|
165
|
+
return this._testSuite;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* If the snapshot already exists, load it
|
|
169
|
+
*/
|
|
170
|
+
async loadExistingSuite() {
|
|
171
|
+
if (this._testSuite) {
|
|
172
|
+
return this._testSuite;
|
|
173
|
+
}
|
|
174
|
+
if (await this.hasOutput()) {
|
|
175
|
+
this._testSuite = await this._loadManifest();
|
|
176
|
+
return this._testSuite;
|
|
177
|
+
}
|
|
178
|
+
if (this.options.TESTING_forceReadLegacyTestSuite) {
|
|
179
|
+
return this._loadLegacyTestSuite();
|
|
180
|
+
}
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
async synthForSnapshotComparison(enableLookupsGuess) {
|
|
184
|
+
this.configureLegacyEnableLookups(enableLookupsGuess);
|
|
185
|
+
const suite = await this.synth(this.getContext('snapshot'), exports.DEFAULT_SYNTH_OPTIONS.env);
|
|
186
|
+
// Check if the enableLookups value has changed between the golden
|
|
187
|
+
// snapshot and the actual snapshot. If it has, we need to re-synth the
|
|
188
|
+
// actual snapshot with the new enableLookups value.
|
|
189
|
+
//
|
|
190
|
+
// See `synthActualSnapshot` for a description of why this is necessary.
|
|
191
|
+
const actualEnableLookups = suite.enableLookups ?? false;
|
|
192
|
+
if (actualEnableLookups !== this._legacyEnableLookups && this._legacyEnableLookups !== 'dont-care') {
|
|
193
|
+
this.configureLegacyEnableLookups(actualEnableLookups);
|
|
194
|
+
return this.synth(this.getContext('snapshot'), exports.DEFAULT_SYNTH_OPTIONS.env);
|
|
195
|
+
}
|
|
196
|
+
return suite;
|
|
197
|
+
}
|
|
198
|
+
async synthForGoldenSnapshot(destructiveChanges, enableLookups) {
|
|
199
|
+
this.configureLegacyEnableLookups(enableLookups);
|
|
200
|
+
await this.synth(this.getContext('snapshot'), exports.DEFAULT_SYNTH_OPTIONS.env);
|
|
201
|
+
await this.cleanupGoldenSnapshot(destructiveChanges);
|
|
202
|
+
return this.testSuite;
|
|
203
|
+
}
|
|
204
|
+
async synthForDeployment() {
|
|
205
|
+
this.configureLegacyEnableLookups('dont-care');
|
|
206
|
+
await this.synth(this.getContext('deployment'), {});
|
|
207
|
+
return this.testSuite;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* For a given cloud assembly return a collection of all templates
|
|
211
|
+
* that should be part of the snapshot and any required meta data.
|
|
212
|
+
*
|
|
213
|
+
* @param cloudAssemblyDir - The directory of the cloud assembly to look for snapshots
|
|
214
|
+
* @param pickStacks - Pick only these stacks from the cloud assembly
|
|
215
|
+
* @returns A SnapshotAssembly, the collection of all templates in this snapshot and required meta data
|
|
216
|
+
*/
|
|
217
|
+
snapshotAssembly(pickStacks = []) {
|
|
218
|
+
const assembly = this.readAssembly(this.outputDirectory);
|
|
219
|
+
const stacks = assembly.stacks;
|
|
220
|
+
const snapshots = {};
|
|
221
|
+
for (const [stackName, stackTemplate] of Object.entries(stacks)) {
|
|
222
|
+
if (pickStacks.includes(stackName)) {
|
|
223
|
+
const manifest = cloud_assembly_1.AssemblyManifestReader.fromPath(this.outputDirectory);
|
|
224
|
+
const assets = manifest.getAssetIdsForStack(stackName);
|
|
225
|
+
snapshots[stackName] = {
|
|
226
|
+
templates: {
|
|
227
|
+
[stackName]: stackTemplate,
|
|
228
|
+
...assembly.getNestedStacksForStack(stackName),
|
|
229
|
+
},
|
|
230
|
+
assets,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return snapshots;
|
|
235
|
+
}
|
|
236
|
+
readAssembly(dir) {
|
|
237
|
+
return cloud_assembly_1.AssemblyManifestReader.fromPath(dir);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Synth the actual application to the given directory, for purposes of generating/validating a snapshot
|
|
241
|
+
*
|
|
242
|
+
* `legacyEnableLookups` is to preserve historical behavior for a while:
|
|
243
|
+
* traditionally, the application would only be seeded with context if
|
|
244
|
+
* `enableLookups` was true, and this information would come from the test
|
|
245
|
+
* definition.
|
|
246
|
+
*
|
|
247
|
+
* - Since the test definition comes from inside the app, this requires a
|
|
248
|
+
* synth just to get the test definition, and then another synth to generate
|
|
249
|
+
* the actual snapshot with the correct context, which is time consuming.
|
|
250
|
+
* - Given that the context is fixed and fake, it could always have been passed.
|
|
251
|
+
*
|
|
252
|
+
* However, the snapshot contents themselves depend on the context flag, and changing
|
|
253
|
+
* this behavior now invalidates all snapshots everywhere, which is annoying for upgrading.
|
|
254
|
+
*
|
|
255
|
+
* So we will use the behavior from the GOLDEN SNAPSHOT's test definition to
|
|
256
|
+
* determine whether to pass the context, and if the new actual snapshot has a
|
|
257
|
+
* different value for `enableLookups`, we will throw away the old snapshot and synth again.
|
|
258
|
+
*/
|
|
259
|
+
async synth(context, env) {
|
|
260
|
+
const output = this.outputDirectory;
|
|
261
|
+
// Remove the target directory, so that we don't have stale files from
|
|
262
|
+
// previous synths. Also, the runner will re-use a directory that already
|
|
263
|
+
// exists and we want force recreation (unless we are unit testing).
|
|
264
|
+
if (!this.options.TESTING_usingMocks) {
|
|
265
|
+
await fs.rm(output, { recursive: true, force: true });
|
|
266
|
+
}
|
|
267
|
+
await this.cdk.synth({
|
|
268
|
+
app: this.appCommand,
|
|
269
|
+
context,
|
|
270
|
+
env,
|
|
271
|
+
output,
|
|
272
|
+
});
|
|
273
|
+
this.setReproCommand(context, env);
|
|
274
|
+
this._testSuite = await this._loadManifest();
|
|
275
|
+
return this._testSuite;
|
|
276
|
+
}
|
|
277
|
+
async deploy(deployArgs) {
|
|
278
|
+
if (!this.hasValidRegion) {
|
|
279
|
+
throw new Error('CdkTestApp.deploy: not initialized with a valid region');
|
|
280
|
+
}
|
|
281
|
+
return this.cdk.deploy({
|
|
282
|
+
...exports.DEFAULT_ARGS,
|
|
283
|
+
...deployArgs,
|
|
284
|
+
output: this.outputDirectory,
|
|
285
|
+
profile: this.profile,
|
|
286
|
+
requireApproval: cloud_assembly_schema_1.RequireApproval.NEVER,
|
|
287
|
+
app: this.appCommand,
|
|
288
|
+
context: {
|
|
289
|
+
...this.getContext('deployment'),
|
|
290
|
+
...deployArgs?.context,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async destroy(destroyArgs) {
|
|
295
|
+
if (!this.hasValidRegion) {
|
|
296
|
+
throw new Error('CdkTestApp.destroy: not initialized with a valid region');
|
|
297
|
+
}
|
|
298
|
+
await this.cdk.destroy({
|
|
299
|
+
...exports.DEFAULT_ARGS,
|
|
300
|
+
...destroyArgs,
|
|
301
|
+
app: this.appCommand,
|
|
302
|
+
output: this.outputDirectory,
|
|
303
|
+
profile: this.profile,
|
|
304
|
+
force: true,
|
|
305
|
+
context: {
|
|
306
|
+
...this.getContext('deployment'),
|
|
307
|
+
...destroyArgs?.context,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
async watch(watchArgs, watchEvents) {
|
|
312
|
+
if (!this.hasValidRegion) {
|
|
313
|
+
throw new Error('CdkTestApp.watch: not initialized with a valid region');
|
|
314
|
+
}
|
|
315
|
+
await this.cdk.watch({
|
|
316
|
+
...exports.DEFAULT_ARGS,
|
|
317
|
+
...watchArgs,
|
|
318
|
+
output: this.outputDirectory,
|
|
319
|
+
profile: this.profile,
|
|
320
|
+
requireApproval: cloud_assembly_schema_1.RequireApproval.NEVER,
|
|
321
|
+
app: this.appCommand,
|
|
322
|
+
context: {
|
|
323
|
+
...this.getContext('deployment'),
|
|
324
|
+
...watchArgs?.context,
|
|
325
|
+
},
|
|
326
|
+
}, watchEvents);
|
|
327
|
+
}
|
|
328
|
+
setReproCommand(context, env) {
|
|
329
|
+
// Show the command necessary to repro this
|
|
330
|
+
const envSet = Object.entries(env).map(([k, v]) => `${k}='${v}'`);
|
|
331
|
+
const envCmd = envSet.length > 0 ? ['env', ...envSet] : [];
|
|
332
|
+
this.synthReproCommand = [
|
|
333
|
+
...envCmd,
|
|
334
|
+
'cdk',
|
|
335
|
+
'synth',
|
|
336
|
+
'-a',
|
|
337
|
+
`'${this.appCommand}'`,
|
|
338
|
+
'-o',
|
|
339
|
+
`'${this.outputDirectory}'`,
|
|
340
|
+
...Object.entries(context).flatMap(([k, v]) => typeof v !== 'object' ? [`-c '${k}=${v}'`] : []),
|
|
341
|
+
].join(' ');
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Load the integ manifest which contains information
|
|
345
|
+
* on how to execute the tests
|
|
346
|
+
* First we try and load the manifest from the integ manifest (i.e. integ.json)
|
|
347
|
+
* from the cloud assembly. If it doesn't exist, then we fallback to the
|
|
348
|
+
* "legacy mode" and create a manifest from pragma
|
|
349
|
+
*
|
|
350
|
+
* @internal
|
|
351
|
+
*/
|
|
352
|
+
async _loadManifest() {
|
|
353
|
+
if (!await this.hasOutput() && !this.options.TESTING_usingMocks) {
|
|
354
|
+
throw new Error(`Synth did not produce output directory: ${this.outputDirectory}`);
|
|
355
|
+
}
|
|
356
|
+
const manifestDir = this.outputDirectory;
|
|
357
|
+
try {
|
|
358
|
+
const testSuite = integ_test_suite_1.IntegTestSuite.fromPath(manifestDir);
|
|
359
|
+
return testSuite;
|
|
360
|
+
}
|
|
361
|
+
catch (modernError) {
|
|
362
|
+
// Only attempt legacy test case if the integ test manifest was not found
|
|
363
|
+
// For any other errors, e.g. when parsing the manifest fails, we abort.
|
|
364
|
+
if (!(modernError instanceof integ_manifest_1.NoManifestError)) {
|
|
365
|
+
throw modernError;
|
|
366
|
+
}
|
|
367
|
+
if (this.showOutput) {
|
|
368
|
+
logger.trace("Failed to load integ test manifest for '%s'. Attempting as deprecated legacy test instead. Error was: %s", manifestDir, modernError.message ?? String(modernError));
|
|
369
|
+
}
|
|
370
|
+
return this._loadLegacyTestSuite();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async _loadLegacyTestSuite() {
|
|
374
|
+
const testCases = await integ_test_suite_1.LegacyIntegTestSuite.fromLegacy({
|
|
375
|
+
cdk: this.cdk,
|
|
376
|
+
testName: this.test.normalizedTestName,
|
|
377
|
+
integSourceFilePath: this.test.fileName,
|
|
378
|
+
listOptions: {
|
|
379
|
+
...this.defaultArgs,
|
|
380
|
+
all: true,
|
|
381
|
+
app: this.appCommand,
|
|
382
|
+
profile: this.profile,
|
|
383
|
+
output: this.outputDirectory,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
this.legacyContext = integ_test_suite_1.LegacyIntegTestSuite.getPragmaContext(this.test.fileName);
|
|
387
|
+
return testCases;
|
|
388
|
+
}
|
|
389
|
+
cleanup() {
|
|
390
|
+
const cdkOutPath = this.outputDirectory;
|
|
391
|
+
if (fs.existsSync(cdkOutPath)) {
|
|
392
|
+
fs.removeSync(cdkOutPath);
|
|
393
|
+
}
|
|
394
|
+
// Clear cache
|
|
395
|
+
this._testSuite = undefined;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* If there are any destructive changes to a stack then this will record
|
|
399
|
+
* those in the manifest.json file
|
|
400
|
+
*/
|
|
401
|
+
renderTraceData(destructiveChanges) {
|
|
402
|
+
const traceData = new Map();
|
|
403
|
+
destructiveChanges.forEach(change => {
|
|
404
|
+
const trace = traceData.get(change.stackName);
|
|
405
|
+
if (trace) {
|
|
406
|
+
trace.set(change.logicalId, `${DESTRUCTIVE_CHANGES} ${change.impact}`);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
traceData.set(change.stackName, new Map([
|
|
410
|
+
[change.logicalId, `${DESTRUCTIVE_CHANGES} ${change.impact}`],
|
|
411
|
+
]));
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
return traceData;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* In cases where we do not want to retain the assets,
|
|
418
|
+
* for example, if the assets are very large.
|
|
419
|
+
*
|
|
420
|
+
* Since it is possible to disable the update workflow for individual test
|
|
421
|
+
* cases, this needs to first get a list of stacks that have the update workflow
|
|
422
|
+
* disabled and then delete assets that relate to that stack. It does that
|
|
423
|
+
* by reading the asset manifest for the stack and deleting the asset source
|
|
424
|
+
*/
|
|
425
|
+
async removeAssetsFromSnapshot() {
|
|
426
|
+
const stacks = this.testSuite.getStacksWithoutUpdateWorkflow() ?? [];
|
|
427
|
+
const manifest = cloud_assembly_1.AssemblyManifestReader.fromPath(this.outputDirectory);
|
|
428
|
+
const assets = (0, utils_1.flatten)(stacks.map(stack => {
|
|
429
|
+
return manifest.getAssetLocationsForStack(stack) ?? [];
|
|
430
|
+
}));
|
|
431
|
+
assets.forEach(asset => {
|
|
432
|
+
const fileName = path.join(this.outputDirectory, asset);
|
|
433
|
+
if (fs.existsSync(fileName)) {
|
|
434
|
+
if (fs.lstatSync(fileName).isDirectory()) {
|
|
435
|
+
fs.removeSync(fileName);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
fs.unlinkSync(fileName);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Remove the asset cache (.cache/) files from the snapshot.
|
|
445
|
+
* These are a cache of the asset zips, but we are fine with
|
|
446
|
+
* re-zipping on deploy
|
|
447
|
+
*/
|
|
448
|
+
removeAssetsCacheFromSnapshot() {
|
|
449
|
+
const files = fs.readdirSync(this.outputDirectory);
|
|
450
|
+
files.forEach(file => {
|
|
451
|
+
const fileName = path.join(this.outputDirectory, file);
|
|
452
|
+
if (fs.lstatSync(fileName).isDirectory() && file === '.cache') {
|
|
453
|
+
fs.emptyDirSync(fileName);
|
|
454
|
+
fs.rmdirSync(fileName);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Perform some cleanup steps after the snapshot is created
|
|
460
|
+
* Anytime the snapshot needs to be modified after creation
|
|
461
|
+
* the logic should live here.
|
|
462
|
+
*/
|
|
463
|
+
async cleanupGoldenSnapshot(destructiveChanges) {
|
|
464
|
+
if (!await this.hasOutput()) {
|
|
465
|
+
// This should not be possible, but a lot of the tests depend on this being a no-op
|
|
466
|
+
// if no output directory got produced.
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
await this.removeAssetsFromSnapshot();
|
|
470
|
+
this.removeAssetsCacheFromSnapshot();
|
|
471
|
+
const assembly = cloud_assembly_1.AssemblyManifestReader.fromPath(this.outputDirectory);
|
|
472
|
+
assembly.cleanManifest();
|
|
473
|
+
assembly.recordTrace(this.renderTraceData(destructiveChanges));
|
|
474
|
+
// if this is a legacy test then create an integ manifest
|
|
475
|
+
// in the snapshot directory which can be used for the
|
|
476
|
+
// update workflow. Save any legacyContext as well so that it can be read
|
|
477
|
+
// the next time
|
|
478
|
+
const actualTestSuite = this.testSuite;
|
|
479
|
+
actualTestSuite.enableLookups = true;
|
|
480
|
+
if (actualTestSuite instanceof integ_test_suite_1.LegacyIntegTestSuite) {
|
|
481
|
+
actualTestSuite.saveManifest(this.outputDirectory, this.legacyContext);
|
|
482
|
+
}
|
|
483
|
+
else if (actualTestSuite instanceof integ_test_suite_1.IntegTestSuite) {
|
|
484
|
+
actualTestSuite.saveManifest(this.outputDirectory);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
getContext(forSnapshot) {
|
|
488
|
+
if (this._legacyEnableLookups === undefined) {
|
|
489
|
+
throw new Error('Must call configureLegacyEnableLookups before synthing');
|
|
490
|
+
}
|
|
491
|
+
// Load the test-specific context (from `integ.context.json` or `cdk.json#context`), if any.
|
|
492
|
+
// If not found, use the built-in current feature flags (at the risk of newer feature flags changing
|
|
493
|
+
// the snapshots).
|
|
494
|
+
const featureFlags = this.testSpecificContext ?? currentlyRecommendedAwsCdkLibFlags();
|
|
495
|
+
return {
|
|
496
|
+
...featureFlags,
|
|
497
|
+
...this.legacyContext,
|
|
498
|
+
// The _legacyEnableLookups flag is crazy but is only there to not disturb existing snapshots too much.
|
|
499
|
+
...(forSnapshot === 'snapshot' && this._legacyEnableLookups !== false ? exports.DEFAULT_SYNTH_OPTIONS.context : {}),
|
|
500
|
+
// Don't record creation stack traces in the snapshot, since they just take up space and are never deterministic.
|
|
501
|
+
'aws:cdk:disable-creation-stack-traces': true,
|
|
502
|
+
// We originally had PLANNED to set this to ['aws', 'aws-cn'], but due to a programming mistake
|
|
503
|
+
// it was set to everything. In this PR, set it to everything to not mess up all the snapshots.
|
|
504
|
+
'@aws-cdk/core:target-partitions': undefined,
|
|
505
|
+
/* ---------------- THE FUTURE LIVES BELOW----------------------------
|
|
506
|
+
// Restricting to these target partitions makes most service principals synthesize to
|
|
507
|
+
// `service.${URL_SUFFIX}`, which is technically *incorrect* (it's only `amazonaws.com`
|
|
508
|
+
// or `amazonaws.com.cn`, never UrlSuffix for any of the restricted regions) but it's what
|
|
509
|
+
// most existing integ tests contain, and we want to disturb as few as possible.
|
|
510
|
+
// [TARGET_PARTITIONS]: ['aws', 'aws-cn'],
|
|
511
|
+
/* ---------------- END OF THE FUTURE ------------------------------- */
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
exports.CdkTestApp = CdkTestApp;
|
|
516
|
+
// Default context we run all integ tests with, so they don't depend on the
|
|
517
|
+
// account of the exercising user.
|
|
518
|
+
exports.DEFAULT_SYNTH_OPTIONS = {
|
|
519
|
+
context: {
|
|
520
|
+
// We have traditionally set this, but it's quite a bad idea. It makes region-agnostic stacks undeployable, and there's really no reason for that.
|
|
521
|
+
// However, if we unset this, we will break many existing snapshots so we keep it for now.
|
|
522
|
+
[cloud_assembly_api_1.AVAILABILITY_ZONE_FALLBACK_CONTEXT_KEY]: ['test-region-1a', 'test-region-1b', 'test-region-1c'],
|
|
523
|
+
'availability-zones:account=12345678:region=test-region': ['test-region-1a', 'test-region-1b', 'test-region-1c'],
|
|
524
|
+
'ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn-ami-hvm-x86_64-gp2:region=test-region': 'ami-1234',
|
|
525
|
+
'ssm:account=12345678:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:region=test-region': 'ami-1234',
|
|
526
|
+
'ssm:account=12345678:parameterName=/aws/service/ecs/optimized-ami/amazon-linux/recommended:region=test-region': '{"image_id": "ami-1234"}',
|
|
527
|
+
// eslint-disable-next-line @stylistic/max-len
|
|
528
|
+
'ami:account=12345678:filters.image-type.0=machine:filters.name.0=amzn-ami-vpc-nat-*:filters.state.0=available:owners.0=amazon:region=test-region': 'ami-1234',
|
|
529
|
+
'vpc-provider:account=12345678:filter.isDefault=true:region=test-region:returnAsymmetricSubnets=true': {
|
|
530
|
+
vpcId: 'vpc-60900905',
|
|
531
|
+
subnetGroups: [
|
|
532
|
+
{
|
|
533
|
+
type: 'Public',
|
|
534
|
+
name: 'Public',
|
|
535
|
+
subnets: [
|
|
536
|
+
{
|
|
537
|
+
subnetId: 'subnet-e19455ca',
|
|
538
|
+
availabilityZone: 'us-east-1a',
|
|
539
|
+
routeTableId: 'rtb-e19455ca',
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
subnetId: 'subnet-e0c24797',
|
|
543
|
+
availabilityZone: 'us-east-1b',
|
|
544
|
+
routeTableId: 'rtb-e0c24797',
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
subnetId: 'subnet-ccd77395',
|
|
548
|
+
availabilityZone: 'us-east-1c',
|
|
549
|
+
routeTableId: 'rtb-ccd77395',
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
},
|
|
553
|
+
],
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
env: {
|
|
557
|
+
CDK_INTEG_ACCOUNT: '12345678',
|
|
558
|
+
CDK_INTEG_REGION: 'test-region',
|
|
559
|
+
CDK_INTEG_HOSTED_ZONE_ID: 'Z23ABC4XYZL05B',
|
|
560
|
+
CDK_INTEG_HOSTED_ZONE_NAME: 'example.com',
|
|
561
|
+
CDK_INTEG_DOMAIN_NAME: '*.example.com',
|
|
562
|
+
CDK_INTEG_CERT_ARN: 'arn:aws:acm:test-region:12345678:certificate/86468209-a272-595d-b831-0efb6421265z',
|
|
563
|
+
CDK_INTEG_SUBNET_ID: 'subnet-0dff1a399d8f6f92c',
|
|
564
|
+
},
|
|
565
|
+
};
|
|
566
|
+
/**
|
|
567
|
+
* Return the currently recommended flags for `aws-cdk-lib`.
|
|
568
|
+
*
|
|
569
|
+
* These have been built into the CLI at build time. If this ever gets changed
|
|
570
|
+
* back to a dynamic load, remember that this source file may be bundled into
|
|
571
|
+
* a JavaScript bundle, and `__dirname` might not point where you think it does.
|
|
572
|
+
*/
|
|
573
|
+
function currentlyRecommendedAwsCdkLibFlags() {
|
|
574
|
+
return recommendedFlagsFile;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Default options to pass to the CDK CLI
|
|
578
|
+
*/
|
|
579
|
+
exports.DEFAULT_ARGS = {
|
|
580
|
+
pathMetadata: false,
|
|
581
|
+
assetMetadata: false,
|
|
582
|
+
versionReporting: false,
|
|
583
|
+
};
|
|
584
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLXRlc3QtYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2RrLXRlc3QtYXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJyQkEsZ0ZBRUM7QUE3ckJELGtEQUFrRDtBQUNsRCwyQ0FBNkI7QUFDN0Isb0VBQXFHO0FBQ3JHLDBFQUF3RztBQUN4Ryw2Q0FBK0I7QUFDL0IseURBQTBFO0FBRTFFLGtEQUFvQztBQUNwQyx3RkFBMEU7QUFDMUUsb0NBQW1DO0FBR25DLDZEQUFrRTtBQUVsRSw2REFBMkQ7QUFDM0QsMkVBQTJGO0FBQzNGLHdEQUFnRTtBQUNoRSxvQ0FBd0M7QUFFeEMsTUFBTSxtQkFBbUIsR0FBRyx3QkFBd0IsQ0FBQztBQStGckQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBYSxVQUFVO0lBc0VnQjtJQUE2QztJQXJFM0UsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxPQUErRDtRQUNuRyxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFDdkIsR0FBRyxPQUFPO1lBQ1YsMkJBQTJCLEVBQUUseUJBQXlCO1NBQ3ZELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxPQUErRDtRQUMvRixPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFDdkIsR0FBRyxPQUFPO1lBQ1YsMkJBQTJCLEVBQUUsdUNBQXVDO1NBQ3JFLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDLE9BQTBCO1FBQ2pFLE9BQU8sVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBK0Q7UUFDL0YsT0FBTyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQ3ZCLEdBQUcsT0FBTztZQUNWLDJCQUEy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QkFBaUI7NEJBQzNCLGdCQUFnQixFQUFFLFlBQVk7NEJBQzlCLFlBQVksRUFBRSxjQUFjO3lCQUM3QjtxQkFDRjtpQkFDRjthQUNGO1NBQ0Y7S0FDRjtJQUNELEdBQUcsRUFBRTtRQUNILGlCQUFpQixFQUFFLFVBQVU7UUFDN0IsZ0JBQWdCLEVBQUUsYUFBYTtRQUMvQix3QkFBd0IsRUFBRSxnQkFBZ0I7UUFDMUMsMEJBQTBCLEVBQUUsYUFBYTtRQUN6QyxxQkFBcUIsRUFBRSxlQUFlO1FBQ3RDLGtCQUFrQixFQUFFLG1GQUFtRjtRQUN2RyxtQkFBbUIsRUFBRSwwQkFBMEI7S0FDaEQ7Q0FDRixDQUFDO0FBRUY7Ozs7OztHQU1HO0FBQ0gsU0FBZ0Isa0NBQWtDO0lBQ2hELE9BQU8sb0JBQW9CLENBQUM7QUFDOUIsQ0FBQztBQXFCRDs7R0FFRztBQUNVLFFBQUEsWUFBWSxHQUFzQjtJQUM3QyxZQUFZLEVBQUUsS0FBSztJQUNuQixhQUFhLEVBQUUsS0FBSztJQUNwQixnQkFBZ0IsRUFBRSxLQUFLO0NBQ3hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBAY2RrbGFicy9uby1saXRlcmFsLXBhcnRpdGlvbiAqL1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IEFWQUlMQUJJTElUWV9aT05FX0ZBTExCQUNLX0NPTlRFWFRfS0VZLCBVTktOT1dOX1JFR0lPTiB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LWFwaSc7XG5pbXBvcnQgeyB0eXBlIFRlc3RDYXNlLCB0eXBlIERlZmF1bHRDZGtPcHRpb25zLCBSZXF1aXJlQXBwcm92YWwgfSBmcm9tICdAYXdzLWNkay9jbG91ZC1hc3NlbWJseS1zY2hlbWEnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgSW50ZWdUZXN0U3VpdGUsIExlZ2FjeUludGVnVGVzdFN1aXRlIH0gZnJvbSAnLi9pbnRlZy10ZXN0LXN1aXRlJztcbmltcG9ydCB0eXBlIHsgRGVwbG95T3B0aW9ucywgRGVzdHJveU9wdGlvbnMsIElDZGssIFdhdGNoRXZlbnRzIH0gZnJvbSAnLi4vZW5naW5lcy9jZGstaW50ZXJmYWNlJztcbmltcG9ydCAqIGFzIGxvZ2dlciBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0ICogYXMgcmVjb21tZW5kZWRGbGFnc0ZpbGUgZnJvbSAnLi4vcmVjb21tZW5kZWQtZmVhdHVyZS1mbGFncy5qc29uJztcbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tICcuLi91dGlscyc7XG5pbXBvcnQgdHlwZSB7IEludGVnVGVzdCB9IGZyb20gJy4vaW50ZWdyYXRpb24tdGVzdHMnO1xuaW1wb3J0IHR5cGUgeyBNYW5pZmVzdFRyYWNlIH0gZnJvbSAnLi9wcml2YXRlL2Nsb3VkLWFzc2VtYmx5JztcbmltcG9ydCB7IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIgfSBmcm9tICcuL3ByaXZhdGUvY2xvdWQtYXNzZW1ibHknO1xuaW1wb3J0IHR5cGUgeyBEZXN0cnVjdGl2ZUNoYW5nZSB9IGZyb20gJy4uL3dvcmtlcnMvY29tbW9uJztcbmltcG9ydCB7IE5vTWFuaWZlc3RFcnJvciB9IGZyb20gJy4vcHJpdmF0ZS9pbnRlZy1tYW5pZmVzdCc7XG5pbXBvcnQgeyBmaW5kVGVzdFNwZWNpZmljQ29udGV4dCwgdHlwZSBDZGtDb250ZXh0IH0gZnJvbSAnLi9wcml2YXRlL3Rlc3Qtc3BlY2lmaWMtY29udGV4dCc7XG5pbXBvcnQgeyBUb29sa2l0TGliUnVubmVyRW5naW5lIH0gZnJvbSAnLi4vZW5naW5lcy90b29sa2l0LWxpYic7XG5pbXBvcnQgeyBhYnNBd2FyZUpvaW4gfSBmcm9tICcuLi9maWxlcyc7XG5cbmNvbnN0IERFU1RSVUNUSVZFX0NIQU5HRVMgPSAnISFERVNUUlVDVElWRV9DSEFOR0VTOic7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBDREsgQ2xvdWQgQXNzZW1ibHlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZGtUZXN0QXBwT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHRlc3Q6IEludGVnVGVzdDtcblxuICAvKipcbiAgICogVGhlIHJlZ2lvbiB3aGVyZSB0aGUgdGVzdCBzaG91bGQgYmUgZGVwbG95ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJlZ2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFXUyBwcm9maWxlIHRvIHVzZSB3aGVuIGludm9raW5nIHRoZSBDREsgQ0xJXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gcHJvZmlsZSBpcyBwYXNzZWQsIHRoZSBkZWZhdWx0IHByb2ZpbGUgaXMgdXNlZFxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdGhhdCB3aWxsIGJlIGF2YWlsYWJsZVxuICAgKiB0byB0aGUgQ0RLIENMSVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGFkZGl0aW9uYWwgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAqL1xuICByZWFkb25seSBlbnY/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogV2hlcmUgd2Ugd2lsbCB3cml0ZSB0aGUgb3V0cHV0IG9mIHRoZSBDREsgQ0xJLCBpbmNsdWRpbmcgdGhlIGNsb3VkIGFzc2VtYmx5IGFuZCB0aGUgc25hcHNob3RcbiAgICpcbiAgICogU2hvdWxkIGJlIGEgc3RyaW5nIGNvbnRhaW5pbmcgYHt0ZXN0TmFtZX1gLCB3aWxsIGJlIHVzZWQgdG8gZ2VuZXJhdGUgYSBkaXJlY3RvcnkgbmFtZSBpbiB0aGUgc2FtZVxuICAgKiBkaXJlY3RvcnkgYXMgdGhlIHRlc3QgaXRzZWxmLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnY2RrLWludGVnLm91dC57dGVzdE5hbWV9LnNuYXBzaG90J1xuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEluc3RhbmNlIG9mIHRoZSBDREsgVG9vbGtpdCBFbmdpbmUgdG8gdXNlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYmFzZWQgb24gYGVuZ2luZWAgb3B0aW9uXG4gICAqL1xuICByZWFkb25seSBjZGs/OiBJQ2RrO1xuXG4gIC8qKlxuICAgKiBTaG93IG91dHB1dCBmcm9tIHJ1bm5pbmcgaW50ZWdyYXRpb24gdGVzdHNcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHNob3dPdXRwdXQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBVc2UgdGhlIGluZGljYXRlZCBwcm94eVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHByb3h5XG4gICAqL1xuICByZWFkb25seSBwcm94eT86IHN0cmluZztcblxuICAvKipcbiAgICogUGF0aCB0byBDQSBjZXJ0aWZpY2F0ZSB0byB1c2Ugd2hlbiB2YWxpZGF0aW5nIEhUVFBTIHJlcXVlc3RzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gYWRkaXRpb25hbCBDQSBidW5kbGVcbiAgICovXG4gIHJlYWRvbmx5IGNhQnVuZGxlUGF0aD86IHN0cmluZztcblxuICAvKipcbiAgICogSW4gdW5pdCB0ZXN0IG1vZGUsIHdlIGFyZSB1c2luZyBtb2NrcyBmb3IgYSBsb3Qgb2YgY2FsbHNcbiAgICpcbiAgICogRG9uJ3QgZGVsZXRlIGRpcmVjdG9yaWVzLCBhbmQgZG9uJ3QgZG8gY2hlY2tzIHdoZXRoZXIgZmlsZXMgYWN0dWFsbHkgZXhpc3Q7IHRoZVxuICAgKiBtb2NrcyB3aWxsIGJlIHRoZXJlIHRvIHByb2R1Y2UgdGhlIGNvbnRlbnRzIGZvciBmaWxlcyB0aGF0IGFyZSBiZWluZyByZWFkIChhbHRob3VnaFxuICAgKiB0aGV5IGFyZSBub3QgdGhlcmUgdG8gcHJldGVuZCB0byBoYXZlIGZpbGVzIHRoZW1zZWx2ZXMpLlxuICAgKi9cbiAgcmVhZG9ubHkgVEVTVElOR191c2luZ01vY2tzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2Ugd2lsbCBvbmx5IHJlYWQgdGhlIGxlZ2FjeSB0ZXN0IGluZm9ybWF0aW9uIGlmIHRoZSB0ZXN0IGFjdHVhbGx5IHByb2R1Y2VkIGFuIG91dHB1dCBkaXJlY3RvcnkuXG4gICAqXG4gICAqIEZvciBoaXN0b3JpY2FsIHJlYXNvbnMgdGhlIHRlc3RzIGhhdmUgYmVlbiB3cml0dGVuIHNvIHRoYXQgdGhleSB3aWxsIGV4cGVjdCB0byByZWFkXG4gICAqIGxlZ2FjeSB0ZXN0IGluZm9ybWF0aW9uIGFsd2F5cy4gRm9yY2UgdGhhdCBiZWhhdmlvciBiYWNrIGZvciB0ZXN0cy5cbiAgICovXG4gIHJlYWRvbmx5IFRFU1RJTkdfZm9yY2VSZWFkTGVnYWN5VGVzdFN1aXRlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBXaGV0aGVyIHRvIHN5bnRoZXNpemUgdGhlIGFjdHVhbCBzbmFwc2hvdCB3aXRoIGxvb2t1cHMgZW5hYmxlZCBvciBub3QuXG4gKlxuICogSWYgZWl0aGVyIGB0cnVlYCBvciBgZmFsc2VgLCB3ZSBzZW5kIGNvbnRleHQgaW4gb3Igbm90IHdoaWxlIHN5bnRoZXNpemluZyxcbiAqIGFuZCBpZiB0aGUgZ2VuZXJhdGVkIHNuYXBzaG90IHRlc3QgZGVmaW5pdGlvbiByZXF1ZXN0cyBhIGRpZmZlcmVudCB2YWx1ZSB3ZVxuICogd2lsbCBzeW50aCBhZ2Fpbi5cbiAqXG4gKiBGb3IgYGRvbnQtY2FyZWAsIHdlIGRvIHNlbmQgaW4gdGhlIGNvbnRleHQgYnV0IHdlIG5ldmVyIHJlc3ludGguXG4gKi9cbmV4cG9ydCB0eXBlIExlZ2FjeUVuYWJsZUxvb2t1cHMgPSB0cnVlIHwgZmFsc2UgfCAnZG9udC1jYXJlJztcblxuLyoqXG4gKiBDbGFzcyB3aXRoIHNvbWUgaGVscGVyIHJvdXRpbmVzIGZvciBydW5uaW5nIENESyBzbmFwc2hvdHMgYW5kIGludGVncmF0aW9uIHRlc3RzLlxuICpcbiAqIEEgXCJnb2xkZW4gc25hcHNob3RcIiBpcyB0aGUgc25hcHNob3QgdGhhdCBpcyBzdG9yZWQgcGVybWFuZW50bHkgaW4gdmVyc2lvblxuICogY29udHJvbCwgdGhhdCBuZXcgcnVucyBhcmUgY29tcGFyZWQgYWdhaW5zdCAoc3RvcmVkIGluIGEgZGlyZWN0b3J5IG5hbWVkXG4gKiBgPHRlc3QtbmFtZT4uc25hcHNob3RgKS5cbiAqXG4gKiBUaGlzIGlzIGFzIG9wcG9zZWQgdG8gb3RoZXIgc25hcHNob3RzLCB3aGljaCBjYW4gYmUgZ2VuZXJhdGVkIGZvciBleGFtcGxlXG4gKiB0ZW1wb3JhcmlseSBpbiBhIHRlbXBvcmFyeSBkaXJlY3RvcnksIHRvIGNvbXBhcmUgYWdhaW5zIHRoZSBnb2xkZW4gc25hcHNob3QuXG4gKi9cbmV4cG9ydCBjbGFzcyBDZGtUZXN0QXBwIHtcbiAgcHVibGljIHN0YXRpYyBhc3luYyBmb3JHb2xkZW5TbmFwc2hvdChvcHRpb25zOiBPbWl0PENka1Rlc3RBcHBPcHRpb25zLCAnb3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlJz4pOiBQcm9taXNlPENka1Rlc3RBcHA+IHtcbiAgICByZXR1cm4gQ2RrVGVzdEFwcC5jcmVhdGUoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG91dHB1dERpcmVjdG9yeU5hbWVUZW1wbGF0ZTogJ3t0ZXN0QmFzZU5hbWV9LnNuYXBzaG90JyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZm9yQ29tcGFyaXNvbihvcHRpb25zOiBPbWl0PENka1Rlc3RBcHBPcHRpb25zLCAnb3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlJz4pOiBQcm9taXNlPENka1Rlc3RBcHA+IHtcbiAgICByZXR1cm4gQ2RrVGVzdEFwcC5jcmVhdGUoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG91dHB1dERpcmVjdG9yeU5hbWVUZW1wbGF0ZTogJ2Nkay1pbnRlZy5vdXQue3Rlc3RCYXNlTmFtZX0uc25hcHNob3QnLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBhc3luYyBmb3JTcGVjaWZpY0RpcmVjdG9yeShvcHRpb25zOiBDZGtUZXN0QXBwT3B0aW9ucyk6IFByb21pc2U8Q2RrVGVzdEFwcD4ge1xuICAgIHJldHVybiBDZGtUZXN0QXBwLmNyZWF0ZShvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZm9yRGVwbG95bWVudChvcHRpb25zOiBPbWl0PENka1Rlc3RBcHBPcHRpb25zLCAnb3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlJz4pOiBQcm9taXNlPENka1Rlc3RBcHA+IHtcbiAgICByZXR1cm4gQ2RrVGVzdEFwcC5jcmVhdGUoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG91dHB1dERpcmVjdG9yeU5hbWVUZW1wbGF0ZTogJ2Nkay1pbnRlZy5vdXQuZGVwbG95Lnt0ZXN0QmFzZU5hbWV9LnNuYXBzaG90JyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGFzeW5jIGNyZWF0ZShvcHRpb25zOiBDZGtUZXN0QXBwT3B0aW9ucyk6IFByb21pc2U8Q2RrVGVzdEFwcD4ge1xuICAgIGNvbnN0IGN0eCA9IGF3YWl0IGZpbmRUZXN0U3BlY2lmaWNDb250ZXh0KG9wdGlvbnMudGVzdC5hYnNvbHV0ZUZpbGVOYW1lKTtcbiAgICBjb25zdCBhcHAgPSBuZXcgQ2RrVGVzdEFwcChvcHRpb25zLCBjdHgpO1xuICAgIHJldHVybiBhcHA7XG4gIH1cblxuICAvKipcbiAgICogQW4gaW5zdGFuY2Ugb2YgdGhlIENESyAgQ0xJXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNkazogSUNkaztcblxuICBwdWJsaWMgcmVhZG9ubHkgb3V0cHV0RGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBDREsgQ0xJXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRBcmdzOiBEZWZhdWx0Q2RrT3B0aW9ucyA9IHtcbiAgICBwYXRoTWV0YWRhdGE6IGZhbHNlLFxuICAgIGFzc2V0TWV0YWRhdGE6IGZhbHNlLFxuICAgIHZlcnNpb25SZXBvcnRpbmc6IGZhbHNlLFxuICB9O1xuXG4gIC8qKlxuICAgKiBUaGUgcHJvZmlsZSB0byB1c2UgZm9yIHRoZSBDREsgQ0xJIGNhbGxzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcHJvZmlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogU2hvdyBvdXRwdXQgZnJvbSB0aGUgaW50ZWcgdGVzdCBydW4uXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHNob3dPdXRwdXQ6IGJvb2xlYW47XG5cbiAgcHVibGljIHJlYWRvbmx5IHRlc3Q6IEludGVnVGVzdDtcblxuICBwdWJsaWMgc3ludGhSZXByb0NvbW1hbmQ6IHN0cmluZyA9ICcnO1xuXG4gIHB1YmxpYyBfZGVzdHJ1Y3RpdmVDaGFuZ2VzPzogRGVzdHJ1Y3RpdmVDaGFuZ2VbXTtcbiAgcHJpdmF0ZSBsZWdhY3lDb250ZXh0PzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgcHJpdmF0ZSBfdGVzdFN1aXRlPzogSW50ZWdUZXN0U3VpdGUgfCBMZWdhY3lJbnRlZ1Rlc3RTdWl0ZTtcbiAgcHJpdmF0ZSBfbGVnYWN5RW5hYmxlTG9va3Vwcz86IExlZ2FjeUVuYWJsZUxvb2t1cHM7XG5cbiAgcHVibGljIHJlYWRvbmx5IGFwcENvbW1hbmQ6IHN0cmluZztcbiAgcHJpdmF0ZSBoYXNWYWxpZFJlZ2lvbjogYm9vbGVhbjtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogQ2RrVGVzdEFwcE9wdGlvbnMsIHByaXZhdGUgcmVhZG9ubHkgdGVzdFNwZWNpZmljQ29udGV4dD86IENka0NvbnRleHQpIHtcbiAgICB0aGlzLmhhc1ZhbGlkUmVnaW9uID0gb3B0aW9ucy5yZWdpb24gIT09IFVOS05PV05fUkVHSU9OO1xuXG4gICAgdGhpcy50ZXN0ID0gb3B0aW9ucy50ZXN0O1xuXG4gICAgY29uc3Qgb3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlID0gb3B0aW9ucy5vdXRwdXREaXJlY3RvcnlOYW1lVGVtcGxhdGU7XG4gICAgdGhpcy5vdXRwdXREaXJlY3RvcnkgPSBhYnNBd2FyZUpvaW4odGhpcy50ZXN0LnRlc3REaXJlY3RvcnksIHRoaXMudGVzdC5zcGVjaWFsaXplVGVtcGxhdGUob3V0cHV0RGlyZWN0b3J5TmFtZVRlbXBsYXRlKSk7XG5cbiAgICB0aGlzLnByb2ZpbGUgPSBvcHRpb25zLnByb2ZpbGU7XG4gICAgdGhpcy5zaG93T3V0cHV0ID0gb3B0aW9ucy5zaG93T3V0cHV0ID8/IGZhbHNlO1xuXG4gICAgdGhpcy5jZGsgPSBvcHRpb25zLmNkayA/PyBuZXcgVG9vbGtpdExpYlJ1bm5lckVuZ2luZSh7XG4gICAgICB3b3JraW5nRGlyZWN0b3J5OiB0aGlzLnRlc3Qud29ya2luZ0RpcmVjdG9yeSxcbiAgICAgIHNob3dPdXRwdXQ6IG9wdGlvbnMuc2hvd091dHB1dCxcbiAgICAgIGVudjogb3B0aW9ucy5lbnYsXG4gICAgICByZWdpb246IG9wdGlvbnMucmVnaW9uLFxuICAgICAgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlLFxuICAgICAgcHJveHk6IG9wdGlvbnMucHJveHksXG4gICAgICBjYUJ1bmRsZVBhdGg6IG9wdGlvbnMuY2FCdW5kbGVQYXRoLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hcHBDb21tYW5kID0gdGhpcy50ZXN0LnNwZWNpYWxpemVUZW1wbGF0ZSh0aGlzLnRlc3QuYXBwQ29tbWFuZFRlbXBsYXRlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmUgdGhlIGxlZ2FjeSBlbmFibGVMb29rdXBzIHZhbHVlIHRvIHVzZSB3aGVuIGdlbmVyYXRpbmcgdGhlIGFjdHVhbCBzbmFwc2hvdC5cbiAgICpcbiAgICogTXVzdCBiZSBzZXQgYmVmb3JlIHVzaW5nIHNuYXBzaG90IG1ldGhvZHMuXG4gICAqL1xuICBwdWJsaWMgY29uZmlndXJlTGVnYWN5RW5hYmxlTG9va3VwcyhlbmFibGVMb29rdXBzOiBMZWdhY3lFbmFibGVMb29rdXBzKTogdm9pZCB7XG4gICAgdGhpcy5fbGVnYWN5RW5hYmxlTG9va3VwcyA9IGVuYWJsZUxvb2t1cHM7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgaGFzT3V0cHV0KCkge1xuICAgIHJldHVybiAoYXdhaXQgZnMucGF0aEV4aXN0cyh0aGlzLm91dHB1dERpcmVjdG9yeSkpICYmIChhd2FpdCBmcy5wYXRoRXhpc3RzKHBhdGguam9pbih0aGlzLm91dHB1dERpcmVjdG9yeSwgJ21hbmlmZXN0Lmpzb24nKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdGVzdCBjYXNlcyBpbnNpZGUgdGhlIG91dHB1dFxuICAgKi9cbiAgcHVibGljIHRlc3RDYXNlcygpOiB7IFt0ZXN0TmFtZTogc3RyaW5nXTogVGVzdENhc2UgfSB7XG4gICAgcmV0dXJuIHRoaXMudGVzdFN1aXRlLnRlc3RTdWl0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdGVzdCBzdWl0ZSBmcm9tIHRoZSBvdXRwdXRcbiAgICovXG4gIHB1YmxpYyBnZXQgdGVzdFN1aXRlKCk6IEludGVnVGVzdFN1aXRlIHwgTGVnYWN5SW50ZWdUZXN0U3VpdGUge1xuICAgIGlmICghdGhpcy5fdGVzdFN1aXRlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N5bnRoZXNpemUgZmlyc3QhJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3Rlc3RTdWl0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGUgc25hcHNob3QgYWxyZWFkeSBleGlzdHMsIGxvYWQgaXRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb2FkRXhpc3RpbmdTdWl0ZSgpOiBQcm9taXNlPEludGVnVGVzdFN1aXRlIHwgTGVnYWN5SW50ZWdUZXN0U3VpdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAodGhpcy5fdGVzdFN1aXRlKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdGVzdFN1aXRlO1xuICAgIH1cblxuICAgIGlmIChhd2FpdCB0aGlzLmhhc091dHB1dCgpKSB7XG4gICAgICB0aGlzLl90ZXN0U3VpdGUgPSBhd2FpdCB0aGlzLl9sb2FkTWFuaWZlc3QoKTtcbiAgICAgIHJldHVybiB0aGlzLl90ZXN0U3VpdGU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5URVNUSU5HX2ZvcmNlUmVhZExlZ2FjeVRlc3RTdWl0ZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xvYWRMZWdhY3lUZXN0U3VpdGUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHN5bnRoRm9yU25hcHNob3RDb21wYXJpc29uKGVuYWJsZUxvb2t1cHNHdWVzczogTGVnYWN5RW5hYmxlTG9va3Vwcykge1xuICAgIHRoaXMuY29uZmlndXJlTGVnYWN5RW5hYmxlTG9va3VwcyhlbmFibGVMb29rdXBzR3Vlc3MpO1xuICAgIGNvbnN0IHN1aXRlID0gYXdhaXQgdGhpcy5zeW50aCh0aGlzLmdldENvbnRleHQoJ3NuYXBzaG90JyksIERFRkFVTFRfU1lOVEhfT1BUSU9OUy5lbnYpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIGVuYWJsZUxvb2t1cHMgdmFsdWUgaGFzIGNoYW5nZWQgYmV0d2VlbiB0aGUgZ29sZGVuXG4gICAgLy8gc25hcHNob3QgYW5kIHRoZSBhY3R1YWwgc25hcHNob3QuIElmIGl0IGhhcywgd2UgbmVlZCB0byByZS1zeW50aCB0aGVcbiAgICAvLyBhY3R1YWwgc25hcHNob3Qgd2l0aCB0aGUgbmV3IGVuYWJsZUxvb2t1cHMgdmFsdWUuXG4gICAgLy9cbiAgICAvLyBTZWUgYHN5bnRoQWN0dWFsU25hcHNob3RgIGZvciBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0aGlzIGlzIG5lY2Vzc2FyeS5cbiAgICBjb25zdCBhY3R1YWxFbmFibGVMb29rdXBzID0gc3VpdGUuZW5hYmxlTG9va3VwcyA/PyBmYWxzZTtcbiAgICBpZiAoYWN0dWFsRW5hYmxlTG9va3VwcyAhPT0gdGhpcy5fbGVnYWN5RW5hYmxlTG9va3VwcyAmJiB0aGlzLl9sZWdhY3lFbmFibGVMb29rdXBzICE9PSAnZG9udC1jYXJlJykge1xuICAgICAgdGhpcy5jb25maWd1cmVMZWdhY3lFbmFibGVMb29rdXBzKGFjdHVhbEVuYWJsZUxvb2t1cHMpO1xuICAgICAgcmV0dXJuIHRoaXMuc3ludGgodGhpcy5nZXRDb250ZXh0KCdzbmFwc2hvdCcpLCBERUZBVUxUX1NZTlRIX09QVElPTlMuZW52KTtcbiAgICB9XG4gICAgcmV0dXJuIHN1aXRlO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHN5bnRoRm9yR29sZGVuU25hcHNob3QoZGVzdHJ1Y3RpdmVDaGFuZ2VzOiBEZXN0cnVjdGl2ZUNoYW5nZVtdLCBlbmFibGVMb29rdXBzOiBMZWdhY3lFbmFibGVMb29rdXBzKSB7XG4gICAgdGhpcy5jb25maWd1cmVMZWdhY3lFbmFibGVMb29rdXBzKGVuYWJsZUxvb2t1cHMpO1xuICAgIGF3YWl0IHRoaXMuc3ludGgodGhpcy5nZXRDb250ZXh0KCdzbmFwc2hvdCcpLCBERUZBVUxUX1NZTlRIX09QVElPTlMuZW52KTtcbiAgICBhd2FpdCB0aGlzLmNsZWFudXBHb2xkZW5TbmFwc2hvdChkZXN0cnVjdGl2ZUNoYW5nZXMpO1xuICAgIHJldHVybiB0aGlzLnRlc3RTdWl0ZTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzeW50aEZvckRlcGxveW1lbnQoKSB7XG4gICAgdGhpcy5jb25maWd1cmVMZWdhY3lFbmFibGVMb29rdXBzKCdkb250LWNhcmUnKTtcbiAgICBhd2FpdCB0aGlzLnN5bnRoKHRoaXMuZ2V0Q29udGV4dCgnZGVwbG95bWVudCcpLCB7fSk7XG4gICAgcmV0dXJuIHRoaXMudGVzdFN1aXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvciBhIGdpdmVuIGNsb3VkIGFzc2VtYmx5IHJldHVybiBhIGNvbGxlY3Rpb24gb2YgYWxsIHRlbXBsYXRlc1xuICAgKiB0aGF0IHNob3VsZCBiZSBwYXJ0IG9mIHRoZSBzbmFwc2hvdCBhbmQgYW55IHJlcXVpcmVkIG1ldGEgZGF0YS5cbiAgICpcbiAgICogQHBhcmFtIGNsb3VkQXNzZW1ibHlEaXIgLSBUaGUgZGlyZWN0b3J5IG9mIHRoZSBjbG91ZCBhc3NlbWJseSB0byBsb29rIGZvciBzbmFwc2hvdHNcbiAgICogQHBhcmFtIHBpY2tTdGFja3MgLSBQaWNrIG9ubHkgdGhlc2Ugc3RhY2tzIGZyb20gdGhlIGNsb3VkIGFzc2VtYmx5XG4gICAqIEByZXR1cm5zIEEgU25hcHNob3RBc3NlbWJseSwgdGhlIGNvbGxlY3Rpb24gb2YgYWxsIHRlbXBsYXRlcyBpbiB0aGlzIHNuYXBzaG90IGFuZCByZXF1aXJlZCBtZXRhIGRhdGFcbiAgICovXG4gIHB1YmxpYyBzbmFwc2hvdEFzc2VtYmx5KHBpY2tTdGFja3M6IHN0cmluZ1tdID0gW10pOiBTbmFwc2hvdEFzc2VtYmx5IHtcbiAgICBjb25zdCBhc3NlbWJseSA9IHRoaXMucmVhZEFzc2VtYmx5KHRoaXMub3V0cHV0RGlyZWN0b3J5KTtcbiAgICBjb25zdCBzdGFja3MgPSBhc3NlbWJseS5zdGFja3M7XG4gICAgY29uc3Qgc25hcHNob3RzOiBTbmFwc2hvdEFzc2VtYmx5ID0ge307XG4gICAgZm9yIChjb25zdCBbc3RhY2tOYW1lLCBzdGFja1RlbXBsYXRlXSBvZiBPYmplY3QuZW50cmllcyhzdGFja3MpKSB7XG4gICAgICBpZiAocGlja1N0YWNrcy5pbmNsdWRlcyhzdGFja05hbWUpKSB7XG4gICAgICAgIGNvbnN0IG1hbmlmZXN0ID0gQXNzZW1ibHlNYW5pZmVzdFJlYWRlci5mcm9tUGF0aCh0aGlzLm91dHB1dERpcmVjdG9yeSk7XG4gICAgICAgIGNvbnN0IGFzc2V0cyA9IG1hbmlmZXN0LmdldEFzc2V0SWRzRm9yU3RhY2soc3RhY2tOYW1lKTtcblxuICAgICAgICBzbmFwc2hvdHNbc3RhY2tOYW1lXSA9IHtcbiAgICAgICAgICB0ZW1wbGF0ZXM6IHtcbiAgICAgICAgICAgIFtzdGFja05hbWVdOiBzdGFja1RlbXBsYXRlLFxuICAgICAgICAgICAgLi4uYXNzZW1ibHkuZ2V0TmVzdGVkU3RhY2tzRm9yU3RhY2soc3RhY2tOYW1lKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGFzc2V0cyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc25hcHNob3RzO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkQXNzZW1ibHkoZGlyOiBzdHJpbmcpOiBBc3NlbWJseU1hbmlmZXN0UmVhZGVyIHtcbiAgICByZXR1cm4gQXNzZW1ibHlNYW5pZmVzdFJlYWRlci5mcm9tUGF0aChkaXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN5bnRoIHRoZSBhY3R1YWwgYXBwbGljYXRpb24gdG8gdGhlIGdpdmVuIGRpcmVjdG9yeSwgZm9yIHB1cnBvc2VzIG9mIGdlbmVyYXRpbmcvdmFsaWRhdGluZyBhIHNuYXBzaG90XG4gICAqXG4gICAqIGBsZWdhY3lFbmFibGVMb29rdXBzYCBpcyB0byBwcmVzZXJ2ZSBoaXN0b3JpY2FsIGJlaGF2aW9yIGZvciBhIHdoaWxlOlxuICAgKiB0cmFkaXRpb25hbGx5LCB0aGUgYXBwbGljYXRpb24gd291bGQgb25seSBiZSBzZWVkZWQgd2l0aCBjb250ZXh0IGlmXG4gICAqIGBlbmFibGVMb29rdXBzYCB3YXMgdHJ1ZSwgYW5kIHRoaXMgaW5mb3JtYXRpb24gd291bGQgY29tZSBmcm9tIHRoZSB0ZXN0XG4gICAqIGRlZmluaXRpb24uXG4gICAqXG4gICAqIC0gU2luY2UgdGhlIHRlc3QgZGVmaW5pdGlvbiBjb21lcyBmcm9tIGluc2lkZSB0aGUgYXBwLCB0aGlzIHJlcXVpcmVzIGFcbiAgICogICBzeW50aCBqdXN0IHRvIGdldCB0aGUgdGVzdCBkZWZpbml0aW9uLCBhbmQgdGhlbiBhbm90aGVyIHN5bnRoIHRvIGdlbmVyYXRlXG4gICAqICAgdGhlIGFjdHVhbCBzbmFwc2hvdCB3aXRoIHRoZSBjb3JyZWN0IGNvbnRleHQsIHdoaWNoIGlzIHRpbWUgY29uc3VtaW5nLlxuICAgKiAtIEdpdmVuIHRoYXQgdGhlIGNvbnRleHQgaXMgZml4ZWQgYW5kIGZha2UsIGl0IGNvdWxkIGFsd2F5cyBoYXZlIGJlZW4gcGFzc2VkLlxuICAgKlxuICAgKiBIb3dldmVyLCB0aGUgc25hcHNob3QgY29udGVudHMgdGhlbXNlbHZlcyBkZXBlbmQgb24gdGhlIGNvbnRleHQgZmxhZywgYW5kIGNoYW5naW5nXG4gICAqIHRoaXMgYmVoYXZpb3Igbm93IGludmFsaWRhdGVzIGFsbCBzbmFwc2hvdHMgZXZlcnl3aGVyZSwgd2hpY2ggaXMgYW5ub3lpbmcgZm9yIHVwZ3JhZGluZy5cbiAgICpcbiAgICogU28gd2Ugd2lsbCB1c2UgdGhlIGJlaGF2aW9yIGZyb20gdGhlIEdPTERFTiBTTkFQU0hPVCdzIHRlc3QgZGVmaW5pdGlvbiB0b1xuICAgKiBkZXRlcm1pbmUgd2hldGhlciB0byBwYXNzIHRoZSBjb250ZXh0LCBhbmQgaWYgdGhlIG5ldyBhY3R1YWwgc25hcHNob3QgaGFzIGFcbiAgICogZGlmZmVyZW50IHZhbHVlIGZvciBgZW5hYmxlTG9va3Vwc2AsIHdlIHdpbGwgdGhyb3cgYXdheSB0aGUgb2xkIHNuYXBzaG90IGFuZCBzeW50aCBhZ2Fpbi5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc3ludGgoY29udGV4dDogUmVjb3JkPHN0cmluZywgYW55PiwgZW52OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUHJvbWlzZTxJbnRlZ1Rlc3RTdWl0ZSB8IExlZ2FjeUludGVnVGVzdFN1aXRlPiB7XG4gICAgY29uc3Qgb3V0cHV0ID0gdGhpcy5vdXRwdXREaXJlY3Rvcnk7XG5cbiAgICAvLyBSZW1vdmUgdGhlIHRhcmdldCBkaXJlY3RvcnksIHNvIHRoYXQgd2UgZG9uJ3QgaGF2ZSBzdGFsZSBmaWxlcyBmcm9tXG4gICAgLy8gcHJldmlvdXMgc3ludGhzLiBBbHNvLCB0aGUgcnVubmVyIHdpbGwgcmUtdXNlIGEgZGlyZWN0b3J5IHRoYXQgYWxyZWFkeVxuICAgIC8vIGV4aXN0cyBhbmQgd2Ugd2FudCBmb3JjZSByZWNyZWF0aW9uICh1bmxlc3Mgd2UgYXJlIHVuaXQgdGVzdGluZykuXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuVEVTVElOR191c2luZ01vY2tzKSB7XG4gICAgICBhd2FpdCBmcy5ybShvdXRwdXQsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmNkay5zeW50aCh7XG4gICAgICBhcHA6IHRoaXMuYXBwQ29tbWFuZCxcbiAgICAgIGNvbnRleHQsXG4gICAgICBlbnYsXG4gICAgICBvdXRwdXQsXG4gICAgfSk7XG5cbiAgICB0aGlzLnNldFJlcHJvQ29tbWFuZChjb250ZXh0LCBlbnYpO1xuXG4gICAgdGhpcy5fdGVzdFN1aXRlID0gYXdhaXQgdGhpcy5fbG9hZE1hbmlmZXN0KCk7XG4gICAgcmV0dXJuIHRoaXMuX3Rlc3RTdWl0ZTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkZXBsb3koZGVwbG95QXJnczogT21pdDxEZXBsb3lPcHRpb25zLCAnYXBwJyB8ICdyZXF1aXJlQXBwcm92YWwnIHwgJ3Byb2ZpbGUnIHwgJ291dHB1dCcgfCAnbG9va3Vwcyc+KSB7XG4gICAgaWYgKCF0aGlzLmhhc1ZhbGlkUmVnaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nka1Rlc3RBcHAuZGVwbG95OiBub3QgaW5pdGlhbGl6ZWQgd2l0aCBhIHZhbGlkIHJlZ2lvbicpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNkay5kZXBsb3koe1xuICAgICAgLi4uREVGQVVMVF9BUkdTLFxuICAgICAgLi4uZGVwbG95QXJncyxcbiAgICAgIG91dHB1dDogdGhpcy5vdXRwdXREaXJlY3RvcnksXG4gICAgICBwcm9maWxlOiB0aGlzLnByb2ZpbGUsXG4gICAgICByZXF1aXJlQXBwcm92YWw6IFJlcXVpcmVBcHByb3ZhbC5ORVZFUixcbiAgICAgIGFwcDogdGhpcy5hcHBDb21tYW5kLFxuICAgICAgY29udGV4dDoge1xuICAgICAgICAuLi50aGlzLmdldENvbnRleHQoJ2RlcGxveW1lbnQnKSxcbiAgICAgICAgLi4uZGVwbG95QXJncz8uY29udGV4dCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVzdHJveShkZXN0cm95QXJnczogT21pdDxEZXN0cm95T3B0aW9ucywgJ2FwcCcgfCAnZm9yY2UnIHwgJ3Byb2ZpbGUnIHwgJ291dHB1dCc+KSB7XG4gICAgaWYgKCF0aGlzLmhhc1ZhbGlkUmVnaW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nka1Rlc3RBcHAuZGVzdHJveTogbm90IGluaXRpYWxpemVkIHdpdGggYSB2YWxpZCByZWdpb24nKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmNkay5kZXN0cm95KHtcbiAgICAgIC4uLkRFRkFVTFRfQVJHUyxcbiAgICAgIC4uLmRlc3Ryb3lBcmdzLFxuICAgICAgYXBwOiB0aGlzLmFwcENvbW1hbmQsXG4gICAgICBvdXRwdXQ6IHRoaXMub3V0cHV0RGlyZWN0b3J5LFxuICAgICAgcHJvZmlsZTogdGhpcy5wcm9maWxlLFxuICAgICAgZm9yY2U6IHRydWUsXG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIC4uLnRoaXMuZ2V0Q29udGV4dCgnZGVwbG95bWVudCcpLFxuICAgICAgICAuLi5kZXN0cm95QXJncz8uY29udGV4dCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgd2F0Y2god2F0Y2hBcmdzOiBPbWl0PERlcGxveU9wdGlvbnMsICdhcHAnIHwgJ3JlcXVpcmVBcHByb3ZhbCcgfCAncHJvZmlsZScgfCAnb3V0cHV0JyB8ICdsb29rdXBzJz4sIHdhdGNoRXZlbnRzOiBXYXRjaEV2ZW50cykge1xuICAgIGlmICghdGhpcy5oYXNWYWxpZFJlZ2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDZGtUZXN0QXBwLndhdGNoOiBub3QgaW5pdGlhbGl6ZWQgd2l0aCBhIHZhbGlkIHJlZ2lvbicpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuY2RrLndhdGNoKHtcbiAgICAgIC4uLkRFRkFVTFRfQVJHUyxcbiAgICAgIC4uLndhdGNoQXJncyxcbiAgICAgIG91dHB1dDogdGhpcy5vdXRwdXREaXJlY3RvcnksXG4gICAgICBwcm9maWxlOiB0aGlzLnByb2ZpbGUsXG4gICAgICByZXF1aXJlQXBwcm92YWw6IFJlcXVpcmVBcHByb3ZhbC5ORVZFUixcbiAgICAgIGFwcDogdGhpcy5hcHBDb21tYW5kLFxuICAgICAgY29udGV4dDoge1xuICAgICAgICAuLi50aGlzLmdldENvbnRleHQoJ2RlcGxveW1lbnQnKSxcbiAgICAgICAgLi4ud2F0Y2hBcmdzPy5jb250ZXh0LFxuICAgICAgfSxcbiAgICB9LCB3YXRjaEV2ZW50cyk7XG4gIH1cblxuICBwcml2YXRlIHNldFJlcHJvQ29tbWFuZChjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBlbnY6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pIHtcbiAgICAvLyBTaG93IHRoZSBjb21tYW5kIG5lY2Vzc2FyeSB0byByZXBybyB0aGlzXG4gICAgY29uc3QgZW52U2V0ID0gT2JqZWN0LmVudHJpZXMoZW52KS5tYXAoKFtrLCB2XSkgPT4gYCR7a309JyR7dn0nYCk7XG4gICAgY29uc3QgZW52Q21kID0gZW52U2V0Lmxlbmd0aCA+IDAgPyBbJ2VudicsIC4uLmVudlNldF0gOiBbXTtcblxuICAgIHRoaXMuc3ludGhSZXByb0NvbW1hbmQgPSBbXG4gICAgICAuLi5lbnZDbWQsXG4gICAgICAnY2RrJyxcbiAgICAgICdzeW50aCcsXG4gICAgICAnLWEnLFxuICAgICAgYCcke3RoaXMuYXBwQ29tbWFuZH0nYCxcbiAgICAgICctbycsXG4gICAgICBgJyR7dGhpcy5vdXRwdXREaXJlY3Rvcnl9J2AsXG4gICAgICAuLi5PYmplY3QuZW50cmllcyhjb250ZXh0KS5mbGF0TWFwKChbaywgdl0pID0+IHR5cGVvZiB2ICE9PSAnb2JqZWN0JyA/IFtgLWMgJyR7a309JHt2fSdgXSA6IFtdKSxcbiAgICBdLmpvaW4oJyAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIHRoZSBpbnRlZyBtYW5pZmVzdCB3aGljaCBjb250YWlucyBpbmZvcm1hdGlvblxuICAgKiBvbiBob3cgdG8gZXhlY3V0ZSB0aGUgdGVzdHNcbiAgICogRmlyc3Qgd2UgdHJ5IGFuZCBsb2FkIHRoZSBtYW5pZmVzdCBmcm9tIHRoZSBpbnRlZyBtYW5pZmVzdCAoaS5lLiBpbnRlZy5qc29uKVxuICAgKiBmcm9tIHRoZSBjbG91ZCBhc3NlbWJseS4gSWYgaXQgZG9lc24ndCBleGlzdCwgdGhlbiB3ZSBmYWxsYmFjayB0byB0aGVcbiAgICogXCJsZWdhY3kgbW9kZVwiIGFuZCBjcmVhdGUgYSBtYW5pZmVzdCBmcm9tIHByYWdtYVxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX2xvYWRNYW5pZmVzdCgpOiBQcm9taXNlPEludGVnVGVzdFN1aXRlIHwgTGVnYWN5SW50ZWdUZXN0U3VpdGU+IHtcbiAgICBpZiAoIWF3YWl0IHRoaXMuaGFzT3V0cHV0KCkgJiYgIXRoaXMub3B0aW9ucy5URVNUSU5HX3VzaW5nTW9ja3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3ludGggZGlkIG5vdCBwcm9kdWNlIG91dHB1dCBkaXJlY3Rvcnk6ICR7dGhpcy5vdXRwdXREaXJlY3Rvcnl9YCk7XG4gICAgfVxuICAgIGNvbnN0IG1hbmlmZXN0RGlyID0gdGhpcy5vdXRwdXREaXJlY3Rvcnk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRlc3RTdWl0ZSA9IEludGVnVGVzdFN1aXRlLmZyb21QYXRoKG1hbmlmZXN0RGlyKTtcbiAgICAgIHJldHVybiB0ZXN0U3VpdGU7XG4gICAgfSBjYXRjaCAobW9kZXJuRXJyb3I6IGFueSkge1xuICAgICAgLy8gT25seSBhdHRlbXB0IGxlZ2FjeSB0ZXN0IGNhc2UgaWYgdGhlIGludGVnIHRlc3QgbWFuaWZlc3Qgd2FzIG5vdCBmb3VuZFxuICAgICAgLy8gRm9yIGFueSBvdGhlciBlcnJvcnMsIGUuZy4gd2hlbiBwYXJzaW5nIHRoZSBtYW5pZmVzdCBmYWlscywgd2UgYWJvcnQuXG4gICAgICBpZiAoIShtb2Rlcm5FcnJvciBpbnN0YW5jZW9mIE5vTWFuaWZlc3RFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgbW9kZXJuRXJyb3I7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnNob3dPdXRwdXQpIHtcbiAgICAgICAgbG9nZ2VyLnRyYWNlKFxuICAgICAgICAgIFwiRmFpbGVkIHRvIGxvYWQgaW50ZWcgdGVzdCBtYW5pZmVzdCBmb3IgJyVzJy4gQXR0ZW1wdGluZyBhcyBkZXByZWNhdGVkIGxlZ2FjeSB0ZXN0IGluc3RlYWQuIEVycm9yIHdhczogJXNcIixcbiAgICAgICAgICBtYW5pZmVzdERpcixcbiAgICAgICAgICBtb2Rlcm5FcnJvci5tZXNzYWdlID8/IFN0cmluZyhtb2Rlcm5FcnJvciksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9sb2FkTGVnYWN5VGVzdFN1aXRlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfbG9hZExlZ2FjeVRlc3RTdWl0ZSgpOiBQcm9taXNlPExlZ2FjeUludGVnVGVzdFN1aXRlPiB7XG4gICAgY29uc3QgdGVzdENhc2VzID0gYXdhaXQgTGVnYWN5SW50ZWdUZXN0U3VpdGUuZnJvbUxlZ2FjeSh7XG4gICAgICBjZGs6IHRoaXMuY2RrLFxuICAgICAgdGVzdE5hbWU6IHRoaXMudGVzdC5ub3JtYWxpemVkVGVzdE5hbWUsXG4gICAgICBpbnRlZ1NvdXJjZUZpbGVQYXRoOiB0aGlzLnRlc3QuZmlsZU5hbWUsXG4gICAgICBsaXN0T3B0aW9uczoge1xuICAgICAgICAuLi50aGlzLmRlZmF1bHRBcmdzLFxuICAgICAgICBhbGw6IHRydWUsXG4gICAgICAgIGFwcDogdGhpcy5hcHBDb21tYW5kLFxuICAgICAgICBwcm9maWxlOiB0aGlzLnByb2ZpbGUsXG4gICAgICAgIG91dHB1dDogdGhpcy5vdXRwdXREaXJlY3RvcnksXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRoaXMubGVnYWN5Q29udGV4dCA9IExlZ2FjeUludGVnVGVzdFN1aXRlLmdldFByYWdtYUNvbnRleHQodGhpcy50ZXN0LmZpbGVOYW1lKTtcbiAgICByZXR1cm4gdGVzdENhc2VzO1xuICB9XG5cbiAgcHVibGljIGNsZWFudXAoKTogdm9pZCB7XG4gICAgY29uc3QgY2RrT3V0UGF0aCA9IHRoaXMub3V0cHV0RGlyZWN0b3J5O1xuICAgIGlmIChmcy5leGlzdHNTeW5jKGNka091dFBhdGgpKSB7XG4gICAgICBmcy5yZW1vdmVTeW5jKGNka091dFBhdGgpO1xuICAgIH1cbiAgICAvLyBDbGVhciBjYWNoZVxuICAgIHRoaXMuX3Rlc3RTdWl0ZSA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGVyZSBhcmUgYW55IGRlc3RydWN0aXZlIGNoYW5nZXMgdG8gYSBzdGFjayB0aGVuIHRoaXMgd2lsbCByZWNvcmRcbiAgICogdGhvc2UgaW4gdGhlIG1hbmlmZXN0Lmpzb24gZmlsZVxuICAgKi9cbiAgcHJpdmF0ZSByZW5kZXJUcmFjZURhdGEoZGVzdHJ1Y3RpdmVDaGFuZ2VzOiBEZXN0cnVjdGl2ZUNoYW5nZVtdKTogTWFuaWZlc3RUcmFjZSB7XG4gICAgY29uc3QgdHJhY2VEYXRhOiBNYW5pZmVzdFRyYWNlID0gbmV3IE1hcCgpO1xuICAgIGRlc3RydWN0aXZlQ2hhbmdlcy5mb3JFYWNoKGNoYW5nZSA9PiB7XG4gICAgICBjb25zdCB0cmFjZSA9IHRyYWNlRGF0YS5nZXQoY2hhbmdlLnN0YWNrTmFtZSk7XG4gICAgICBpZiAodHJhY2UpIHtcbiAgICAgICAgdHJhY2Uuc2V0KGNoYW5nZS5sb2dpY2FsSWQsIGAke0RFU1RSVUNUSVZFX0NIQU5HRVN9ICR7Y2hhbmdlLmltcGFjdH1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYWNlRGF0YS5zZXQoY2hhbmdlLnN0YWNrTmFtZSwgbmV3IE1hcChbXG4gICAgICAgICAgW2NoYW5nZS5sb2dpY2FsSWQsIGAke0RFU1RSVUNUSVZFX0NIQU5HRVN9ICR7Y2hhbmdlLmltcGFjdH1gXSxcbiAgICAgICAgXSkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB0cmFjZURhdGE7XG4gIH1cblxuICAvKipcbiAgICogSW4gY2FzZXMgd2hlcmUgd2UgZG8gbm90IHdhbnQgdG8gcmV0YWluIHRoZSBhc3NldHMsXG4gICAqIGZvciBleGFtcGxlLCBpZiB0aGUgYXNzZXRzIGFyZSB2ZXJ5IGxhcmdlLlxuICAgKlxuICAgKiBTaW5jZSBpdCBpcyBwb3NzaWJsZSB0byBkaXNhYmxlIHRoZSB1cGRhdGUgd29ya2Zsb3cgZm9yIGluZGl2aWR1YWwgdGVzdFxuICAgKiBjYXNlcywgdGhpcyBuZWVkcyB0byBmaXJzdCBnZXQgYSBsaXN0IG9mIHN0YWNrcyB0aGF0IGhhdmUgdGhlIHVwZGF0ZSB3b3JrZmxvd1xuICAgKiBkaXNhYmxlZCBhbmQgdGhlbiBkZWxldGUgYXNzZXRzIHRoYXQgcmVsYXRlIHRvIHRoYXQgc3RhY2suIEl0IGRvZXMgdGhhdFxuICAgKiBieSByZWFkaW5nIHRoZSBhc3NldCBtYW5pZmVzdCBmb3IgdGhlIHN0YWNrIGFuZCBkZWxldGluZyB0aGUgYXNzZXQgc291cmNlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHJlbW92ZUFzc2V0c0Zyb21TbmFwc2hvdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBzdGFja3MgPSB0aGlzLnRlc3RTdWl0ZS5nZXRTdGFja3NXaXRob3V0VXBkYXRlV29ya2Zsb3coKSA/PyBbXTtcbiAgICBjb25zdCBtYW5pZmVzdCA9IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIuZnJvbVBhdGgodGhpcy5vdXRwdXREaXJlY3RvcnkpO1xuICAgIGNvbnN0IGFzc2V0cyA9IGZsYXR0ZW4oc3RhY2tzLm1hcChzdGFjayA9PiB7XG4gICAgICByZXR1cm4gbWFuaWZlc3QuZ2V0QXNzZXRMb2NhdGlvbnNGb3JTdGFjayhzdGFjaykgPz8gW107XG4gICAgfSkpO1xuXG4gICAgYXNzZXRzLmZvckVhY2goYXNzZXQgPT4ge1xuICAgICAgY29uc3QgZmlsZU5hbWUgPSBwYXRoLmpvaW4odGhpcy5vdXRwdXREaXJlY3RvcnksIGFzc2V0KTtcbiAgICAgIGlmIChmcy5leGlzdHNTeW5jKGZpbGVOYW1lKSkge1xuICAgICAgICBpZiAoZnMubHN0YXRTeW5jKGZpbGVOYW1lKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgZnMucmVtb3ZlU3luYyhmaWxlTmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZnMudW5saW5rU3luYyhmaWxlTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGFzc2V0IGNhY2hlICguY2FjaGUvKSBmaWxlcyBmcm9tIHRoZSBzbmFwc2hvdC5cbiAgICogVGhlc2UgYXJlIGEgY2FjaGUgb2YgdGhlIGFzc2V0IHppcHMsIGJ1dCB3ZSBhcmUgZmluZSB3aXRoXG4gICAqIHJlLXppcHBpbmcgb24gZGVwbG95XG4gICAqL1xuICBwcml2YXRlIHJlbW92ZUFzc2V0c0NhY2hlRnJvbVNuYXBzaG90KCk6IHZvaWQge1xuICAgIGNvbnN0IGZpbGVzID0gZnMucmVhZGRpclN5bmModGhpcy5vdXRwdXREaXJlY3RvcnkpO1xuICAgIGZpbGVzLmZvckVhY2goZmlsZSA9PiB7XG4gICAgICBjb25zdCBmaWxlTmFtZSA9IHBhdGguam9pbih0aGlzLm91dHB1dERpcmVjdG9yeSwgZmlsZSk7XG4gICAgICBpZiAoZnMubHN0YXRTeW5jKGZpbGVOYW1lKS5pc0RpcmVjdG9yeSgpICYmIGZpbGUgPT09ICcuY2FjaGUnKSB7XG4gICAgICAgIGZzLmVtcHR5RGlyU3luYyhmaWxlTmFtZSk7XG4gICAgICAgIGZzLnJtZGlyU3luYyhmaWxlTmFtZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBzb21lIGNsZWFudXAgc3RlcHMgYWZ0ZXIgdGhlIHNuYXBzaG90IGlzIGNyZWF0ZWRcbiAgICogQW55dGltZSB0aGUgc25hcHNob3QgbmVlZHMgdG8gYmUgbW9kaWZpZWQgYWZ0ZXIgY3JlYXRpb25cbiAgICogdGhlIGxvZ2ljIHNob3VsZCBsaXZlIGhlcmUuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNsZWFudXBHb2xkZW5TbmFwc2hvdChkZXN0cnVjdGl2ZUNoYW5nZXM6IERlc3RydWN0aXZlQ2hhbmdlW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIWF3YWl0IHRoaXMuaGFzT3V0cHV0KCkpIHtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIG5vdCBiZSBwb3NzaWJsZSwgYnV0IGEgbG90IG9mIHRoZSB0ZXN0cyBkZXBlbmQgb24gdGhpcyBiZWluZyBhIG5vLW9wXG4gICAgICAvLyBpZiBubyBvdXRwdXQgZGlyZWN0b3J5IGdvdCBwcm9kdWNlZC5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnJlbW92ZUFzc2V0c0Zyb21TbmFwc2hvdCgpO1xuICAgIHRoaXMucmVtb3ZlQXNzZXRzQ2FjaGVGcm9tU25hcHNob3QoKTtcbiAgICBjb25zdCBhc3NlbWJseSA9IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIuZnJvbVBhdGgodGhpcy5vdXRwdXREaXJlY3RvcnkpO1xuICAgIGFzc2VtYmx5LmNsZWFuTWFuaWZlc3QoKTtcbiAgICBhc3NlbWJseS5yZWNvcmRUcmFjZSh0aGlzLnJlbmRlclRyYWNlRGF0YShkZXN0cnVjdGl2ZUNoYW5nZXMpKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYSBsZWdhY3kgdGVzdCB0aGVuIGNyZWF0ZSBhbiBpbnRlZyBtYW5pZmVzdFxuICAgIC8vIGluIHRoZSBzbmFwc2hvdCBkaXJlY3Rvcnkgd2hpY2ggY2FuIGJlIHVzZWQgZm9yIHRoZVxuICAgIC8vIHVwZGF0ZSB3b3JrZmxvdy4gU2F2ZSBhbnkgbGVnYWN5Q29udGV4dCBhcyB3ZWxsIHNvIHRoYXQgaXQgY2FuIGJlIHJlYWRcbiAgICAvLyB0aGUgbmV4dCB0aW1lXG4gICAgY29uc3QgYWN0dWFsVGVzdFN1aXRlID0gdGhpcy50ZXN0U3VpdGU7XG4gICAgYWN0dWFsVGVzdFN1aXRlLmVuYWJsZUxvb2t1cHMgPSB0cnVlO1xuXG4gICAgaWYgKGFjdHVhbFRlc3RTdWl0ZSBpbnN0YW5jZW9mIExlZ2FjeUludGVnVGVzdFN1aXRlKSB7XG4gICAgICBhY3R1YWxUZXN0U3VpdGUuc2F2ZU1hbmlmZXN0KHRoaXMub3V0cHV0RGlyZWN0b3J5LCB0aGlzLmxlZ2FjeUNvbnRleHQpO1xuICAgIH0gZWxzZSBpZiAoYWN0dWFsVGVzdFN1aXRlIGluc3RhbmNlb2YgSW50ZWdUZXN0U3VpdGUpIHtcbiAgICAgIGFjdHVhbFRlc3RTdWl0ZS5zYXZlTWFuaWZlc3QodGhpcy5vdXRwdXREaXJlY3RvcnkpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRDb250ZXh0KGZvclNuYXBzaG90OiAnc25hcHNob3QnIHwgJ2RlcGxveW1lbnQnKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgaWYgKHRoaXMuX2xlZ2FjeUVuYWJsZUxvb2t1cHMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNdXN0IGNhbGwgY29uZmlndXJlTGVnYWN5RW5hYmxlTG9va3VwcyBiZWZvcmUgc3ludGhpbmcnKTtcbiAgICB9XG4gICAgLy8gTG9hZCB0aGUgdGVzdC1zcGVjaWZpYyBjb250ZXh0IChmcm9tIGBpbnRlZy5jb250ZXh0Lmpzb25gIG9yIGBjZGsuanNvbiNjb250ZXh0YCksIGlmIGFueS5cbiAgICAvLyBJZiBub3QgZm91bmQsIHVzZSB0aGUgYnVpbHQtaW4gY3VycmVudCBmZWF0dXJlIGZsYWdzIChhdCB0aGUgcmlzayBvZiBuZXdlciBmZWF0dXJlIGZsYWdzIGNoYW5naW5nXG4gICAgLy8gdGhlIHNuYXBzaG90cykuXG4gICAgY29uc3QgZmVhdHVyZUZsYWdzID0gdGhpcy50ZXN0U3BlY2lmaWNDb250ZXh0ID8/IGN1cnJlbnRseVJlY29tbWVuZGVkQXdzQ2RrTGliRmxhZ3MoKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5mZWF0dXJlRmxhZ3MsXG4gICAgICAuLi50aGlzLmxlZ2FjeUNvbnRleHQsXG5cbiAgICAgIC8vIFRoZSBfbGVnYWN5RW5hYmxlTG9va3VwcyBmbGFnIGlzIGNyYXp5IGJ1dCBpcyBvbmx5IHRoZXJlIHRvIG5vdCBkaXN0dXJiIGV4aXN0aW5nIHNuYXBzaG90cyB0b28gbXVjaC5cbiAgICAgIC4uLihmb3JTbmFwc2hvdCA9PT0gJ3NuYXBzaG90JyAmJiB0aGlzLl9sZWdhY3lFbmFibGVMb29rdXBzICE9PSBmYWxzZSA/IERFRkFVTFRfU1lOVEhfT1BUSU9OUy5jb250ZXh0IDoge30pLFxuXG4gICAgICAvLyBEb24ndCByZWNvcmQgY3JlYXRpb24gc3RhY2sgdHJhY2VzIGluIHRoZSBzbmFwc2hvdCwgc2luY2UgdGhleSBqdXN0IHRha2UgdXAgc3BhY2UgYW5kIGFyZSBuZXZlciBkZXRlcm1pbmlzdGljLlxuICAgICAgJ2F3czpjZGs6ZGlzYWJsZS1jcmVhdGlvbi1zdGFjay10cmFjZXMnOiB0cnVlLFxuXG4gICAgICAvLyBXZSBvcmlnaW5hbGx5IGhhZCBQTEFOTkVEIHRvIHNldCB0aGlzIHRvIFsnYXdzJywgJ2F3cy1jbiddLCBidXQgZHVlIHRvIGEgcHJvZ3JhbW1pbmcgbWlzdGFrZVxuICAgICAgLy8gaXQgd2FzIHNldCB0byBldmVyeXRoaW5nLiBJbiB0aGlzIFBSLCBzZXQgaXQgdG8gZXZlcnl0aGluZyB0byBub3QgbWVzcyB1cCBhbGwgdGhlIHNuYXBzaG90cy5cbiAgICAgICdAYXdzLWNkay9jb3JlOnRhcmdldC1wYXJ0aXRpb25zJzogdW5kZWZpbmVkLFxuXG4gICAgICAvKiAtLS0tLS0tLS0tLS0tLS0tIFRIRSBGVVRVUkUgTElWRVMgQkVMT1ctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAvLyBSZXN0cmljdGluZyB0byB0aGVzZSB0YXJnZXQgcGFydGl0aW9ucyBtYWtlcyBtb3N0IHNlcnZpY2UgcHJpbmNpcGFscyBzeW50aGVzaXplIHRvXG4gICAgICAvLyBgc2VydmljZS4ke1VSTF9TVUZGSVh9YCwgd2hpY2ggaXMgdGVjaG5pY2FsbHkgKmluY29ycmVjdCogKGl0J3Mgb25seSBgYW1hem9uYXdzLmNvbWBcbiAgICAgIC8vIG9yIGBhbWF6b25hd3MuY29tLmNuYCwgbmV2ZXIgVXJsU3VmZml4IGZvciBhbnkgb2YgdGhlIHJlc3RyaWN0ZWQgcmVnaW9ucykgYnV0IGl0J3Mgd2hhdFxuICAgICAgLy8gbW9zdCBleGlzdGluZyBpbnRlZyB0ZXN0cyBjb250YWluLCBhbmQgd2Ugd2FudCB0byBkaXN0dXJiIGFzIGZldyBhcyBwb3NzaWJsZS5cbiAgICAgIC8vIFtUQVJHRVRfUEFSVElUSU9OU106IFsnYXdzJywgJ2F3cy1jbiddLFxuICAgICAgLyogLS0tLS0tLS0tLS0tLS0tLSBFTkQgT0YgVEhFIEZVVFVSRSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG4gICAgfTtcbiAgfVxufVxuXG4vLyBEZWZhdWx0IGNvbnRleHQgd2UgcnVuIGFsbCBpbnRlZyB0ZXN0cyB3aXRoLCBzbyB0aGV5IGRvbid0IGRlcGVuZCBvbiB0aGVcbi8vIGFjY291bnQgb2YgdGhlIGV4ZXJjaXNpbmcgdXNlci5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1NZTlRIX09QVElPTlMgPSB7XG4gIGNvbnRleHQ6IHtcbiAgICAvLyBXZSBoYXZlIHRyYWRpdGlvbmFsbHkgc2V0IHRoaXMsIGJ1dCBpdCdzIHF1aXRlIGEgYmFkIGlkZWEuIEl0IG1ha2VzIHJlZ2lvbi1hZ25vc3RpYyBzdGFja3MgdW5kZXBsb3lhYmxlLCBhbmQgdGhlcmUncyByZWFsbHkgbm8gcmVhc29uIGZvciB0aGF0LlxuICAgIC8vIEhvd2V2ZXIsIGlmIHdlIHVuc2V0IHRoaXMsIHdlIHdpbGwgYnJlYWsgbWFueSBleGlzdGluZyBzbmFwc2hvdHMgc28gd2Uga2VlcCBpdCBmb3Igbm93LlxuICAgIFtBVkFJTEFCSUxJVFlfWk9ORV9GQUxMQkFDS19DT05URVhUX0tFWV06IFsndGVzdC1yZWdpb24tMWEnLCAndGVzdC1yZWdpb24tMWInLCAndGVzdC1yZWdpb24tMWMnXSxcbiAgICAnYXZhaWxhYmlsaXR5LXpvbmVzOmFjY291bnQ9MTIzNDU2Nzg6cmVnaW9uPXRlc3QtcmVnaW9uJzogWyd0ZXN0LXJlZ2lvbi0xYScsICd0ZXN0LXJlZ2lvbi0xYicsICd0ZXN0LXJlZ2lvbi0xYyddLFxuICAgICdzc206YWNjb3VudD0xMjM0NTY3ODpwYXJhbWV0ZXJOYW1lPS9hd3Mvc2VydmljZS9hbWktYW1hem9uLWxpbnV4LWxhdGVzdC9hbXpuLWFtaS1odm0teDg2XzY0LWdwMjpyZWdpb249dGVzdC1yZWdpb24nOiAnYW1pLTEyMzQnLFxuICAgICdzc206YWNjb3VudD0xMjM0NTY3ODpwYXJhbWV0ZXJOYW1lPS9hd3Mvc2VydmljZS9hbWktYW1hem9uLWxpbnV4LWxhdGVzdC9hbXpuMi1hbWktaHZtLXg4Nl82NC1ncDI6cmVnaW9uPXRlc3QtcmVnaW9uJzogJ2FtaS0xMjM0JyxcbiAgICAnc3NtOmFjY291bnQ9MTIzNDU2Nzg6cGFyYW1ldGVyTmFtZT0vYXdzL3NlcnZpY2UvZWNzL29wdGltaXplZC1hbWkvYW1hem9uLWxpbnV4L3JlY29tbWVuZGVkOnJlZ2lvbj10ZXN0LXJlZ2lvbic6ICd7XCJpbWFnZV9pZFwiOiBcImFtaS0xMjM0XCJ9JyxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHN0eWxpc3RpYy9tYXgtbGVuXG4gICAgJ2FtaTphY2NvdW50PTEyMzQ1Njc4OmZpbHRlcnMuaW1hZ2UtdHlwZS4wPW1hY2hpbmU6ZmlsdGVycy5uYW1lLjA9YW16bi1hbWktdnBjLW5hdC0qOmZpbHRlcnMuc3RhdGUuMD1hdmFpbGFibGU6b3duZXJzLjA9YW1hem9uOnJlZ2lvbj10ZXN0LXJlZ2lvbic6ICdhbWktMTIzNCcsXG4gICAgJ3ZwYy1wcm92aWRlcjphY2NvdW50PTEyMzQ1Njc4OmZpbHRlci5pc0RlZmF1bHQ9dHJ1ZTpyZWdpb249dGVzdC1yZWdpb246cmV0dXJuQXN5bW1ldHJpY1N1Ym5ldHM9dHJ1ZSc6IHtcbiAgICAgIHZwY0lkOiAndnBjLTYwOTAwOTA1JyxcbiAgICAgIHN1Ym5ldEdyb3VwczogW1xuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ1B1YmxpYycsXG4gICAgICAgICAgbmFtZTogJ1B1YmxpYycsXG4gICAgICAgICAgc3VibmV0czogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBzdWJuZXRJZDogJ3N1Ym5ldC1lMTk0NTVjYScsXG4gICAgICAgICAgICAgIGF2YWlsYWJpbGl0eVpvbmU6ICd1cy1lYXN0LTFhJyxcbiAgICAgICAgICAgICAgcm91dGVUYWJsZUlkOiAncnRiLWUxOTQ1NWNhJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHN1Ym5ldElkOiAnc3VibmV0LWUwYzI0Nzk3JyxcbiAgICAgICAgICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogJ3VzLWVhc3QtMWInLFxuICAgICAgICAgICAgICByb3V0ZVRhYmxlSWQ6ICdydGItZTBjMjQ3OTcnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc3VibmV0SWQ6ICdzdWJuZXQtY2NkNzczOTUnLFxuICAgICAgICAgICAgICBhdmFpbGFiaWxpdHlab25lOiAndXMtZWFzdC0xYycsXG4gICAgICAgICAgICAgIHJvdXRlVGFibGVJZDogJ3J0Yi1jY2Q3NzM5NScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0sXG4gIH0sXG4gIGVudjoge1xuICAgIENES19JTlRFR19BQ0NPVU5UOiAnMTIzNDU2NzgnLFxuICAgIENES19JTlRFR19SRUdJT046ICd0ZXN0LXJlZ2lvbicsXG4gICAgQ0RLX0lOVEVHX0hPU1RFRF9aT05FX0lEOiAnWjIzQUJDNFhZWkwwNUInLFxuICAgIENES19JTlRFR19IT1NURURfWk9ORV9OQU1FOiAnZXhhbXBsZS5jb20nLFxuICAgIENES19JTlRFR19ET01BSU5fTkFNRTogJyouZXhhbXBsZS5jb20nLFxuICAgIENES19JTlRFR19DRVJUX0FSTjogJ2Fybjphd3M6YWNtOnRlc3QtcmVnaW9uOjEyMzQ1Njc4OmNlcnRpZmljYXRlLzg2NDY4MjA5LWEyNzItNTk1ZC1iODMxLTBlZmI2NDIxMjY1eicsXG4gICAgQ0RLX0lOVEVHX1NVQk5FVF9JRDogJ3N1Ym5ldC0wZGZmMWEzOTlkOGY2ZjkyYycsXG4gIH0sXG59O1xuXG4vKipcbiAqIFJldHVybiB0aGUgY3VycmVudGx5IHJlY29tbWVuZGVkIGZsYWdzIGZvciBgYXdzLWNkay1saWJgLlxuICpcbiAqIFRoZXNlIGhhdmUgYmVlbiBidWlsdCBpbnRvIHRoZSBDTEkgYXQgYnVpbGQgdGltZS4gSWYgdGhpcyBldmVyIGdldHMgY2hhbmdlZFxuICogYmFjayB0byBhIGR5bmFtaWMgbG9hZCwgcmVtZW1iZXIgdGhhdCB0aGlzIHNvdXJjZSBmaWxlIG1heSBiZSBidW5kbGVkIGludG9cbiAqIGEgSmF2YVNjcmlwdCBidW5kbGUsIGFuZCBgX19kaXJuYW1lYCBtaWdodCBub3QgcG9pbnQgd2hlcmUgeW91IHRoaW5rIGl0IGRvZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjdXJyZW50bHlSZWNvbW1lbmRlZEF3c0Nka0xpYkZsYWdzKCkge1xuICByZXR1cm4gcmVjb21tZW5kZWRGbGFnc0ZpbGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU25hcHNob3RBc3NlbWJseSB7XG4gIC8qKlxuICAgKiBNYXAgb2Ygc3RhY2tzIHRoYXQgYXJlIHBhcnQgb2YgdGhpcyBhc3NlbWJseVxuICAgKi9cbiAgW3N0YWNrTmFtZTogc3RyaW5nXToge1xuICAgIC8qKlxuICAgICAqIEFsbCB0ZW1wbGF0ZXMgZm9yIHRoaXMgc3RhY2ssIGluY2x1ZGluZyBuZXN0ZWQgc3RhY2tzXG4gICAgICovXG4gICAgdGVtcGxhdGVzOiB7XG4gICAgICBbdGVtcGxhdGVJZDogc3RyaW5nXTogYW55O1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBMaXN0IG9mIGFzc2V0IElkcyB0aGF0IGFyZSB1c2VkIGJ5IHRoaXMgYXNzZW1ibHlcbiAgICAgKi9cbiAgICBhc3NldHM6IHN0cmluZ1tdO1xuICB9O1xufVxuXG4vKipcbiAqIERlZmF1bHQgb3B0aW9ucyB0byBwYXNzIHRvIHRoZSBDREsgQ0xJXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0FSR1M6IERlZmF1bHRDZGtPcHRpb25zID0ge1xuICBwYXRoTWV0YWRhdGE6IGZhbHNlLFxuICBhc3NldE1ldGFkYXRhOiBmYWxzZSxcbiAgdmVyc2lvblJlcG9ydGluZzogZmFsc2UsXG59O1xuIl19
|