UNPKG

@angular/core

Version:

Angular - the core framework

555 lines 85.5 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ // The formatter and CI disagree on how this import statement should be formatted. Both try to keep // it on one line, too, which has gotten very hard to read & manage. So disable the formatter for // this statement only. /* clang-format off */ import { EnvironmentInjector, InjectFlags, Injector, NgZone, runInInjectionContext, ɵconvertToBitFlags as convertToBitFlags, ɵDeferBlockBehavior as DeferBlockBehavior, ɵEffectScheduler as EffectScheduler, ɵflushModuleScopingQueueAsMuchAsPossible as flushModuleScopingQueueAsMuchAsPossible, ɵgetAsyncClassMetadataFn as getAsyncClassMetadataFn, ɵgetUnknownElementStrictMode as getUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode as getUnknownPropertyStrictMode, ɵRender3ComponentFactory as ComponentFactory, ɵresetCompiledComponents as resetCompiledComponents, ɵsetAllowDuplicateNgModuleIdsForTest as setAllowDuplicateNgModuleIdsForTest, ɵsetUnknownElementStrictMode as setUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode as setUnknownPropertyStrictMode, ɵstringify as stringify, } from '@angular/core'; /* clang-format on */ import { ComponentFixture } from './component_fixture'; import { ComponentFixtureNoNgZone, TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT, TestComponentRenderer, THROW_ON_UNKNOWN_ELEMENTS_DEFAULT, THROW_ON_UNKNOWN_PROPERTIES_DEFAULT } from './test_bed_common'; import { TestBedCompiler } from './test_bed_compiler'; const DEFER_BLOCK_DEFAULT_BEHAVIOR = DeferBlockBehavior.Playthrough; let _nextRootElementId = 0; /** * Returns a singleton of the `TestBed` class. * * @publicApi */ export function getTestBed() { return TestBedImpl.INSTANCE; } /** * @description * Configures and initializes environment for unit testing and provides methods for * creating components and services in unit tests. * * TestBed is the primary api for writing unit tests for Angular applications and libraries. */ export class TestBedImpl { constructor() { /** * Defer block behavior option that specifies whether defer blocks will be triggered manually * or set to play through. */ this._instanceDeferBlockBehavior = DEFER_BLOCK_DEFAULT_BEHAVIOR; // Properties this.platform = null; this.ngModule = null; this._compiler = null; this._testModuleRef = null; this._activeFixtures = []; /** * Internal-only flag to indicate whether a module * scoping queue has been checked and flushed already. * @nodoc */ this.globalCompilationChecked = false; } static { this._INSTANCE = null; } static get INSTANCE() { return TestBedImpl._INSTANCE = TestBedImpl._INSTANCE || new TestBedImpl(); } /** * Initialize the environment for testing with a compiler factory, a PlatformRef, and an * angular module. These are common to every test in the suite. * * This may only be called once, to set up the common providers for the current test * suite on the current platform. If you absolutely need to change the providers, * first use `resetTestEnvironment`. * * Test modules and platforms for individual platforms are available from * '@angular/<platform_name>/testing'. * * @publicApi */ static initTestEnvironment(ngModule, platform, options) { const testBed = TestBedImpl.INSTANCE; testBed.initTestEnvironment(ngModule, platform, options); return testBed; } /** * Reset the providers for the test injector. * * @publicApi */ static resetTestEnvironment() { TestBedImpl.INSTANCE.resetTestEnvironment(); } static configureCompiler(config) { return TestBedImpl.INSTANCE.configureCompiler(config); } /** * Allows overriding default providers, directives, pipes, modules of the test injector, * which are defined in test_injector.js */ static configureTestingModule(moduleDef) { return TestBedImpl.INSTANCE.configureTestingModule(moduleDef); } /** * Compile components with a `templateUrl` for the test's NgModule. * It is necessary to call this function * as fetching urls is asynchronous. */ static compileComponents() { return TestBedImpl.INSTANCE.compileComponents(); } static overrideModule(ngModule, override) { return TestBedImpl.INSTANCE.overrideModule(ngModule, override); } static overrideComponent(component, override) { return TestBedImpl.INSTANCE.overrideComponent(component, override); } static overrideDirective(directive, override) { return TestBedImpl.INSTANCE.overrideDirective(directive, override); } static overridePipe(pipe, override) { return TestBedImpl.INSTANCE.overridePipe(pipe, override); } static overrideTemplate(component, template) { return TestBedImpl.INSTANCE.overrideTemplate(component, template); } /** * Overrides the template of the given component, compiling the template * in the context of the TestingModule. * * Note: This works for JIT and AOTed components as well. */ static overrideTemplateUsingTestingModule(component, template) { return TestBedImpl.INSTANCE.overrideTemplateUsingTestingModule(component, template); } static overrideProvider(token, provider) { return TestBedImpl.INSTANCE.overrideProvider(token, provider); } static inject(token, notFoundValue, flags) { return TestBedImpl.INSTANCE.inject(token, notFoundValue, convertToBitFlags(flags)); } /** @deprecated from v9.0.0 use TestBed.inject */ static get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { return TestBedImpl.INSTANCE.inject(token, notFoundValue, flags); } /** * Runs the given function in the `EnvironmentInjector` context of `TestBed`. * * @see {@link EnvironmentInjector#runInContext} */ static runInInjectionContext(fn) { return TestBedImpl.INSTANCE.runInInjectionContext(fn); } static createComponent(component) { return TestBedImpl.INSTANCE.createComponent(component); } static resetTestingModule() { return TestBedImpl.INSTANCE.resetTestingModule(); } static execute(tokens, fn, context) { return TestBedImpl.INSTANCE.execute(tokens, fn, context); } static get platform() { return TestBedImpl.INSTANCE.platform; } static get ngModule() { return TestBedImpl.INSTANCE.ngModule; } static flushEffects() { return TestBedImpl.INSTANCE.flushEffects(); } /** * Initialize the environment for testing with a compiler factory, a PlatformRef, and an * angular module. These are common to every test in the suite. * * This may only be called once, to set up the common providers for the current test * suite on the current platform. If you absolutely need to change the providers, * first use `resetTestEnvironment`. * * Test modules and platforms for individual platforms are available from * '@angular/<platform_name>/testing'. * * @publicApi */ initTestEnvironment(ngModule, platform, options) { if (this.platform || this.ngModule) { throw new Error('Cannot set base providers because it has already been called'); } TestBedImpl._environmentTeardownOptions = options?.teardown; TestBedImpl._environmentErrorOnUnknownElementsOption = options?.errorOnUnknownElements; TestBedImpl._environmentErrorOnUnknownPropertiesOption = options?.errorOnUnknownProperties; this.platform = platform; this.ngModule = ngModule; this._compiler = new TestBedCompiler(this.platform, this.ngModule); // TestBed does not have an API which can reliably detect the start of a test, and thus could be // used to track the state of the NgModule registry and reset it correctly. Instead, when we // know we're in a testing scenario, we disable the check for duplicate NgModule registration // completely. setAllowDuplicateNgModuleIdsForTest(true); } /** * Reset the providers for the test injector. * * @publicApi */ resetTestEnvironment() { this.resetTestingModule(); this._compiler = null; this.platform = null; this.ngModule = null; TestBedImpl._environmentTeardownOptions = undefined; setAllowDuplicateNgModuleIdsForTest(false); } resetTestingModule() { this.checkGlobalCompilationFinished(); resetCompiledComponents(); if (this._compiler !== null) { this.compiler.restoreOriginalState(); } this._compiler = new TestBedCompiler(this.platform, this.ngModule); // Restore the previous value of the "error on unknown elements" option setUnknownElementStrictMode(this._previousErrorOnUnknownElementsOption ?? THROW_ON_UNKNOWN_ELEMENTS_DEFAULT); // Restore the previous value of the "error on unknown properties" option setUnknownPropertyStrictMode(this._previousErrorOnUnknownPropertiesOption ?? THROW_ON_UNKNOWN_PROPERTIES_DEFAULT); // We have to chain a couple of try/finally blocks, because each step can // throw errors and we don't want it to interrupt the next step and we also // want an error to be thrown at the end. try { this.destroyActiveFixtures(); } finally { try { if (this.shouldTearDownTestingModule()) { this.tearDownTestingModule(); } } finally { this._testModuleRef = null; this._instanceTeardownOptions = undefined; this._instanceErrorOnUnknownElementsOption = undefined; this._instanceErrorOnUnknownPropertiesOption = undefined; this._instanceDeferBlockBehavior = DEFER_BLOCK_DEFAULT_BEHAVIOR; } } return this; } configureCompiler(config) { if (config.useJit != null) { throw new Error('JIT compiler is not configurable via TestBed APIs.'); } if (config.providers !== undefined) { this.compiler.setCompilerProviders(config.providers); } return this; } configureTestingModule(moduleDef) { this.assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module'); // Trigger module scoping queue flush before executing other TestBed operations in a test. // This is needed for the first test invocation to ensure that globally declared modules have // their components scoped properly. See the `checkGlobalCompilationFinished` function // description for additional info. this.checkGlobalCompilationFinished(); // Always re-assign the options, even if they're undefined. // This ensures that we don't carry them between tests. this._instanceTeardownOptions = moduleDef.teardown; this._instanceErrorOnUnknownElementsOption = moduleDef.errorOnUnknownElements; this._instanceErrorOnUnknownPropertiesOption = moduleDef.errorOnUnknownProperties; this._instanceDeferBlockBehavior = moduleDef.deferBlockBehavior ?? DEFER_BLOCK_DEFAULT_BEHAVIOR; // Store the current value of the strict mode option, // so we can restore it later this._previousErrorOnUnknownElementsOption = getUnknownElementStrictMode(); setUnknownElementStrictMode(this.shouldThrowErrorOnUnknownElements()); this._previousErrorOnUnknownPropertiesOption = getUnknownPropertyStrictMode(); setUnknownPropertyStrictMode(this.shouldThrowErrorOnUnknownProperties()); this.compiler.configureTestingModule(moduleDef); return this; } compileComponents() { return this.compiler.compileComponents(); } inject(token, notFoundValue, flags) { if (token === TestBed) { return this; } const UNDEFINED = {}; const result = this.testModuleRef.injector.get(token, UNDEFINED, convertToBitFlags(flags)); return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) : result; } /** @deprecated from v9.0.0 use TestBed.inject */ get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { return this.inject(token, notFoundValue, flags); } runInInjectionContext(fn) { return runInInjectionContext(this.inject(EnvironmentInjector), fn); } execute(tokens, fn, context) { const params = tokens.map(t => this.inject(t)); return fn.apply(context, params); } overrideModule(ngModule, override) { this.assertNotInstantiated('overrideModule', 'override module metadata'); this.compiler.overrideModule(ngModule, override); return this; } overrideComponent(component, override) { this.assertNotInstantiated('overrideComponent', 'override component metadata'); this.compiler.overrideComponent(component, override); return this; } overrideTemplateUsingTestingModule(component, template) { this.assertNotInstantiated('TestBed.overrideTemplateUsingTestingModule', 'Cannot override template when the test module has already been instantiated'); this.compiler.overrideTemplateUsingTestingModule(component, template); return this; } overrideDirective(directive, override) { this.assertNotInstantiated('overrideDirective', 'override directive metadata'); this.compiler.overrideDirective(directive, override); return this; } overridePipe(pipe, override) { this.assertNotInstantiated('overridePipe', 'override pipe metadata'); this.compiler.overridePipe(pipe, override); return this; } /** * Overwrites all providers for the given token with the given provider definition. */ overrideProvider(token, provider) { this.assertNotInstantiated('overrideProvider', 'override provider'); this.compiler.overrideProvider(token, provider); return this; } overrideTemplate(component, template) { return this.overrideComponent(component, { set: { template, templateUrl: null } }); } createComponent(type) { const testComponentRenderer = this.inject(TestComponentRenderer); const rootElId = `root${_nextRootElementId++}`; testComponentRenderer.insertRootElement(rootElId); if (getAsyncClassMetadataFn(type)) { throw new Error(`Component '${type.name}' has unresolved metadata. ` + `Please call \`await TestBed.compileComponents()\` before running this test.`); } const componentDef = type.ɵcmp; if (!componentDef) { throw new Error(`It looks like '${stringify(type)}' has not been compiled.`); } const componentFactory = new ComponentFactory(componentDef); const initComponent = () => { const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this.testModuleRef); return this.runInInjectionContext(() => new ComponentFixture(componentRef)); }; const noNgZone = this.inject(ComponentFixtureNoNgZone, false); const ngZone = noNgZone ? null : this.inject(NgZone, null); const fixture = ngZone ? ngZone.run(initComponent) : initComponent(); this._activeFixtures.push(fixture); return fixture; } /** * @internal strip this from published d.ts files due to * https://github.com/microsoft/TypeScript/issues/36216 */ get compiler() { if (this._compiler === null) { throw new Error(`Need to call TestBed.initTestEnvironment() first`); } return this._compiler; } /** * @internal strip this from published d.ts files due to * https://github.com/microsoft/TypeScript/issues/36216 */ get testModuleRef() { if (this._testModuleRef === null) { this._testModuleRef = this.compiler.finalize(); } return this._testModuleRef; } assertNotInstantiated(methodName, methodDescription) { if (this._testModuleRef !== null) { throw new Error(`Cannot ${methodDescription} when the test module has already been instantiated. ` + `Make sure you are not using \`inject\` before \`${methodName}\`.`); } } /** * Check whether the module scoping queue should be flushed, and flush it if needed. * * When the TestBed is reset, it clears the JIT module compilation queue, cancelling any * in-progress module compilation. This creates a potential hazard - the very first time the * TestBed is initialized (or if it's reset without being initialized), there may be pending * compilations of modules declared in global scope. These compilations should be finished. * * To ensure that globally declared modules have their components scoped properly, this function * is called whenever TestBed is initialized or reset. The _first_ time that this happens, prior * to any other operations, the scoping queue is flushed. */ checkGlobalCompilationFinished() { // Checking _testNgModuleRef is null should not be necessary, but is left in as an additional // guard that compilations queued in tests (after instantiation) are never flushed accidentally. if (!this.globalCompilationChecked && this._testModuleRef === null) { flushModuleScopingQueueAsMuchAsPossible(); } this.globalCompilationChecked = true; } destroyActiveFixtures() { let errorCount = 0; this._activeFixtures.forEach((fixture) => { try { fixture.destroy(); } catch (e) { errorCount++; console.error('Error during cleanup of component', { component: fixture.componentInstance, stacktrace: e, }); } }); this._activeFixtures = []; if (errorCount > 0 && this.shouldRethrowTeardownErrors()) { throw Error(`${errorCount} ${(errorCount === 1 ? 'component' : 'components')} ` + `threw errors during cleanup`); } } shouldRethrowTeardownErrors() { const instanceOptions = this._instanceTeardownOptions; const environmentOptions = TestBedImpl._environmentTeardownOptions; // If the new teardown behavior hasn't been configured, preserve the old behavior. if (!instanceOptions && !environmentOptions) { return TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT; } // Otherwise use the configured behavior or default to rethrowing. return instanceOptions?.rethrowErrors ?? environmentOptions?.rethrowErrors ?? this.shouldTearDownTestingModule(); } shouldThrowErrorOnUnknownElements() { // Check if a configuration has been provided to throw when an unknown element is found return this._instanceErrorOnUnknownElementsOption ?? TestBedImpl._environmentErrorOnUnknownElementsOption ?? THROW_ON_UNKNOWN_ELEMENTS_DEFAULT; } shouldThrowErrorOnUnknownProperties() { // Check if a configuration has been provided to throw when an unknown property is found return this._instanceErrorOnUnknownPropertiesOption ?? TestBedImpl._environmentErrorOnUnknownPropertiesOption ?? THROW_ON_UNKNOWN_PROPERTIES_DEFAULT; } shouldTearDownTestingModule() { return this._instanceTeardownOptions?.destroyAfterEach ?? TestBedImpl._environmentTeardownOptions?.destroyAfterEach ?? TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT; } getDeferBlockBehavior() { return this._instanceDeferBlockBehavior; } tearDownTestingModule() { // If the module ref has already been destroyed, we won't be able to get a test renderer. if (this._testModuleRef === null) { return; } // Resolve the renderer ahead of time, because we want to remove the root elements as the very // last step, but the injector will be destroyed as a part of the module ref destruction. const testRenderer = this.inject(TestComponentRenderer); try { this._testModuleRef.destroy(); } catch (e) { if (this.shouldRethrowTeardownErrors()) { throw e; } else { console.error('Error during cleanup of a testing module', { component: this._testModuleRef.instance, stacktrace: e, }); } } finally { testRenderer.removeAllRootElements?.(); } } /** * Execute any pending effects. * * @developerPreview */ flushEffects() { this.inject(EffectScheduler).flush(); } } /** * @description * Configures and initializes environment for unit testing and provides methods for * creating components and services in unit tests. * * `TestBed` is the primary api for writing unit tests for Angular applications and libraries. * * @publicApi */ export const TestBed = TestBedImpl; /** * Allows injecting dependencies in `beforeEach()` and `it()`. Note: this function * (imported from the `@angular/core/testing` package) can **only** be used to inject dependencies * in tests. To inject dependencies in your application code, use the [`inject`](api/core/inject) * function from the `@angular/core` package instead. * * Example: * * ``` * beforeEach(inject([Dependency, AClass], (dep, object) => { * // some code that uses `dep` and `object` * // ... * })); * * it('...', inject([AClass], (object) => { * object.doSomething(); * expect(...); * }) * ``` * * @publicApi */ export function inject(tokens, fn) { const testBed = TestBedImpl.INSTANCE; // Not using an arrow function to preserve context passed from call site return function () { return testBed.execute(tokens, fn, this); }; } /** * @publicApi */ export class InjectSetupWrapper { constructor(_moduleDef) { this._moduleDef = _moduleDef; } _addModule() { const moduleDef = this._moduleDef(); if (moduleDef) { TestBedImpl.configureTestingModule(moduleDef); } } inject(tokens, fn) { const self = this; // Not using an arrow function to preserve context passed from call site return function () { self._addModule(); return inject(tokens, fn).call(this); }; } } export function withModule(moduleDef, fn) { if (fn) { // Not using an arrow function to preserve context passed from call site return function () { const testBed = TestBedImpl.INSTANCE; if (moduleDef) { testBed.configureTestingModule(moduleDef); } return fn.apply(this); }; } return new InjectSetupWrapper(() => moduleDef); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9iZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb3JlL3Rlc3Rpbmcvc3JjL3Rlc3RfYmVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILG1HQUFtRztBQUNuRyxpR0FBaUc7QUFDakcsdUJBQXVCO0FBRXZCLHNCQUFzQjtBQUN0QixPQUFPLEVBR0wsbUJBQW1CLEVBQ25CLFdBQVcsRUFFWCxRQUFRLEVBRVIsTUFBTSxFQUlOLHFCQUFxQixFQUVyQixrQkFBa0IsSUFBSSxpQkFBaUIsRUFDdkMsbUJBQW1CLElBQUksa0JBQWtCLEVBQ3pDLGdCQUFnQixJQUFJLGVBQWUsRUFDbkMsd0NBQXdDLElBQUksdUNBQXVDLEVBQ25GLHdCQUF3QixJQUFJLHVCQUF1QixFQUNuRCw0QkFBNEIsSUFBSSwyQkFBMkIsRUFDM0QsNkJBQTZCLElBQUksNEJBQTRCLEVBQzdELHdCQUF3QixJQUFJLGdCQUFnQixFQUU1Qyx3QkFBd0IsSUFBSSx1QkFBdUIsRUFDbkQsb0NBQW9DLElBQUksbUNBQW1DLEVBQzNFLDRCQUE0QixJQUFJLDJCQUEyQixFQUMzRCw2QkFBNkIsSUFBSSw0QkFBNEIsRUFDN0QsVUFBVSxJQUFJLFNBQVMsR0FDeEIsTUFBTSxlQUFlLENBQUM7QUFFdkIscUJBQXFCO0FBSXJCLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBRXJELE9BQU8sRUFBNkIsd0JBQXdCLEVBQXlCLDBDQUEwQyxFQUFFLHFCQUFxQixFQUE4QyxpQ0FBaUMsRUFBRSxtQ0FBbUMsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ3JTLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQztBQUVwRCxNQUFNLDRCQUE0QixHQUFHLGtCQUFrQixDQUFDLFdBQVcsQ0FBQztBQXdHcEUsSUFBSSxrQkFBa0IsR0FBRyxDQUFDLENBQUM7QUFFM0I7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RUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QixDQUFDLENBQUM7SUFDSixDQUFDO0lBQ0QsT0FBTyxJQUFJLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuLy8gVGhlIGZvcm1hdHRlciBhbmQgQ0kgZGlzYWdyZWUgb24gaG93IHRoaXMgaW1wb3J0IHN0YXRlbWVudCBzaG91bGQgYmUgZm9ybWF0dGVkLiBCb3RoIHRyeSB0byBrZWVwXG4vLyBpdCBvbiBvbmUgbGluZSwgdG9vLCB3aGljaCBoYXMgZ290dGVuIHZlcnkgaGFyZCB0byByZWFkICYgbWFuYWdlLiBTbyBkaXNhYmxlIHRoZSBmb3JtYXR0ZXIgZm9yXG4vLyB0aGlzIHN0YXRlbWVudCBvbmx5LlxuXG4vKiBjbGFuZy1mb3JtYXQgb2ZmICovXG5pbXBvcnQge1xuICBDb21wb25lbnQsXG4gIERpcmVjdGl2ZSxcbiAgRW52aXJvbm1lbnRJbmplY3RvcixcbiAgSW5qZWN0RmxhZ3MsXG4gIEluamVjdE9wdGlvbnMsXG4gIEluamVjdG9yLFxuICBOZ01vZHVsZSxcbiAgTmdab25lLFxuICBQaXBlLFxuICBQbGF0Zm9ybVJlZixcbiAgUHJvdmlkZXJUb2tlbixcbiAgcnVuSW5JbmplY3Rpb25Db250ZXh0LFxuICBUeXBlLFxuICDJtWNvbnZlcnRUb0JpdEZsYWdzIGFzIGNvbnZlcnRUb0JpdEZsYWdzLFxuICDJtURlZmVyQmxvY2tCZWhhdmlvciBhcyBEZWZlckJsb2NrQmVoYXZpb3IsXG4gIMm1RWZmZWN0U2NoZWR1bGVyIGFzIEVmZmVjdFNjaGVkdWxlcixcbiAgybVmbHVzaE1vZHVsZVNjb3BpbmdRdWV1ZUFzTXVjaEFzUG9zc2libGUgYXMgZmx1c2hNb2R1bGVTY29waW5nUXVldWVBc011Y2hBc1Bvc3NpYmxlLFxuICDJtWdldEFzeW5jQ2xhc3NNZXRhZGF0YUZuIGFzIGdldEFzeW5jQ2xhc3NNZXRhZGF0YUZuLFxuICDJtWdldFVua25vd25FbGVtZW50U3RyaWN0TW9kZSBhcyBnZXRVbmtub3duRWxlbWVudFN0cmljdE1vZGUsXG4gIMm1Z2V0VW5rbm93blByb3BlcnR5U3RyaWN0TW9kZSBhcyBnZXRVbmtub3duUHJvcGVydHlTdHJpY3RNb2RlLFxuICDJtVJlbmRlcjNDb21wb25lbnRGYWN0b3J5IGFzIENvbXBvbmVudEZhY3RvcnksXG4gIMm1UmVuZGVyM05nTW9kdWxlUmVmIGFzIE5nTW9kdWxlUmVmLFxuICDJtXJlc2V0Q29tcGlsZWRDb21wb25lbnRzIGFzIHJlc2V0Q29tcGlsZWRDb21wb25lbnRzLFxuICDJtXNldEFsbG93RHVwbGljYXRlTmdNb2R1bGVJZHNGb3JUZXN0IGFzIHNldEFsbG93RHVwbGljYXRlTmdNb2R1bGVJZHNGb3JUZXN0LFxuICDJtXNldFVua25vd25FbGVtZW50U3RyaWN0TW9kZSBhcyBzZXRVbmtub3duRWxlbWVudFN0cmljdE1vZGUsXG4gIMm1c2V0VW5rbm93blByb3BlcnR5U3RyaWN0TW9kZSBhcyBzZXRVbmtub3duUHJvcGVydHlTdHJpY3RNb2RlLFxuICDJtXN0cmluZ2lmeSBhcyBzdHJpbmdpZnksXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKiBjbGFuZy1mb3JtYXQgb24gKi9cblxuXG5cbmltcG9ydCB7Q29tcG9uZW50Rml4dHVyZX0gZnJvbSAnLi9jb21wb25lbnRfZml4dHVyZSc7XG5pbXBvcnQge01ldGFkYXRhT3ZlcnJpZGV9IGZyb20gJy4vbWV0YWRhdGFfb3ZlcnJpZGUnO1xuaW1wb3J0IHtDb21wb25lbnRGaXh0dXJlQXV0b0RldGVjdCwgQ29tcG9uZW50Rml4dHVyZU5vTmdab25lLCBNb2R1bGVUZWFyZG93bk9wdGlvbnMsIFRFQVJET1dOX1RFU1RJTkdfTU9EVUxFX09OX0RFU1RST1lfREVGQVVMVCwgVGVzdENvbXBvbmVudFJlbmRlcmVyLCBUZXN0RW52aXJvbm1lbnRPcHRpb25zLCBUZXN0TW9kdWxlTWV0YWRhdGEsIFRIUk9XX09OX1VOS05PV05fRUxFTUVOVFNfREVGQVVMVCwgVEhST1dfT05fVU5LTk9XTl9QUk9QRVJUSUVTX0RFRkFVTFR9IGZyb20gJy4vdGVzdF9iZWRfY29tbW9uJztcbmltcG9ydCB7VGVzdEJlZENvbXBpbGVyfSBmcm9tICcuL3Rlc3RfYmVkX2NvbXBpbGVyJztcblxuY29uc3QgREVGRVJfQkxPQ0tfREVGQVVMVF9CRUhBVklPUiA9IERlZmVyQmxvY2tCZWhhdmlvci5QbGF5dGhyb3VnaDtcblxuLyoqXG4gKiBTdGF0aWMgbWV0aG9kcyBpbXBsZW1lbnRlZCBieSB0aGUgYFRlc3RCZWRgLlxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZXN0QmVkU3RhdGljIGV4dGVuZHMgVGVzdEJlZCB7XG4gIG5ldyguLi5hcmdzOiBhbnlbXSk6IFRlc3RCZWQ7XG59XG5cbi8qKlxuICogQHB1YmxpY0FwaVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlc3RCZWQge1xuICBnZXQgcGxhdGZvcm0oKTogUGxhdGZvcm1SZWY7XG5cbiAgZ2V0IG5nTW9kdWxlKCk6IFR5cGU8YW55PnxUeXBlPGFueT5bXTtcblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgZW52aXJvbm1lbnQgZm9yIHRlc3Rpbmcgd2l0aCBhIGNvbXBpbGVyIGZhY3RvcnksIGEgUGxhdGZvcm1SZWYsIGFuZCBhblxuICAgKiBhbmd1bGFyIG1vZHVsZS4gVGhlc2UgYXJlIGNvbW1vbiB0byBldmVyeSB0ZXN0IGluIHRoZSBzdWl0ZS5cbiAgICpcbiAgICogVGhpcyBtYXkgb25seSBiZSBjYWxsZWQgb25jZSwgdG8gc2V0IHVwIHRoZSBjb21tb24gcHJvdmlkZXJzIGZvciB0aGUgY3VycmVudCB0ZXN0XG4gICAqIHN1aXRlIG9uIHRoZSBjdXJyZW50IHBsYXRmb3JtLiBJZiB5b3UgYWJzb2x1dGVseSBuZWVkIHRvIGNoYW5nZSB0aGUgcHJvdmlkZXJzLFxuICAgKiBmaXJzdCB1c2UgYHJlc2V0VGVzdEVudmlyb25tZW50YC5cbiAgICpcbiAgICogVGVzdCBtb2R1bGVzIGFuZCBwbGF0Zm9ybXMgZm9yIGluZGl2aWR1YWwgcGxhdGZvcm1zIGFyZSBhdmFpbGFibGUgZnJvbVxuICAgKiAnQGFuZ3VsYXIvPHBsYXRmb3JtX25hbWU+L3Rlc3RpbmcnLlxuICAgKi9cbiAgaW5pdFRlc3RFbnZpcm9ubWVudChcbiAgICAgIG5nTW9kdWxlOiBUeXBlPGFueT58VHlwZTxhbnk+W10sIHBsYXRmb3JtOiBQbGF0Zm9ybVJlZixcbiAgICAgIG9wdGlvbnM/OiBUZXN0RW52aXJvbm1lbnRPcHRpb25zKTogdm9pZDtcblxuICAvKipcbiAgICogUmVzZXQgdGhlIHByb3ZpZGVycyBmb3IgdGhlIHRlc3QgaW5qZWN0b3IuXG4gICAqL1xuICByZXNldFRlc3RFbnZpcm9ubWVudCgpOiB2b2lkO1xuXG4gIHJlc2V0VGVzdGluZ01vZHVsZSgpOiBUZXN0QmVkO1xuXG4gIGNvbmZpZ3VyZUNvbXBpbGVyKGNvbmZpZzoge3Byb3ZpZGVycz86IGFueVtdLCB1c2VKaXQ/OiBib29sZWFufSk6IHZvaWQ7XG5cbiAgY29uZmlndXJlVGVzdGluZ01vZHVsZShtb2R1bGVEZWY6IFRlc3RNb2R1bGVNZXRhZGF0YSk6IFRlc3RCZWQ7XG5cbiAgY29tcGlsZUNvbXBvbmVudHMoKTogUHJvbWlzZTxhbnk+O1xuXG4gIGluamVjdDxUPih0b2tlbjogUHJvdmlkZXJUb2tlbjxUPiwgbm90Rm91bmRWYWx1ZTogdW5kZWZpbmVkLCBvcHRpb25zOiBJbmplY3RPcHRpb25zJntcbiAgICBvcHRpb25hbD86IGZhbHNlXG4gIH0pOiBUO1xuICBpbmplY3Q8VD4odG9rZW46IFByb3ZpZGVyVG9rZW48VD4sIG5vdEZvdW5kVmFsdWU6IG51bGx8dW5kZWZpbmVkLCBvcHRpb25zOiBJbmplY3RPcHRpb25zKTogVHxudWxsO1xuICBpbmplY3Q8VD4odG9rZW46IFByb3ZpZGVyVG9rZW48VD4sIG5vdEZvdW5kVmFsdWU/OiBULCBvcHRpb25zPzogSW5qZWN0T3B0aW9ucyk6IFQ7XG4gIC8qKiBAZGVwcmVjYXRlZCB1c2Ugb2JqZWN0LWJhc2VkIGZsYWdzIChgSW5qZWN0T3B0aW9uc2ApIGluc3RlYWQuICovXG4gIGluamVjdDxUPih0b2tlbjogUHJvdmlkZXJUb2tlbjxUPiwgbm90Rm91bmRWYWx1ZT86IFQsIGZsYWdzPzogSW5qZWN0RmxhZ3MpOiBUO1xuICAvKiogQGRlcHJlY2F0ZWQgdXNlIG9iamVjdC1iYXNlZCBmbGFncyAoYEluamVjdE9wdGlvbnNgKSBpbnN0ZWFkLiAqL1xuICBpbmplY3Q8VD4odG9rZW46IFByb3ZpZGVyVG9rZW48VD4sIG5vdEZvdW5kVmFsdWU6IG51bGwsIGZsYWdzPzogSW5qZWN0RmxhZ3MpOiBUfG51bGw7XG5cbiAgLyoqIEBkZXByZWNhdGVkIGZyb20gdjkuMC4wIHVzZSBUZXN0QmVkLmluamVjdCAqL1xuICBnZXQ8VD4odG9rZW46IFByb3ZpZGVyVG9rZW48VD4sIG5vdEZvdW5kVmFsdWU/OiBULCBmbGFncz86IEluamVjdEZsYWdzKTogYW55O1xuICAvKiogQGRlcHJlY2F0ZWQgZnJvbSB2OS4wLjAgdXNlIFRlc3RCZWQuaW5qZWN0ICovXG4gIGdldCh0b2tlbjogYW55LCBub3RGb3VuZFZhbHVlPzogYW55KTogYW55O1xuXG4gIC8qKlxuICAgKiBSdW5zIHRoZSBnaXZlbiBmdW5jdGlvbiBpbiB0aGUgYEVudmlyb25tZW50SW5qZWN0b3JgIGNvbnRleHQgb2YgYFRlc3RCZWRgLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBFbnZpcm9ubWVudEluamVjdG9yI3J1bkluQ29udGV4dH1cbiAgICovXG4gIHJ1bkluSW5qZWN0aW9uQ29udGV4dDxUPihmbjogKCkgPT4gVCk6IFQ7XG5cbiAgZXhlY3V0ZSh0b2tlbnM6IGFueVtdLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBhbnkpOiBhbnk7XG5cbiAgb3ZlcnJpZGVNb2R1bGUobmdNb2R1bGU6IFR5cGU8YW55Piwgb3ZlcnJpZGU6IE1ldGFkYXRhT3ZlcnJpZGU8TmdNb2R1bGU+KTogVGVzdEJlZDtcblxuICBvdmVycmlkZUNvbXBvbmVudChjb21wb25lbnQ6IFR5cGU8YW55Piwgb3ZlcnJpZGU6IE1ldGFkYXRhT3ZlcnJpZGU8Q29tcG9uZW50Pik6IFRlc3RCZWQ7XG5cbiAgb3ZlcnJpZGVEaXJlY3RpdmUoZGlyZWN0aXZlOiBUeXBlPGFueT4sIG92ZXJyaWRlOiBNZXRhZGF0YU92ZXJyaWRlPERpcmVjdGl2ZT4pOiBUZXN0QmVkO1xuXG4gIG92ZXJyaWRlUGlwZShwaXBlOiBUeXBlPGFueT4sIG92ZXJyaWRlOiBNZXRhZGF0YU92ZXJyaWRlPFBpcGU+KTogVGVzdEJlZDtcblxuICBvdmVycmlkZVRlbXBsYXRlKGNvbXBvbmVudDogVHlwZTxhbnk+LCB0ZW1wbGF0ZTogc3RyaW5nKTogVGVzdEJlZDtcblxuICAvKipcbiAgICogT3ZlcndyaXRlcyBhbGwgcHJvdmlkZXJzIGZvciB0aGUgZ2l2ZW4gdG9rZW4gd2l0aCB0aGUgZ2l2ZW4gcHJvdmlkZXIgZGVmaW5pdGlvbi5cbiAgICovXG4gIG92ZXJyaWRlUHJvdmlkZXIodG9rZW46IGFueSwgcHJvdmlkZXI6IHt1c2VGYWN0b3J5OiBGdW5jdGlvbiwgZGVwczogYW55W10sIG11bHRpPzogYm9vbGVhbn0pOlxuICAgICAgVGVzdEJlZDtcbiAgb3ZlcnJpZGVQcm92aWRlcih0b2tlbjogYW55LCBwcm92aWRlcjoge3VzZVZhbHVlOiBhbnksIG11bHRpPzogYm9vbGVhbn0pOiBUZXN0QmVkO1xuICBvdmVycmlkZVByb3ZpZGVyKFxuICAgICAgdG9rZW46IGFueSxcbiAgICAgIHByb3ZpZGVyOiB7dXNlRmFjdG9yeT86IEZ1bmN0aW9uLCB1c2VWYWx1ZT86IGFueSwgZGVwcz86IGFueVtdLCBtdWx0aT86IGJvb2xlYW59KTogVGVzdEJlZDtcblxuICBvdmVycmlkZVRlbXBsYXRlVXNpbmdUZXN0aW5nTW9kdWxlKGNvbXBvbmVudDogVHlwZTxhbnk+LCB0ZW1wbGF0ZTogc3RyaW5nKTogVGVzdEJlZDtcblxuICBjcmVhdGVDb21wb25lbnQ8VD4oY29tcG9uZW50OiBUeXBlPFQ+KTogQ29tcG9uZW50Rml4dHVyZTxUPjtcblxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFueSBwZW5kaW5nIGVmZmVjdHMuXG4gICAqXG4gICAqIEBkZXZlbG9wZXJQcmV2aWV3XG4gICAqL1xuICBmbHVzaEVmZmVjdHMoKTogdm9pZDtcbn1cblxubGV0IF9uZXh0Um9vdEVsZW1lbnRJZCA9IDA7XG5cbi8qKlxuICogUmV0dXJucyBhIHNpbmdsZXRvbiBvZiB0aGUgYFRlc3RCZWRgIGNsYXNzLlxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRlc3RCZWQoKTogVGVzdEJlZCB7XG4gIHJldHVybiBUZXN0QmVkSW1wbC5JTlNUQU5DRTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqIENvbmZpZ3VyZXMgYW5kIGluaXRpYWxpemVzIGVudmlyb25tZW50IGZvciB1bml0IHRlc3RpbmcgYW5kIHByb3ZpZGVzIG1ldGhvZHMgZm9yXG4gKiBjcmVhdGluZyBjb21wb25lbnRzIGFuZCBzZXJ2aWNlcyBpbiB1bml0IHRlc3RzLlxuICpcbiAqIFRlc3RCZWQgaXMgdGhlIHByaW1hcnkgYXBpIGZvciB3cml0aW5nIHVuaXQgdGVzdHMgZm9yIEFuZ3VsYXIgYXBwbGljYXRpb25zIGFuZCBsaWJyYXJpZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBUZXN0QmVkSW1wbCBpbXBsZW1lbnRzIFRlc3RCZWQg