projen
Version:
CDK for software projects
322 lines • 67.7 kB
JavaScript
"use strict";
var _a, _b, _c, _d;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Jest = exports.JestReporter = exports.UpdateSnapshot = exports.WatchPlugin = exports.Transform = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = require("path");
const component_1 = require("../component");
const json_1 = require("../json");
const util_1 = require("../util");
const DEFAULT_TEST_REPORTS_DIR = "test-reports";
class Transform {
constructor(name, options) {
this.name = name;
this.options = options;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
if (this.options != null) {
return [this.name, this.options];
}
return this.name;
}
}
exports.Transform = Transform;
_a = JSII_RTTI_SYMBOL_1;
Transform[_a] = { fqn: "projen.javascript.Transform", version: "0.95.2" };
class WatchPlugin {
constructor(name, options) {
this.name = name;
this.options = options;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
if (this.options != null) {
return [this.name, this.options];
}
return this.name;
}
}
exports.WatchPlugin = WatchPlugin;
_b = JSII_RTTI_SYMBOL_1;
WatchPlugin[_b] = { fqn: "projen.javascript.WatchPlugin", version: "0.95.2" };
var UpdateSnapshot;
(function (UpdateSnapshot) {
/**
* Always update snapshots in "test" task.
*/
UpdateSnapshot["ALWAYS"] = "always";
/**
* Never update snapshots in "test" task and create a separate "test:update" task.
*/
UpdateSnapshot["NEVER"] = "never";
})(UpdateSnapshot || (exports.UpdateSnapshot = UpdateSnapshot = {}));
class JestReporter {
constructor(name, options) {
this.name = name;
this.options = options;
}
/**
* @jsii ignore
* @internal
*/
toJSON() {
if (this.options == null) {
return this.name;
}
return [this.name, this.options];
}
}
exports.JestReporter = JestReporter;
_c = JSII_RTTI_SYMBOL_1;
JestReporter[_c] = { fqn: "projen.javascript.JestReporter", version: "0.95.2" };
/**
* Installs the following npm scripts:
*
* - `test`, intended for testing locally and in CI. Will update snapshots unless `updateSnapshot: UpdateSnapshot: NEVER` is set.
* - `test:watch`, intended for automatically rerunning tests when files change.
* - `test:update`, intended for testing locally and updating snapshots to match the latest unit under test. Only available when `updateSnapshot: UpdateSnapshot: NEVER`.
*
*/
class Jest extends component_1.Component {
/**
* Returns the singleton Jest component of a project or undefined if there is none.
*/
static of(project) {
const isJest = (c) => c instanceof Jest;
return project.components.find(isJest);
}
constructor(project, options = {}) {
super(project);
this.testMatch = new Array();
// hard deprecation
if (options.typescriptConfig) {
throw new Error('"jestOptions.typescriptConfig" is deprecated. Use "typescriptProject.tsconfigDev" instead');
}
// Jest snapshot files are generated files!
project.root.annotateGenerated("*.snap");
this.jestVersion = options.jestVersion ? `@${options.jestVersion}` : "";
project.addDevDeps(`jest${this.jestVersion}`);
// use native v8 coverage collection as default
// https://jestjs.io/docs/en/cli#--coverageproviderprovider
const coverageProvider = this.jestConfig?.coverageProvider ?? "v8";
this.jestConfig = {
coverageProvider,
...options.jestConfig,
additionalOptions: undefined,
...options.jestConfig?.additionalOptions,
};
this.extraCliOptions = options.extraCliOptions ?? [];
this.passWithNoTests = options.passWithNoTests ?? true;
this.ignorePatterns = this.jestConfig?.testPathIgnorePatterns ??
options.ignorePatterns ?? ["/node_modules/"];
this.watchIgnorePatterns = this.jestConfig?.watchPathIgnorePatterns ?? [
"/node_modules/",
];
this.coverageReporters = this.jestConfig?.coverageReporters ?? [
"json",
"lcov",
"clover",
"cobertura",
];
if (this.jestConfig?.testMatch && this.jestConfig.testMatch.length > 0) {
this.jestConfig.testMatch.forEach((pattern) => this.addTestMatch(pattern));
}
const coverageDirectory = this.jestConfig?.coverageDirectory ?? "coverage";
this.reporters = [];
if (options.preserveDefaultReporters ?? true) {
this.reporters.unshift(new JestReporter("default"));
}
this.config = {
...this.jestConfig,
clearMocks: this.jestConfig?.clearMocks ?? true,
collectCoverage: options.coverage ?? this.jestConfig?.collectCoverage ?? true,
coverageReporters: this.coverageReporters,
coverageDirectory: coverageDirectory,
coveragePathIgnorePatterns: this.jestConfig?.coveragePathIgnorePatterns ?? this.ignorePatterns,
testPathIgnorePatterns: this.ignorePatterns,
watchPathIgnorePatterns: this.watchIgnorePatterns,
// @ts-expect-error - lazily loading the testMatch in order to only apply defaults if none are ever added
testMatch: () => this.testMatch.length > 0
? this.testMatch
: [`**/__tests__/**/*.[jt]s?(x)`, `**/*(*.)@(spec|test).[jt]s?(x)`], // Jest defaults
reporters: this.reporters,
snapshotResolver: (() => this._snapshotResolver),
};
if (options.junitReporting ?? true) {
const reportsDir = DEFAULT_TEST_REPORTS_DIR;
this.addReporter(new JestReporter("jest-junit", { outputDirectory: reportsDir }));
project.addDevDeps("jest-junit@^16");
project.gitignore.exclude("# jest-junit artifacts", `/${reportsDir}/`, "junit.xml");
project.npmignore?.exclude("# jest-junit artifacts", `/${reportsDir}/`, "junit.xml");
}
if (this.jestConfig?.reporters) {
for (const reporter of this.jestConfig.reporters) {
this.addReporter(reporter);
}
}
if (this.jestConfig?.coverageThreshold) {
this.config.coverageThreshold = {
global: this.jestConfig?.coverageThreshold,
};
}
this.configureTestCommand(options.updateSnapshot ?? UpdateSnapshot.ALWAYS);
if (options.configFilePath) {
this.file = new json_1.JsonFile(project, options.configFilePath, {
obj: this.config,
});
project.npmignore?.addPatterns(`/${this.file.path}`);
}
else {
project.addFields({ jest: this.config });
}
const coverageDirectoryPath = path.posix.join("/", coverageDirectory, "/");
project.npmignore?.exclude(coverageDirectoryPath);
project.gitignore.exclude(coverageDirectoryPath);
if (options.coverageText ?? true) {
this.coverageReporters.push("text");
}
}
/**
* Adds a test match pattern.
* @param pattern glob pattern to match for tests
*/
addTestMatch(pattern) {
this.testMatch.push(pattern);
}
/**
* Build standard test match patterns for a directory.
* @param dirs The directories to add test matches for. Matches any folder if not specified or an empty array.
* @param options Options for building test match patterns.
*/
discoverTestMatchPatternsForDirs(dirs, options) {
const testPatterns = this.buildTestMatchPatternsForDirs(dirs, options);
testPatterns.forEach((pattern) => this.addTestMatch(pattern));
}
/**
* Build standard test match patterns for a directory.
* @param dirs The directories to add test matches for. Matches any folder if not specified.
* @param fileExtensionPattern The file extension pattern to use. Defaults to "[jt]s?(x)".
* @returns The test match patterns.
*/
buildTestMatchPatternsForDirs(dirs, options) {
const fileExtensionPattern = options?.fileExtensionPattern ?? "[jt]s?(x)";
return [
`<rootDir>/@(${dirs.join("|")})/**/*(*.)@(spec|test).${fileExtensionPattern}`,
`<rootDir>/@(${dirs.join("|")})/**/__tests__/**/*.${fileExtensionPattern}`,
];
}
/**
* Adds a watch ignore pattern.
* @param pattern The pattern (regular expression).
*/
addWatchIgnorePattern(pattern) {
this.watchIgnorePatterns.push(pattern);
}
addIgnorePattern(pattern) {
this.ignorePatterns.push(pattern);
}
addReporter(reporter) {
this.reporters.push(reporter);
}
/**
* Adds a a setup file to Jest's setupFiles configuration.
* @param file File path to setup file
*/
addSetupFile(file) {
if (!this.config.setupFiles) {
this.config.setupFiles = [];
}
this.config.setupFiles.push(file);
}
/**
* Adds a a setup file to Jest's setupFilesAfterEnv configuration.
* @param file File path to setup file
*/
addSetupFileAfterEnv(file) {
if (!this.config.setupFilesAfterEnv) {
this.config.setupFilesAfterEnv = [];
}
this.config.setupFilesAfterEnv.push(file);
}
addSnapshotResolver(file) {
const normalized = (0, util_1.normalizePersistedPath)(file);
this._snapshotResolver = normalized;
}
/**
* Adds one or more moduleNameMapper entries to Jest's configuration.
* Will overwrite if the same key is used as a pre-existing one.
*
* @param moduleNameMapperAdditions - A map from regular expressions to module names or to arrays of module names that allow to stub out resources, like images or styles with a single module.
*/
addModuleNameMappers(moduleNameMapperAdditions) {
const existingModuleNameMapper = this.config.moduleNameMapper ?? {};
this.config.moduleNameMapper = {
...existingModuleNameMapper,
...moduleNameMapperAdditions,
};
}
/**
* Adds one or more modulePaths to Jest's configuration.
*
* @param modulePaths - An array of absolute paths to additional locations to search when resolving modules *
*/
addModulePaths(...modulePaths) {
const existingModulePaths = this.config.modulePaths ?? [];
this.config.modulePaths = [
...new Set([...existingModulePaths, ...modulePaths]),
];
}
/**
* Adds one or more roots to Jest's configuration.
*
* @param roots - A list of paths to directories that Jest should use to search for files in.
*/
addRoots(...roots) {
const existingRoots = this.config.roots ?? [];
this.config.roots = [...new Set([...existingRoots, ...roots])];
}
configureTestCommand(updateSnapshot) {
const jestOpts = this.extraCliOptions;
const jestConfigOpts = this.file && this.file.path != "jest.config.json"
? ` -c ${this.file.path}`
: "";
if (this.passWithNoTests) {
jestOpts.push("--passWithNoTests");
}
if (updateSnapshot === UpdateSnapshot.ALWAYS) {
jestOpts.push("--updateSnapshot");
}
else {
jestOpts.push("--ci"); // to prevent accepting new snapshots
const testUpdate = this.project.tasks.tryFind("test:update");
if (!testUpdate) {
this.project.addTask("test:update", {
description: "Update jest snapshots",
exec: `jest --updateSnapshot ${jestOpts.join(" ")}${jestConfigOpts}`,
receiveArgs: true,
});
}
}
this.project.testTask.exec(`jest ${jestOpts.join(" ")}${jestConfigOpts}`, {
receiveArgs: true,
});
const testWatch = this.project.tasks.tryFind("test:watch");
if (!testWatch) {
this.project.addTask("test:watch", {
description: "Run jest in watch mode",
exec: `jest --watch${jestConfigOpts}`,
});
}
}
}
exports.Jest = Jest;
_d = JSII_RTTI_SYMBOL_1;
Jest[_d] = { fqn: "projen.javascript.Jest", version: "0.95.2" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9qYXZhc2NyaXB0L2plc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2QkFBNkI7QUFDN0IsNENBQXlDO0FBRXpDLGtDQUFtQztBQUVuQyxrQ0FBaUQ7QUFFakQsTUFBTSx3QkFBd0IsR0FBRyxjQUFjLENBQUM7QUEyZWhELE1BQWEsU0FBUztJQUNwQixZQUNtQixJQUFZLEVBQ1osT0FBYTtRQURiLFNBQUksR0FBSixJQUFJLENBQVE7UUFDWixZQUFPLEdBQVAsT0FBTyxDQUFNO0lBQzdCLENBQUM7SUFFSjs7O09BR0c7SUFDSSxNQUFNO1FBQ1gsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ25CLENBQUM7O0FBZkgsOEJBZ0JDOzs7QUFFRCxNQUFhLFdBQVc7SUFDdEIsWUFDbUIsSUFBWSxFQUNaLE9BQWE7UUFEYixTQUFJLEdBQUosSUFBSSxDQUFRO1FBQ1osWUFBTyxHQUFQLE9BQU8sQ0FBTTtJQUM3QixDQUFDO0lBRUo7OztPQUdHO0lBQ0ksTUFBTTtRQUNYLElBQUksSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbkMsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztJQUNuQixDQUFDOztBQWZILGtDQWdCQzs7O0FBMkZELElBQVksY0FVWDtBQVZELFdBQVksY0FBYztJQUN4Qjs7T0FFRztJQUNILG1DQUFpQixDQUFBO0lBRWpCOztPQUVHO0lBQ0gsaUNBQWUsQ0FBQTtBQUNqQixDQUFDLEVB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QyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRTtnQkFDakMsV0FBVyxFQUFFLHdCQUF3QjtnQkFDckMsSUFBSSxFQUFFLGVBQWUsY0FBYyxFQUFFO2FBQ3RDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDOztBQXBVSCxvQkFxVUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgeyBOb2RlUHJvamVjdCB9IGZyb20gXCIuLi9qYXZhc2NyaXB0XCI7XG5pbXBvcnQgeyBKc29uRmlsZSB9IGZyb20gXCIuLi9qc29uXCI7XG5pbXBvcnQgeyBQcm9qZWN0IH0gZnJvbSBcIi4uL3Byb2plY3RcIjtcbmltcG9ydCB7IG5vcm1hbGl6ZVBlcnNpc3RlZFBhdGggfSBmcm9tIFwiLi4vdXRpbFwiO1xuXG5jb25zdCBERUZBVUxUX1RFU1RfUkVQT1JUU19ESVIgPSBcInRlc3QtcmVwb3J0c1wiO1xuXG4vLyBQdWxsZWQgZnJvbSBodHRwczovL2plc3Rqcy5pby9kb2NzL2VuL2NvbmZpZ3VyYXRpb25cbmV4cG9ydCBpbnRlcmZhY2UgSmVzdENvbmZpZ09wdGlvbnMge1xuICAvKipcbiAgICogVGhpcyBvcHRpb24gdGVsbHMgSmVzdCB0aGF0IGFsbCBpbXBvcnRlZCBtb2R1bGVzIGluIHlvdXIgdGVzdHMgc2hvdWxkIGJlIG1vY2tlZCBhdXRvbWF0aWNhbGx5LlxuICAgKiBBbGwgbW9kdWxlcyB1c2VkIGluIHlvdXIgdGVzdHMgd2lsbCBoYXZlIGEgcmVwbGFjZW1lbnQgaW1wbGVtZW50YXRpb24sIGtlZXBpbmcgdGhlIEFQSSBzdXJmYWNlXG4gICAqIEBkZWZhdWx0IC0gZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGF1dG9tb2NrPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQnkgZGVmYXVsdCwgSmVzdCBydW5zIGFsbCB0ZXN0cyBhbmQgcHJvZHVjZXMgYWxsIGVycm9ycyBpbnRvIHRoZSBjb25zb2xlIHVwb24gY29tcGxldGlvbi5cbiAgICogVGhlIGJhaWwgY29uZmlnIG9wdGlvbiBjYW4gYmUgdXNlZCBoZXJlIHRvIGhhdmUgSmVzdCBzdG9wIHJ1bm5pbmcgdGVzdHMgYWZ0ZXIgbiBmYWlsdXJlcy5cbiAgICogU2V0dGluZyBiYWlsIHRvIHRydWUgaXMgdGhlIHNhbWUgYXMgc2V0dGluZyBiYWlsIHRvIDEuXG4gICAqIEBkZWZhdWx0IC0gMFxuICAgKi9cbiAgcmVhZG9ubHkgYmFpbD86IGJvb2xlYW4gfCBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBkaXJlY3Rvcnkgd2hlcmUgSmVzdCBzaG91bGQgc3RvcmUgaXRzIGNhY2hlZCBkZXBlbmRlbmN5IGluZm9ybWF0aW9uXG4gICAqIEBkZWZhdWx0IC0gXCIvdG1wLzxwYXRoPlwiXG4gICAqL1xuICByZWFkb25seSBjYWNoZURpcmVjdG9yeT86IHN0cmluZztcblxuICAvKipcbiAgICogQXV0b21hdGljYWxseSBjbGVhciBtb2NrIGNhbGxzIGFuZCBpbnN0YW5jZXMgYmVmb3JlIGV2ZXJ5IHRlc3QuXG4gICAqIEVxdWl2YWxlbnQgdG8gY2FsbGluZyBqZXN0LmNsZWFyQWxsTW9ja3MoKSBiZWZvcmUgZWFjaCB0ZXN0LlxuICAgKiBUaGlzIGRvZXMgbm90IHJlbW92ZSBhbnkgbW9jayBpbXBsZW1lbnRhdGlvbiB0aGF0IG1heSBoYXZlIGJlZW4gcHJvdmlkZWRcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2xlYXJNb2Nrcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBjb3ZlcmFnZSBpbmZvcm1hdGlvbiBzaG91bGQgYmUgY29sbGVjdGVkIHdoaWxlIGV4ZWN1dGluZyB0aGUgdGVzdC5cbiAgICogQmVjYXVzZSB0aGlzIHJldHJvZml0cyBhbGwgZXhlY3V0ZWQgZmlsZXMgd2l0aCBjb3ZlcmFnZSBjb2xsZWN0aW9uIHN0YXRlbWVudHMsXG4gICAqIGl0IG1heSBzaWduaWZpY2FudGx5IHNsb3cgZG93biB5b3VyIHRlc3RzXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGNvbGxlY3RDb3ZlcmFnZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEFuIGFycmF5IG9mIGdsb2IgcGF0dGVybnMgaW5kaWNhdGluZyBhIHNldCBvZiBmaWxlcyBmb3Igd2hpY2ggY292ZXJhZ2UgaW5mb3JtYXRpb24gc2hvdWxkIGJlIGNvbGxlY3RlZC5cbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWRcbiAgICovXG4gIHJlYWRvbmx5IGNvbGxlY3RDb3ZlcmFnZUZyb20/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGRpcmVjdG9yeSB3aGVyZSBKZXN0IHNob3VsZCBvdXRwdXQgaXRzIGNvdmVyYWdlIGZpbGVzLlxuICAgKiBAZGVmYXVsdCBcImNvdmVyYWdlXCJcbiAgICovXG4gIHJlYWRvbmx5IGNvdmVyYWdlRGlyZWN0b3J5Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiByZWdleHAgcGF0dGVybiBzdHJpbmdzIHRoYXQgYXJlIG1hdGNoZWQgYWdhaW5zdCBhbGwgZmlsZSBwYXRocyBiZWZvcmUgZXhlY3V0aW5nIHRoZSB0ZXN0LlxuICAgKiBJZiB0aGUgZmlsZSBwYXRoIG1hdGNoZXMgYW55IG9mIHRoZSBwYXR0ZXJucywgY292ZXJhZ2UgaW5mb3JtYXRpb24gd2lsbCBiZSBza2lwcGVkXG4gICAqIEBkZWZhdWx0IFwiL25vZGVfbW9kdWxlcy9cIlxuICAgKi9cbiAgcmVhZG9ubHkgY292ZXJhZ2VQYXRoSWdub3JlUGF0dGVybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoaWNoIHByb3ZpZGVyIHNob3VsZCBiZSB1c2VkIHRvIGluc3RydW1lbnQgY29kZSBmb3IgY292ZXJhZ2UuXG4gICAqIEFsbG93ZWQgdmFsdWVzIGFyZSB2OCAoZGVmYXVsdCkgb3IgYmFiZWxcbiAgICogQGRlZmF1bHQgLSBcInY4XCJcbiAgICovXG4gIHJlYWRvbmx5IGNvdmVyYWdlUHJvdmlkZXI/OiBcImJhYmVsXCIgfCBcInY4XCI7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiByZXBvcnRlciBuYW1lcyB0aGF0IEplc3QgdXNlcyB3aGVuIHdyaXRpbmcgY292ZXJhZ2UgcmVwb3J0cy4gQW55IGlzdGFuYnVsIHJlcG9ydGVyIGNhbiBiZSB1c2VkXG4gICAqIEBkZWZhdWx0IC0gW1wianNvblwiLCBcImxjb3ZcIiwgXCJ0ZXh0XCIsIFwiY2xvdmVyXCIsIFwiY29iZXJ0dXJhXCJdXG4gICAqL1xuICByZWFkb25seSBjb3ZlcmFnZVJlcG9ydGVycz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHRoZSBnbG9iYWwgY292ZXJhZ2UgdGhyZXNob2xkcy4gVGhpcyB3aWxsIGJlIHVzZWQgdG8gY29uZmlndXJlIG1pbmltdW0gdGhyZXNob2xkIGVuZm9yY2VtZW50XG4gICAqIGZvciBjb3ZlcmFnZSByZXN1bHRzLiBUaHJlc2hvbGRzIGNhbiBiZSBzcGVjaWZpZWQgYXMgZ2xvYmFsLCBhcyBhIGdsb2IsIGFuZCBhcyBhIGRpcmVjdG9yeSBvciBmaWxlIHBhdGguXG4gICAqIElmIHRocmVzaG9sZHMgYXJlbid0IG1ldCwgamVzdCB3aWxsIGZhaWwuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBjb3ZlcmFnZVRocmVzaG9sZD86IENvdmVyYWdlVGhyZXNob2xkO1xuXG4gIC8qKlxuICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgdGhlIHVzZSBvZiBhIGN1c3RvbSBkZXBlbmRlbmN5IGV4dHJhY3Rvci5cbiAgICogSXQgbXVzdCBiZSBhIG5vZGUgbW9kdWxlIHRoYXQgZXhwb3J0cyBhbiBvYmplY3Qgd2l0aCBhbiBleHRyYWN0IGZ1bmN0aW9uXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBkZXBlbmRlbmN5RXh0cmFjdG9yPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBbGxvd3MgZm9yIGEgbGFiZWwgdG8gYmUgcHJpbnRlZCBhbG9uZ3NpZGUgYSB0ZXN0IHdoaWxlIGl0IGlzIHJ1bm5pbmcuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBkaXNwbGF5TmFtZT86IHN0cmluZyB8IGFueTtcblxuICAvKipcbiAgICogTWFrZSBjYWxsaW5nIGRlcHJlY2F0ZWQgQVBJcyB0aHJvdyBoZWxwZnVsIGVycm9yIG1lc3NhZ2VzLiBVc2VmdWwgZm9yIGVhc2luZyB0aGUgdXBncmFkZSBwcm9jZXNzLlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlcnJvck9uRGVwcmVjYXRlZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRlc3QgZmlsZXMgcnVuIGluc2lkZSBhIHZtLCB3aGljaCBzbG93cyBjYWxscyB0byBnbG9iYWwgY29udGV4dCBwcm9wZXJ0aWVzIChlLmcuIE1hdGgpLlxuICAgKiBXaXRoIHRoaXMgb3B0aW9uIHlvdSBjYW4gc3BlY2lmeSBleHRyYSBwcm9wZXJ0aWVzIHRvIGJlIGRlZmluZWQgaW5zaWRlIHRoZSB2bSBmb3IgZmFzdGVyIGxvb2t1cHMuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBleHRyYUdsb2JhbHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGVzdCBmaWxlcyBhcmUgbm9ybWFsbHkgaWdub3JlZCBmcm9tIGNvbGxlY3RpbmcgY29kZSBjb3ZlcmFnZS5cbiAgICogV2l0aCB0aGlzIG9wdGlvbiwgeW91IGNhbiBvdmVyd3JpdGUgdGhpcyBiZWhhdmlvciBhbmQgaW5jbHVkZSBvdGhlcndpc2UgaWdub3JlZCBmaWxlcyBpbiBjb2RlIGNvdmVyYWdlLlxuICAgKiBAZGVmYXVsdCAtIFsnJ11cbiAgICovXG4gIHJlYWRvbmx5IGZvcmNlQ292ZXJhZ2VNYXRjaD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBnbG9iYWwgdmFyaWFibGVzIHRoYXQgbmVlZCB0byBiZSBhdmFpbGFibGUgaW4gYWxsIHRlc3QgZW52aXJvbm1lbnRzLlxuICAgKiBAZGVmYXVsdCAtIHt9XG4gICAqL1xuICByZWFkb25seSBnbG9iYWxzPzogYW55O1xuXG4gIC8qKlxuICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgdGhlIHVzZSBvZiBhIGN1c3RvbSBnbG9iYWwgc2V0dXAgbW9kdWxlIHdoaWNoIGV4cG9ydHMgYW4gYXN5bmMgZnVuY3Rpb24gdGhhdCBpc1xuICAgKiB0cmlnZ2VyZWQgb25jZSBiZWZvcmUgYWxsIHRlc3Qgc3VpdGVzLiBUaGlzIGZ1bmN0aW9uIGdldHMgSmVzdCdzIGdsb2JhbENvbmZpZyBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBnbG9iYWxTZXR1cD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhpcyBvcHRpb24gYWxsb3dzIHRoZSB1c2Ugb2YgYSBjdXN0b20gZ2xvYmFsIHRlYXJkb3duIG1vZHVsZSB3aGljaCBleHBvcnRzIGFuIGFzeW5jIGZ1bmN0aW9uIHRoYXQgaXNcbiAgICogdHJpZ2dlcmVkIG9uY2UgYWZ0ZXIgYWxsIHRlc3Qgc3VpdGVzLiBUaGlzIGZ1bmN0aW9uIGdldHMgSmVzdCdzIGdsb2JhbENvbmZpZyBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBnbG9iYWxUZWFyZG93bj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhpcyB3aWxsIGJlIHVzZWQgdG8gY29uZmlndXJlIHRoZSBiZWhhdmlvciBvZiBqZXN0LWhhc3RlLW1hcCwgSmVzdCdzIGludGVybmFsIGZpbGUgY3Jhd2xlci9jYWNoZSBzeXN0ZW0uXG4gICAqIEBkZWZhdWx0IC0ge31cbiAgICovXG4gIHJlYWRvbmx5IGhhc3RlPzogSGFzdGVDb25maWc7XG5cbiAgLyoqXG4gICAqIEluc2VydCBKZXN0J3MgZ2xvYmFscyAoZXhwZWN0LCB0ZXN0LCBkZXNjcmliZSwgYmVmb3JlRWFjaCBldGMuKSBpbnRvIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQuXG4gICAqIElmIHlvdSBzZXQgdGhpcyB0byBmYWxzZSwgeW91IHNob3VsZCBpbXBvcnQgZnJvbSBAamVzdC9nbG9iYWxzXG4gICAqIEBkZWZhdWx0IC0gdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgaW5qZWN0R2xvYmFscz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEEgbnVtYmVyIGxpbWl0aW5nIHRoZSBudW1iZXIgb2YgdGVzdHMgdGhhdCBhcmUgYWxsb3dlZCB0byBydW4gYXQgdGhlIHNhbWUgdGltZSB3aGVuIHVzaW5nIHRlc3QuY29uY3VycmVudC5cbiAgICogQW55IHRlc3QgYWJvdmUgdGhpcyBsaW1pdCB3aWxsIGJlIHF1ZXVlZCBhbmQgZXhlY3V0ZWQgb25jZSBhIHNsb3QgaXMgcmVsZWFzZWQuXG4gICAqIEBkZWZhdWx0IC0gNVxuICAgKi9cbiAgcmVhZG9ubHkgbWF4Q29uY3VycmVuY3k/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgbWF4aW11bSBudW1iZXIgb2Ygd29ya2VycyB0aGUgd29ya2VyLXBvb2wgd2lsbCBzcGF3biBmb3IgcnVubmluZyB0ZXN0cy4gSW4gc2luZ2xlIHJ1biBtb2RlLFxuICAgKiB0aGlzIGRlZmF1bHRzIHRvIHRoZSBudW1iZXIgb2YgdGhlIGNvcmVzIGF2YWlsYWJsZSBvbiB5b3VyIG1hY2hpbmUgbWludXMgb25lIGZvciB0aGUgbWFpbiB0aHJlYWRcbiAgICogSW4gd2F0Y2ggbW9kZSwgdGhpcyBkZWZhdWx0cyB0byBoYWxmIG9mIHRoZSBhdmFpbGFibGUgY29yZXMgb24geW91ciBtYWNoaW5lLlxuICAgKiBGb3IgZW52aXJvbm1lbnRzIHdpdGggdmFyaWFibGUgQ1BVcyBhdmFpbGFibGUsIHlvdSBjYW4gdXNlIHBlcmNlbnRhZ2UgYmFzZWQgY29uZmlndXJhdGlvbjogXCJtYXhXb3JrZXJzXCI6IFwiNTAlXCJcbiAgICogQGRlZmF1bHQgLSB0aGUgbnVtYmVyIG9mIHRoZSBjb3JlcyBhdmFpbGFibGUgb24geW91ciBtYWNoaW5lIG1pbnVzIG9uZSBmb3IgdGhlIG1haW4gdGhyZWFkXG4gICAqL1xuICByZWFkb25seSBtYXhXb3JrZXJzPzogbnVtYmVyIHwgc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiBkaXJlY3RvcnkgbmFtZXMgdG8gYmUgc2VhcmNoZWQgcmVjdXJzaXZlbHkgdXAgZnJvbSB0aGUgcmVxdWlyaW5nIG1vZHVsZSdzIGxvY2F0aW9uLlxuICAgKiBTZXR0aW5nIHRoaXMgb3B0aW9uIHdpbGwgb3ZlcnJpZGUgdGhlIGRlZmF1bHQsIGlmIHlvdSB3aXNoIHRvIHN0aWxsIHNlYXJjaCBub2RlX21vZHVsZXMgZm9yIHBhY2thZ2VzXG4gICAqIGluY2x1ZGUgaXQgYWxvbmcgd2l0aCBhbnkgb3RoZXIgb3B0aW9uczogW1wibm9kZV9tb2R1bGVzXCIsIFwiYm93ZXJfY29tcG9uZW50c1wiXVxuICAgKiBAZGVmYXVsdCAtIFtcIm5vZGVfbW9kdWxlc1wiXVxuICAgKi9cbiAgcmVhZG9ubHkgbW9kdWxlRGlyZWN0b3JpZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQW4gYXJyYXkgb2YgZmlsZSBleHRlbnNpb25zIHlvdXIgbW9kdWxlcyB1c2UuIElmIHlvdSByZXF1aXJlIG1vZHVsZXMgd2l0aG91dCBzcGVjaWZ5aW5nIGEgZmlsZSBleHRlbnNpb24sXG4gICAqIHRoZXNlIGFyZSB0aGUgZXh0ZW5zaW9ucyBKZXN0IHdpbGwgbG9vayBmb3IsIGluIGxlZnQtdG8tcmlnaHQgb3JkZXIuXG4gICAqIEBkZWZhdWx0IC0gW1wianNcIiwgXCJqc29uXCIsIFwianN4XCIsIFwidHNcIiwgXCJ0c3hcIiwgXCJub2RlXCJdXG4gICAqL1xuICByZWFkb25seSBtb2R1bGVGaWxlRXh0ZW5zaW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBIG1hcCBmcm9tIHJlZ3VsYXIgZXhwcmVzc2lvbnMgdG8gbW9kdWxlIG5hbWVzIG9yIHRvIGFycmF5cyBvZiBtb2R1bGUgbmFtZXMgdGhhdCBhbGxvdyB0byBzdHViIG91dFxuICAgKiByZXNvdXJjZXMsIGxpa2UgaW1hZ2VzIG9yIHN0eWxlcyB3aXRoIGEgc2luZ2xlIG1vZHVsZS5cbiAgICogQGRlZmF1bHQgLSBudWxsXG4gICAqL1xuICByZWFkb25seSBtb2R1bGVOYW1lTWFwcGVyPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXSB9O1xuXG4gIC8qKlxuICAgKiBBbiBhcnJheSBvZiByZWdleHAgcGF0dGVybiBzdHJpbmdzIHRoYXQgYXJlIG1hdGNoZWQgYWdhaW5zdCBhbGwgbW9kdWxlIHBhdGhzIGJlZm9yZSB0aG9zZSBwYXRocyBhcmVcbiAgICogdG8gYmUgY29uc2lkZXJlZCAndmlzaWJsZScgdG8gdGhlIG1vZHVsZSBsb2FkZXIuIElmIGEgZ2l2ZW4gbW9kdWxlJ3MgcGF0aCBtYXRjaGVzIGFueSBvZiB0aGUgcGF0dGVybnMsXG4gICAqIGl0IHdpbGwgbm90IGJlIHJlcXVpcmUoKS1hYmxlIGluIHRoZSB0ZXN0IGVudmlyb25tZW50LlxuICAgKiBAZGVmYXVsdCAtIFtdXG4gICAqL1xuICByZWFkb25seSBtb2R1bGVQYXRoSWdub3JlUGF0dGVybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQW4gYWx0ZXJuYXRpdmUgQVBJIHRvIHNldHRpbmcgdGhlIE5PREVfUEFUSCBlbnYgdmFyaWFibGUsIG1vZHVsZVBhdGhzIGlzIGFuIGFycmF5IG9mIGFic29sdXRlIHBhdGhzXG4gICAqIHRvIGFkZGl0aW9uYWwgbG9jYXRpb25zIHRvIHNlYXJjaCB3aGVuIHJlc29sdmluZyBtb2R1bGVzLiBVc2UgdGhlIDxyb290RGlyPiBzdHJpbmcgdG9rZW4gdG8gaW5jbHVkZVxuICAgKiB0aGUgcGF0aCB0byB5b3VyIHByb2plY3QncyByb290IGRpcmVjdG9yeS4gRXhhbXBsZTogW1wiPHJvb3REaXI+L2FwcC9cIl0uXG4gICAqIEBkZWZhdWx0IC0gW11cbiAgICovXG4gIHJlYWRvbmx5IG1vZHVsZVBhdGhzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEFjdGl2YXRlcyBub3RpZmljYXRpb25zIGZvciB0ZXN0IHJlc3VsdHMuXG4gICAqIEBkZWZhdWx0IC0gZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmeT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyBub3RpZmljYXRpb24gbW9kZS4gUmVxdWlyZXMgbm90aWZ5OiB0cnVlXG4gICAqIEBkZWZhdWx0IC0gZmFpbHVyZS1jaGFuZ2VcbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmeU1vZGU/OlxuICAgIHwgXCJhbHdheXNcIlxuICAgIHwgXCJmYWlsdXJlXCJcbiAgICB8IFwic3VjY2Vzc1wiXG4gICAgfCBcImNoYW5nZVwiXG4gICAgfCBcInN1Y2Nlc3MtY2hhbmdlXCJcbiAgICB8IFwiZmFpbHVyZS1jaGFuZ2VcIjtcblxuICAvKipcbiAgICogQSBwcmVzZXQgdGhhdCBpcyB1c2VkIGFzIGEgYmFzZSBmb3IgSmVzdCdzIGNvbmZpZ3VyYXRpb24uIEEgcHJlc2V0IHNob3VsZCBwb2ludCB0byBhbiBucG0gbW9kdWxlXG4gICAqIHRoYXQgaGFzIGEgamVzdC1wcmVzZXQuanNvbiBvciBqZXN0LXByZXNldC5qcyBmaWxlIGF0IHRoZSByb290LlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcHJlc2V0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBwYXRoIHRvIHRoZSBwcmV0dGllciBub2RlIG1vZHVsZSB1c2VkIHRvIHVwZGF0ZSBpbmxpbmUgc25hcHNob3RzLlxuICAgKiBAZGVmYXVsdCAtIFwicHJldHRpZXJcIlxuICAgKi9cbiAgcmVhZG9ubHkgcHJldHRpZXJQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIHRoZSBwcm9qZWN0cyBjb25maWd1cmF0aW9uIGlzIHByb3ZpZGVkIHdpdGggYW4gYXJyYXkgb2YgcGF0aHMgb3IgZ2xvYiBwYXR0ZXJucywgSmVzdCB3aWxsXG4gICAqIHJ1biB0ZXN0cyBpbiBhbGwgb2YgdGhlIHNwZWNpZmllZCBwcm9qZWN0cyBhdCB0aGUgc2FtZSB0aW1lLiBUaGlzIGlzIGdyZWF0IGZvciBtb25vcmVwb3Mgb3JcbiAgICogd2hlbiB3b3JraW5nIG9uIG11bHRpcGxlIHByb2plY3RzIGF0IHRoZSBzYW1lIHRpbWUuXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBwcm9qZWN0cz86IEFycmF5PHN0cmluZyB8IHsgW2tleTogc3RyaW5nXTogYW55IH0+O1xuXG4gIC8qKlxuICAgKiBVc2UgdGhpcyBjb25maWd1cmF0aW9uIG9wdGlvbiB0byBhZGQgY3VzdG9tIHJlcG9ydGVycyB0byBKZXN0LiBBIGN1c3RvbSByZXBvcnRlciBpcyBhIGNsYXNzXG4gICAqIHRoYXQgaW1wbGVtZW50cyBvblJ1blN0YXJ0LCBvblRlc3RTdGFydCwgb25UZXN0UmVzdWx0LCBvblJ1bkNvbXBsZXRlIG1ldGhvZHMgdGhhdCB3aWxsIGJlXG4gICAqIGNhbGxlZCB3aGVuIGFueSBvZiB0aG9zZSBldmVudHMgb2NjdXJzLlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcmVwb3J0ZXJzPzogSmVzdFJlcG9ydGVyW107XG5cbiAgLyoqXG4gICAqIEF1dG9tYXRpY2FsbHkgcmVzZXQgbW9jayBzdGF0ZSBiZWZvcmUgZXZlcnkgdGVzdC4gRXF1aXZhbGVudCB0byBjYWxsaW5nIGplc3QucmVzZXRBbGxNb2NrcygpXG4gICAqIGJlZm9yZSBlYWNoIHRlc3QuIFRoaXMgd2lsbCBsZWFkIHRvIGFueSBtb2NrcyBoYXZpbmcgdGhlaXIgZmFrZSBpbXBsZW1lbnRhdGlvbnMgcmVtb3ZlZCBidXRcbiAgICogZG9lcyBub3QgcmVzdG9yZSB0aGVpciBpbml0aWFsIGltcGxlbWVudGF0aW9uLlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZXNldE1vY2tzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQnkgZGVmYXVsdCwgZWFjaCB0ZXN0IGZpbGUgZ2V0cyBpdHMgb3duIGluZGVwZW5kZW50IG1vZHVsZSByZWdpc3RyeS4gRW5hYmxpbmcgcmVzZXRNb2R1bGVzXG4gICAqIGdvZXMgYSBzdGVwIGZ1cnRoZXIgYW5kIHJlc2V0cyB0aGUgbW9kdWxlIHJlZ2lzdHJ5IGJlZm9yZSBydW5uaW5nIGVhY2ggaW5kaXZpZHVhbCB0ZXN0LlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZXNldE1vZHVsZXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgdGhlIHVzZSBvZiBhIGN1c3RvbSByZXNvbHZlci5cbiAgICogaHR0cHM6Ly9qZXN0anMuaW8vZG9jcy9lbi9jb25maWd1cmF0aW9uI3Jlc29sdmVyLXN0cmluZ1xuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb2x2ZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEF1dG9tYXRpY2FsbHkgcmVzdG9yZSBtb2NrIHN0YXRlIGJlZm9yZSBldmVyeSB0ZXN0LiBFcXVpdmFsZW50IHRvIGNhbGxpbmcgamVzdC5yZXN0b3JlQWxsTW9ja3MoKVxuICAgKiBiZWZvcmUgZWFjaCB0ZXN0LiBUaGlzIHdpbGwgbGVhZCB0byBhbnkgbW9ja3MgaGF2aW5nIHRoZWlyIGZha2UgaW1wbGVtZW50YXRpb25zIHJlbW92ZWQgYW5kXG4gICAqIHJlc3RvcmVzIHRoZWlyIGluaXRpYWwgaW1wbGVtZW50YXRpb24uXG4gICAqIEBkZWZhdWx0IC0gZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHJlc3RvcmVNb2Nrcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSByb290IGRpcmVjdG9yeSB0aGF0IEplc3Qgc2hvdWxkIHNjYW4gZm9yIHRlc3RzIGFuZCBtb2R1bGVzIHdpdGhpbi4gSWYgeW91IHB1dCB5b3VyIEplc3RcbiAgICogY29uZmlnIGluc2lkZSB5b3VyIHBhY2thZ2UuanNvbiBhbmQgd2FudCB0aGUgcm9vdCBkaXJlY3RvcnkgdG8gYmUgdGhlIHJvb3Qgb2YgeW91ciByZXBvLCB0aGVcbiAgICogdmFsdWUgZm9yIHRoaXMgY29uZmlnIHBhcmFtIHdpbGwgZGVmYXVsdCB0byB0aGUgZGlyZWN0b3J5IG9mIHRoZSBwYWNrYWdlLmpzb24uXG4gICAqIEBkZWZhdWx0IC0gZGlyZWN0b3J5IG9mIHRoZSBwYWNrYWdlLmpzb25cbiAgICovXG4gIHJlYWRvbmx5IHJvb3REaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBwYXRocyB0byBkaXJlY3RvcmllcyB0aGF0IEplc3Qgc2hvdWxkIHVzZSB0byBzZWFyY2ggZm9yIGZpbGVzIGluLlxuICAgKiBAZGVmYXVsdCAtIFtcIjxyb290RGlyPlwiXVxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhpcyBvcHRpb24gYWxsb3dzIHlvdSB0byB1c2UgYSBjdXN0b20gcnVubmVyIGluc3RlYWQgb2YgSmVzdCdzIGRlZmF1bHQgdGVzdCBydW5uZXIuXG4gICAqIEBkZWZhdWx0IC0gXCJqZXN0LXJ1bm5lclwiXG4gICAqL1xuICByZWFkb25seSBydW5uZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBwYXRocyB0byBtb2R1bGVzIHRoYXQgcnVuIHNvbWUgY29kZSB0byBjb25maWd1cmUgb3Igc2V0IHVwIHRoZSB0ZXN0aW5nIGVudmlyb25tZW50LlxuICAgKiBFYWNoIHNldHVwRmlsZSB3aWxsIGJlIHJ1biBvbmNlIHBlciB0ZXN0IGZpbGUuIFNpbmNlIGV2ZXJ5IHRlc3QgcnVucyBpbiBpdHMgb3duIGVudmlyb25tZW50LFxuICAgKiB0aGVzZSBzY3JpcHRzIHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIHRlc3RpbmcgZW52aXJvbm1lbnQgaW1tZWRpYXRlbHkgYmVmb3JlIGV4ZWN1dGluZyB0aGVcbiAgICogdGVzdCBjb2RlIGl0c2VsZi5cbiAgICogQGRlZmF1bHQgLSBbXVxuICAgKi9cbiAgcmVhZG9ubHkgc2V0dXBGaWxlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgcGF0aHMgdG8gbW9kdWxlcyB0aGF0IHJ1biBzb21lIGNvZGUgdG8gY29uZmlndXJlIG9yIHNldCB1cCB0aGUgdGVzdGluZyBmcmFtZXdvcmtcbiAgICogYmVmb3JlIGVhY2ggdGVzdCBmaWxlIGluIHRoZSBzdWl0ZSBpcyBleGVjdXRlZC4gU2luY2Ugc2V0dXBGaWxlcyBleGVjdXRlcyBiZWZvcmUgdGhlIHRlc3RcbiAgICogZnJhbWV3b3JrIGlzIGluc3RhbGxlZCBpbiB0aGUgZW52aXJvbm1lbnQsIHRoaXMgc2NyaXB0IGZpbGUgcHJlc2VudHMgeW91IHRoZSBvcHBvcnR1bml0eSBvZlxuICAgKiBydW5uaW5nIHNvbWUgY29kZSBpbW1lZGlhdGVseSBhZnRlciB0aGUgdGVzdCBmcmFtZXdvcmsgaGFzIGJlZW4gaW5zdGFsbGVkIGluIHRoZSBlbnZpcm9ubWVudC5cbiAgICogQGRlZmF1bHQgLSBbXVxuICAgKi9cbiAgcmVhZG9ubHkgc2V0dXBGaWxlc0FmdGVyRW52Pzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyBhZnRlciB3aGljaCBhIHRlc3QgaXMgY29uc2lkZXJlZCBhcyBzbG93IGFuZCByZXBvcnRlZCBhcyBzdWNoIGluIHRoZSByZXN1bHRzLlxuICAgKiBAZGVmYXVsdCAtIDVcbiAgICovXG4gIHJlYWRvbmx5IHNsb3dUZXN0VGhyZXNob2xkPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgcGF0aCB0byBhIG1vZHVsZSB0aGF0IGNhbiByZXNvbHZlIHRlc3Q8LT5zbmFwc2hvdCBwYXRoLiBUaGlzIGNvbmZpZyBvcHRpb24gbGV0cyB5b3UgY3VzdG9taXplXG4gICAqIHdoZXJlIEplc3Qgc3RvcmVzIHNuYXBzaG90IGZpbGVzIG9uIGRpc2suXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSBzbmFwc2hvdFJlc29sdmVyPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgcGF0aHMgdG8gc25hcHNob3Qgc2VyaWFsaXplciBtb2R1bGVzIEplc3Qgc2hvdWxkIHVzZSBmb3Igc25hcHNob3QgdGVzdGluZy5cbiAgICogQGRlZmF1bHQgPSBbXVxuICAgKi9cbiAgcmVhZG9ubHkgc25hcHNob3RTZXJpYWxpemVycz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgdGVzdCBlbnZpcm9ubWVudCB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgdGVzdGluZy4gVGhlIGRlZmF1bHQgZW52aXJvbm1lbnQgaW4gSmVzdCBpcyBhXG4gICAqIGJyb3dzZXItbGlrZSBlbnZpcm9ubWVudCB0aHJvdWdoIGpzZG9tLiBJZiB5b3UgYXJlIGJ1aWxkaW5nIGEgbm9kZSBzZXJ2aWNlLCB5b3UgY2FuIHVzZSB0aGUgbm9kZVxuICAgKiBvcHRpb24gdG8gdXNlIGEgbm9kZS1saWtlIGVudmlyb25tZW50IGluc3RlYWQuXG4gICAqIEBkZWZhdWx0IC0gXCJqc2RvbVwiXG4gICAqL1xuICByZWFkb25seSB0ZXN0RW52aXJvbm1lbnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRlc3QgZW52aXJvbm1lbnQgb3B0aW9ucyB0aGF0IHdpbGwgYmUgcGFzc2VkIHRvIHRoZSB0ZXN0RW52aXJvbm1lbnQuXG4gICAqIFRoZSByZWxldmFudCBvcHRpb25zIGRlcGVuZCBvbiB0aGUgZW52aXJvbm1lbnQuXG4gICAqIEBkZWZhdWx0IC0ge31cbiAgICovXG4gIHJlYWRvbmx5IHRlc3RFbnZpcm9ubWVudE9wdGlvbnM/OiBhbnk7XG5cbiAgLyoqXG4gICAqIFRoZSBleGl0IGNvZGUgSmVzdCByZXR1cm5zIG9uIHRlc3QgZmFpbHVyZS5cbiAgICogQGRlZmF1bHQgLSAxXG4gICAqL1xuICByZWFkb25seSB0ZXN0RmFpbHVyZUV4aXRDb2RlPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgZ2xvYiBwYXR0ZXJucyBKZXN0IHVzZXMgdG8gZGV0ZWN0IHRlc3QgZmlsZXMuIEJ5IGRlZmF1bHQgaXQgbG9va3MgZm9yIC5qcywgLmpzeCwgLnRzIGFuZCAudHN4XG4gICAqIGZpbGVzIGluc2lkZSBvZiBfX3Rlc3RzX18gZm9sZGVycywgYXMgd2VsbCBhcyBhbnkgZmlsZXMgd2l0aCBhIHN1ZmZpeCBvZiAudGVzdCBvciAuc3BlY1xuICAgKiAoZS5nLiBDb21wb25lbnQudGVzdC5qcyBvciBDb21wb25lbnQuc3BlYy5qcykuIEl0IHdpbGwgYWxzbyBmaW5kIGZpbGVzIGNhbGxlZCB0ZXN0LmpzIG9yIHNwZWMuanMuXG4gICAqIEBkZWZhdWx0IFsnKipcXC9fX3Rlc3RzX18vKipcXC8qLltqdF1zPyh4KScsICcqKlxcLyooKi4pQChzcGVjfHRlc3QpLlt0al1zPyh4KSddXG4gICAqL1xuICByZWFkb25seSB0ZXN0TWF0Y2g/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQW4gYXJyYXkgb2YgcmVnZXhwIHBhdHRlcm4gc3RyaW5ncyB0aGF0IGFyZSBtYXRjaGVkIGFnYWluc3QgYWxsIHRlc3QgcGF0aHMgYmVmb3JlIGV4ZWN1dGluZyB0aGUgdGVzdC5cbiAgICogSWYgdGhlIHRlc3QgcGF0aCBtYXRjaGVzIGFueSBvZiB0aGUgcGF0dGVybnMsIGl0IHdpbGwgYmUgc2tpcHBlZC5cbiAgICogQGRlZmF1bHQgLSBbXCIvbm9kZV9tb2R1bGVzL1wiXVxuICAgKi9cbiAgcmVhZG9ubHkgdGVzdFBhdGhJZ25vcmVQYXR0ZXJucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgcGF0dGVybiBvciBwYXR0ZXJucyBKZXN0IHVzZXMgdG8gZGV0ZWN0IHRlc3QgZmlsZXMuIEJ5IGRlZmF1bHQgaXQgbG9va3MgZm9yIC5qcywgLmpzeCwgLnRzIGFuZCAudHN4XG4gICAqIGZpbGVzIGluc2lkZSBvZiBfX3Rlc3RzX18gZm9sZGVycywgYXMgd2VsbCBhcyBhbnkgZmlsZXMgd2l0aCBhIHN1ZmZpeCBvZiAudGVzdCBvciAuc3BlY1xuICAgKiAoZS5nLiBDb21wb25lbnQudGVzdC5qcyBvciBDb21wb25lbnQuc3BlYy5qcykuIEl0IHdpbGwgYWxzbyBmaW5kIGZpbGVzIGNhbGxlZCB0ZXN0LmpzIG9yIHNwZWMuanMuXG4gICAqIEBkZWZhdWx0IC0gKC9fX3Rlc3RzX18vLip8KFxcXFwufC8pKHRlc3R8c3BlYykpXFxcXC5banRdc3g/JFxuICAgKi9cbiAgcmVhZG9ubHkgdGVzdFJlZ2V4Pzogc3RyaW5nIHwgc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoaXMgb3B0aW9uIGFsbG93cyB0aGUgdXNlIG9mIGEgY3VzdG9tIHJlc3VsdHMgcHJvY2Vzc29yLlxuICAgKiBAZGVmYXVsdCAtIHVuZGVmaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgdGVzdFJlc3VsdHNQcm9jZXNzb3I/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoaXMgb3B0aW9uIGFsbG93cyB0aGUgdXNlIG9mIGEgY3VzdG9tIHRlc3QgcnVubmVyLiBUaGUgZGVmYXVsdCBpcyBqYXNtaW5lMi4gQSBjdXN0b20gdGVzdCBydW5uZXJcbiAgICogY2FuIGJlIHByb3ZpZGVkIGJ5IHNwZWNpZnlpbmcgYSBwYXRoIHRvIGEgdGVzdCBydW5uZXIgaW1wbGVtZW50YXRpb24uXG4gICAqIEBkZWZhdWx0IC0gXCJqYXNtaW5lMlwiXG4gICAqL1xuICByZWFkb25seSB0ZXN0UnVubmVyPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgeW91IHRvIHVzZSBhIGN1c3RvbSBzZXF1ZW5jZXIgaW5zdGVhZCBvZiBKZXN0J3MgZGVmYXVsdC5cbiAgICogU29ydCBtYXkgb3B0aW9uYWxseSByZXR1cm4gYSBQcm9taXNlLlxuICAgKiBAZGVmYXVsdCAtIFwiQGplc3QvdGVzdC1zZXF1ZW5jZXJcIlxuICAgKi9cbiAgcmVhZG9ubHkgdGVzdFNlcXVlbmNlcj86IHN0cmluZztcblxuICAvKipcbiAgICogRGVmYXVsdCB0aW1lb3V0IG9mIGEgdGVzdCBpbiBtaWxsaXNlY29uZHMuXG4gICAqIEBkZWZhdWx0IC0gNTAwMFxuICAgKi9cbiAgcmVhZG9ubHkgdGVzdFRpbWVvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoaXMgb3B0aW9uIHNldHMgdGhlIFVSTCBmb3IgdGhlIGpzZG9tIGVudmlyb25tZW50LiBJdCBpcyByZWZsZWN0ZWQgaW4gcHJvcGVydGllcyBzdWNoIGFzIGxvY2F0aW9uLmhyZWYuXG4gICAqIEBkZWZhdWx0IC0gXCJodHRwOi8vbG9jYWxob3N0XCJcbiAgICovXG4gIHJlYWRvbmx5IHRlc3RVUkw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNldHRpbmcgdGhpcyB2YWx1ZSB0byBsZWdhY3kgb3IgZmFrZSBhbGxvd3MgdGhlIHVzZSBvZiBmYWtlIHRpbWVycyBmb3IgZnVuY3Rpb25zIHN1Y2ggYXMgc2V0VGltZW91dC5cbiAgICogRmFrZSB0aW1lcnMgYXJlIHVzZWZ1bCB3aGVuIGEgcGllY2Ugb2YgY29kZSBzZXRzIGEgbG9uZyB0aW1lb3V0IHRoYXQgd2UgZG9uJ3Qgd2FudCB0byB3YWl0IGZvciBpbiBhIHRlc3QuXG4gICAqIEBkZWZhdWx0IC0gXCJyZWFsXCJcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVycz86IHN0cmluZztcblxuICAvKipcbiAgICogQSBtYXAgZnJvbSByZWd1bGFyIGV4cHJlc3Npb25zIHRvIHBhdGhzIHRvIHRyYW5zZm9ybWVycy4gQSB0cmFuc2Zvcm1lciBpcyBhIG1vZHVsZSB0aGF0IHByb3ZpZGVzIGFcbiAgICogc3luY2hyb25vdXMgZnVuY3Rpb24gZm9yIHRyYW5zZm9ybWluZyBzb3VyY2UgZmlsZXMuXG4gICAqIEBkZWZhdWx0IC0ge1wiXFxcXC5banRdc3g/JFwiOiBcImJhYmVsLWplc3RcIn1cbiAgICovXG4gIHJlYWRvbmx5IHRyYW5zZm9ybT86IHsgW2tleTogc3RyaW5nXTogVHJhbnNmb3JtIH07XG5cbiAgLyoqXG4gICAqIEFuIGFycmF5IG9mIHJlZ2V4cCBwYXR0ZXJuIHN0cmluZ3MgdGhhdCBhcmUgbWF0Y2hlZCBhZ2FpbnN0IGFsbCBzb3VyY2UgZmlsZSBwYXRocyBiZWZvcmUgdHJhbnNmb3JtYXRpb24uXG4gICAqIElmIHRoZSB0ZXN0IHBhdGggbWF0Y2hlcyBhbnkgb2YgdGhlIHBhdHRlcm5zLCBpdCB3aWxsIG5vdCBiZSB0cmFuc2Zvcm1lZC5cbiAgICogQGRlZmF1bHQgLSBbXCIvbm9kZV9tb2R1bGVzL1wiLCBcIlxcXFwucG5wXFxcXC5bXlxcXFxcXC9dKyRcIl1cbiAgICovXG4gIHJlYWRvbmx5IHRyYW5zZm9ybUlnbm9yZVBhdHRlcm5zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEFuIGFycmF5IG9mIHJlZ2V4cCBwYXR0ZXJuIHN0cmluZ3MgdGhhdCBhcmUgbWF0Y2hlZCBhZ2FpbnN0IGFsbCBtb2R1bGVzIGJlZm9yZSB0aGUgbW9kdWxlIGxvYWRlciB3aWxsXG4gICAqIGF1dG9tYXRpY2FsbHkgcmV0dXJuIGEgbW9jayBmb3IgdGhlbS4gSWYgYSBtb2R1bGUncyBwYXRoIG1hdGNoZXMgYW55IG9mIHRoZSBwYXR0ZXJucyBpbiB0aGlzIGxpc3QsIGl0XG4gICAqIHdpbGwgbm90IGJlIGF1dG9tYXRpY2FsbHkgbW9ja2VkIGJ5IHRoZSBtb2R1bGUgbG9hZGVyLlxuICAgKiBAZGVmYXVsdCAtIFtdXG4gICAqL1xuICByZWFkb25seSB1bm1vY2tlZE1vZHVsZVBhdGhQYXR0ZXJucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBlYWNoIGluZGl2aWR1YWwgdGVzdCBzaG91bGQgYmUgcmVwb3J0ZWQgZHVyaW5nIHRoZSBydW4uIEFsbCBlcnJvcnMgd2lsbCBhbHNvXG4gICAqIHN0aWxsIGJlIHNob3duIG9uIHRoZSBib3R0b20gYWZ0ZXIgZXhlY3V0aW9uLiBOb3RlIHRoYXQgaWYgdGhlcmUgaXMgb25seSBvbmUgdGVzdCBmaWxlIGJlaW5nIHJ1blxuICAgKiBpdCB3aWxsIGRlZmF1bHQgdG8gdHJ1ZS5cbiAgICogQGRlZmF1bHQgLSBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgdmVyYm9zZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEFuIGFycmF5IG9mIFJlZ0V4cCBwYXR0ZXJucyB0aGF0IGFyZSBtYXRjaGVkIGFnYWluc3QgYWxsIHNvdXJjZSBmaWxlIHBhdGhzIGJlZm9yZSByZS1ydW5uaW5nIHRlc3RzXG4gICAqIGluIHdhdGNoIG1vZGUuIElmIHRoZSBmaWxlIHBhdGggbWF0Y2hlcyBhbnkgb2YgdGhlIHBhdHRlcm5zLCB3aGVuIGl0IGlzIHVwZGF0ZWQsIGl0IHdpbGwgbm90IHRyaWdnZXJcbiAgICogYSByZS1ydW4gb2YgdGVzdHMuXG4gICAqIEBkZWZhdWx0IC0gW11cbiAgICovXG4gIHJlYWRvbmx5IHdhdGNoUGF0aElnbm9yZVBhdHRlcm5zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqXG4gICAqIEBkZWZhdWx0IC1cbiAgICovXG4gIHJlYWRvbmx5IHdhdGNoUGx1Z2lucz86IFdhdGNoUGx1Z2luW107XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gdXNlIHdhdGNobWFuIGZvciBmaWxlIGNyYXdsaW5nLlxuICAgKiBAZGVmYXVsdCAtIHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHdhdGNobWFuPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRXNjYXBlIGhhdGNoIHRvIGFsbG93IGFueSB2YWx1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYWRkaXRpb25hbE9wdGlvbnM/OiB7IFtuYW1lOiBzdHJpbmddOiBhbnkgfTtcblxuICAvKipcbiAgICogRXNjYXBlIGhhdGNoIHRvIGFsbG93IGFueSB2YWx1ZSAoSlMvVFMgb25seSlcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBhZGRpdGlvbmFsT3B0aW9uc2AgaW5zdGVhZC5cbiAgICpcbiAgICogQGpzaWkgaWdub3JlXG4gICAqL1xuICByZWFkb25seSBbbmFtZTogc3RyaW5nXTogYW55O1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGRpc2NvdmVyVGVzdE1hdGNoUGF0dGVybnNGb3JEaXJzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEplc3REaXNjb3ZlclRlc3RNYXRjaFBhdHRlcm5zRm9yRGlyc09wdGlvbnMge1xuICAvKiogVGhlIGZpbGUgZXh0ZW5zaW9uIHBhdHRlcm4gdG8gdXNlLiBEZWZhdWx0cyB0byBcIltqdF1zPyh4KVwiLiAqL1xuICByZWFkb25seSBmaWxlRXh0ZW5zaW9uUGF0dGVybj86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIFRyYW5zZm9ybSB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5hbWU6IHN0cmluZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM/OiBhbnlcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBAanNpaSBpZ25vcmVcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIGlmICh0aGlzLm9wdGlvbnMgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIFt0aGlzLm5hbWUsIHRoaXMub3B0aW9uc107XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdhdGNoUGx1Z2luIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbmFtZTogc3RyaW5nLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9ucz86IGFueVxuICApIHt9XG5cbiAgLyoqXG4gICAqIEBqc2lpIGlnbm9yZVxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucyAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gW3RoaXMubmFtZSwgdGhpcy5vcHRpb25zXTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEplc3RPcHRpb25zIHtcbiAgLyoqXG4gICAqIENvbGxlY3QgY292ZXJhZ2UuIERlcHJlY2F0ZWRcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKiBAZGVwcmVjYXRlZCB1c2UgamVzdENvbmZpZy5jb2xsZWN0Q292ZXJhZ2VcbiAgICovXG4gIHJlYWRvbmx5IGNvdmVyYWdlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5jbHVkZSB0aGUgYHRleHRgIGNvdmVyYWdlIHJlcG9ydGVyLCB3aGljaCBtZWFucyB0aGF0IGNvdmVyYWdlIHN1bW1hcnkgaXMgcHJpbnRlZFxuICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBqZXN0IGV4ZWN1dGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY292ZXJhZ2VUZXh0PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRGVmaW5lcyBgdGVzdFBhdGhJZ25vcmVQYXR0ZXJuc2AgYW5kIGBjb3ZlcmFnZVBhdGhJZ25vcmVQYXR0ZXJuc2BcbiAgICogQGRlZmF1bHQgW1wiL25vZGVfbW9kdWxlcy9cIl1cbiAgICogQGRlcHJlY2F0ZWQgdXNlIGplc3RDb25maWcuY292ZXJhZ2VQYXRoSWdub3JlUGF0dGVybnMgb3IgamVzdENvbmZpZy50ZXN0UGF0aElnbm9yZVBhdHRlcm5zIHJlc3BlY3RpdmVseVxuICAgKi9cbiAgcmVhZG9ubHkgaWdub3JlUGF0dGVybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogUmVzdWx0IHByb2Nlc3Npbmcgd2l0aCBqZXN0LWp1bml0LlxuICAgKlxuICAgKiBPdXRwdXQgZGlyZWN0b3J5IGlzIGB0ZXN0LXJlcG9ydHMvYC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkganVuaXRSZXBvcnRpbmc/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQcmVzZXJ2ZSB0aGUgZGVmYXVsdCBKZXN0IHJlcG9ydGVyIHdoZW4gYWRkaXRpb25hbCByZXBvcnRlcnMgYXJlIGFkZGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBwcmVzZXJ2ZURlZmF1bHRSZXBvcnRlcnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIH