ngx-speculoos 9.0.0 → 10.0.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/esm2022/lib/component-tester.mjs +147 -0
- package/esm2022/lib/route.mjs +351 -0
- package/{fesm2020 → fesm2022}/ngx-speculoos.mjs +21 -17
- package/{fesm2020 → fesm2022}/ngx-speculoos.mjs.map +1 -1
- package/package.json +9 -15
- package/esm2020/lib/component-tester.mjs +0 -147
- package/esm2020/lib/route.mjs +0 -351
- package/fesm2015/ngx-speculoos.mjs +0 -1290
- package/fesm2015/ngx-speculoos.mjs.map +0 -1
- /package/{esm2020 → esm2022}/jasmine-matchers.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/matchers.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/mock.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-button.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-element-querier.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-element.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-html-element.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-input.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-select.mjs +0 -0
- /package/{esm2020 → esm2022}/lib/test-textarea.mjs +0 -0
- /package/{esm2020 → esm2022}/ngx-speculoos.mjs +0 -0
- /package/{esm2020 → esm2022}/public_api.mjs +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
4
|
+
import { TestElementQuerier } from './test-element-querier';
|
|
5
|
+
/**
|
|
6
|
+
* The main entry point of the API. It wraps an Angular ComponentFixture<T>, and gives access to its
|
|
7
|
+
* most used properties and methods. It also allows getting elements wrapped in TestElement (and its subclasses)
|
|
8
|
+
* @param <C> the type of the component to test
|
|
9
|
+
*/
|
|
10
|
+
export class ComponentTester {
|
|
11
|
+
/**
|
|
12
|
+
* Creates a component fixture of the given type with the TestBed and wraps it into a ComponentTester
|
|
13
|
+
*/
|
|
14
|
+
static create(componentType) {
|
|
15
|
+
const fixture = TestBed.createComponent(componentType);
|
|
16
|
+
return new ComponentTester(fixture);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a ComponentFixture for the given component type using the TestBed, and creates a ComponentTester
|
|
20
|
+
* wrapping (and delegating) to this fixture. If a fixture is passed, then delegates to this fixture directly.
|
|
21
|
+
*
|
|
22
|
+
* Note that no `detectChanges()` call is made by this constructor. It's up to the subclass constructor,
|
|
23
|
+
* or to the user of the created ComponentTester, to call `detectChanges()` at least once to trigger change
|
|
24
|
+
* detection. This is necessary because some component templates can only be evaluated once inputs
|
|
25
|
+
* have been set on the component instance.
|
|
26
|
+
*
|
|
27
|
+
* @param arg the type of the component to wrap, or a component fixture to wrap
|
|
28
|
+
*/
|
|
29
|
+
constructor(arg) {
|
|
30
|
+
this.fixture = arg instanceof ComponentFixture ? arg : TestBed.createComponent(arg);
|
|
31
|
+
this.testElement = TestElementQuerier.wrap(this.debugElement, this);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The native DOM host element of the component
|
|
35
|
+
*/
|
|
36
|
+
get nativeElement() {
|
|
37
|
+
return this.fixture.nativeElement;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Gets the instance of the tested component from the wrapped fixture
|
|
41
|
+
*/
|
|
42
|
+
get componentInstance() {
|
|
43
|
+
return this.fixture.componentInstance;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Gets the debug element from the wrapped fixture
|
|
47
|
+
*/
|
|
48
|
+
get debugElement() {
|
|
49
|
+
return this.fixture.debugElement;
|
|
50
|
+
}
|
|
51
|
+
element(selector) {
|
|
52
|
+
return this.testElement.element(selector);
|
|
53
|
+
}
|
|
54
|
+
elements(selector) {
|
|
55
|
+
return this.testElement.elements(selector);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.
|
|
59
|
+
* @param selector a CSS or directive selector
|
|
60
|
+
* @returns the wrapped input, or null if no element was matched
|
|
61
|
+
*/
|
|
62
|
+
input(selector) {
|
|
63
|
+
return this.testElement.input(selector);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.
|
|
67
|
+
* @param selector a CSS or directive selector
|
|
68
|
+
* @returns the wrapped select, or null if no element was matched
|
|
69
|
+
*/
|
|
70
|
+
select(selector) {
|
|
71
|
+
return this.testElement.select(selector);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Gets the first textarea matched by the given selector
|
|
75
|
+
* @param selector a CSS or directive selector
|
|
76
|
+
* @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.
|
|
77
|
+
* @throws {Error} if the matched element isn't actually a textarea
|
|
78
|
+
*/
|
|
79
|
+
textarea(selector) {
|
|
80
|
+
return this.testElement.textarea(selector);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.
|
|
84
|
+
* @param selector a CSS or directive selector
|
|
85
|
+
* @returns the wrapped button, or null if no element was matched
|
|
86
|
+
*/
|
|
87
|
+
button(selector) {
|
|
88
|
+
return this.testElement.button(selector);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Gets the first directive matching the given component directive selector and returns its component instance
|
|
92
|
+
* @param selector the selector of a component directive
|
|
93
|
+
*/
|
|
94
|
+
component(selector) {
|
|
95
|
+
return this.testElement.component(selector);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the directives matching the given component directive selector and returns their component instance
|
|
99
|
+
* @param selector the selector of a component directive
|
|
100
|
+
*/
|
|
101
|
+
components(selector) {
|
|
102
|
+
return this.testElement.components(selector);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token
|
|
106
|
+
* @param selector a CSS or directive selector
|
|
107
|
+
* @param token the token to get from the matched element injector
|
|
108
|
+
*/
|
|
109
|
+
token(selector, token) {
|
|
110
|
+
return this.testElement.token(selector, token);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token
|
|
114
|
+
* @param selector a CSS or directive selector
|
|
115
|
+
* @param token the token to get from the matched element injector
|
|
116
|
+
*/
|
|
117
|
+
tokens(selector, token) {
|
|
118
|
+
return this.testElement.tokens(selector, token);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided
|
|
122
|
+
* type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
|
|
123
|
+
* custom elements or components.
|
|
124
|
+
* @param selector a CSS or directive selector
|
|
125
|
+
* @param customTestElementType the type of the TestElement subclass that will wrap the found element
|
|
126
|
+
*/
|
|
127
|
+
custom(selector, customTestElementType) {
|
|
128
|
+
return this.testElement.custom(selector, customTestElementType);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Gets the elements matching the given selector, and creates and returns custom TestElements of the provided
|
|
132
|
+
* type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
|
|
133
|
+
* custom elements or components.
|
|
134
|
+
* @param selector a CSS or directive selector
|
|
135
|
+
* @param customTestElementType the type of the TestElement subclass that will wrap the found elements
|
|
136
|
+
*/
|
|
137
|
+
customs(selector, customTestElementType) {
|
|
138
|
+
return this.testElement.customs(selector, customTestElementType);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Triggers a change detection using the wrapped fixture
|
|
142
|
+
*/
|
|
143
|
+
detectChanges(checkNoChanges) {
|
|
144
|
+
this.fixture.detectChanges(checkNoChanges);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXRlc3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zcGVjdWxvb3Mvc3JjL2xpYi9jb21wb25lbnQtdGVzdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHNEQUFzRDtBQUN0RCx1REFBdUQ7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQVcxQjs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFNLENBQUksYUFBc0I7UUFDckMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN2RCxPQUFPLElBQUksZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHO0lBQ0gsWUFBWSxHQUFrQztRQUM1QyxJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsWUFBWSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BGLElBQUksQ0FBQyxXQUFXLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUE2QixDQUFDO0lBQ2xHLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksYUFBYTtRQUNmLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7SUFDcEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxpQkFBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQThHRCxPQUFPLENBQUMsUUFBNEI7UUFDbEMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBOEdELFFBQVEsQ0FBQyxRQUE0QjtRQUNuQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLFFBQTRCO1FBQ2hDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsUUFBNEI7UUFDakMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxRQUFRLENBQUMsUUFBNEI7UUFDbkMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxRQUE0QjtRQUNqQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLENBQUksUUFBaUI7UUFDNUIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsVUFBVSxDQUFJLFFBQWlCO1FBQzdCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUksUUFBNEIsRUFBRSxLQUF1QjtRQUM1RCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBSSxRQUE0QixFQUFFLEtBQXVCO1FBQzdELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQXdCLFFBQTRCLEVBQUUscUJBQThCO1FBQ3hGLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLHFCQUFxQixDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE9BQU8sQ0FBd0IsUUFBNEIsRUFBRSxxQkFBOEI7UUFDekYsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUscUJBQXFCLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLENBQUMsY0FBd0I7UUFDcEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDN0MsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5pbXBvcnQgeyBDb21wb25lbnRGaXh0dXJlLCBUZXN0QmVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS90ZXN0aW5nJztcbmltcG9ydCB7IERlYnVnRWxlbWVudCwgUHJvdmlkZXJUb2tlbiwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVGVzdFRleHRBcmVhIH0gZnJvbSAnLi90ZXN0LXRleHRhcmVhJztcbmltcG9ydCB7IFRlc3RFbGVtZW50IH0gZnJvbSAnLi90ZXN0LWVsZW1lbnQnO1xuaW1wb3J0IHsgVGVzdElucHV0IH0gZnJvbSAnLi90ZXN0LWlucHV0JztcbmltcG9ydCB7IFRlc3RTZWxlY3QgfSBmcm9tICcuL3Rlc3Qtc2VsZWN0JztcbmltcG9ydCB7IFRlc3RCdXR0b24gfSBmcm9tICcuL3Rlc3QtYnV0dG9uJztcbmltcG9ydCB7IFRlc3RFbGVtZW50UXVlcmllciB9IGZyb20gJy4vdGVzdC1lbGVtZW50LXF1ZXJpZXInO1xuaW1wb3J0IHsgVGVzdEh0bWxFbGVtZW50IH0gZnJvbSAnLi90ZXN0LWh0bWwtZWxlbWVudCc7XG5cbi8qKlxuICogVGhlIG1haW4gZW50cnkgcG9pbnQgb2YgdGhlIEFQSS4gSXQgd3JhcHMgYW4gQW5ndWxhciBDb21wb25lbnRGaXh0dXJlPFQ+LCBhbmQgZ2l2ZXMgYWNjZXNzIHRvIGl0c1xuICogbW9zdCB1c2VkIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMuIEl0IGFsc28gYWxsb3dzIGdldHRpbmcgZWxlbWVudHMgd3JhcHBlZCBpbiBUZXN0RWxlbWVudCAoYW5kIGl0cyBzdWJjbGFzc2VzKVxuICogQHBhcmFtIDxDPiB0aGUgdHlwZSBvZiB0aGUgY29tcG9uZW50IHRvIHRlc3RcbiAqL1xuZXhwb3J0IGNsYXNzIENvbXBvbmVudFRlc3RlcjxDPiB7XG4gIC8qKlxuICAgKiBUaGUgdGVzdCBlbGVtZW50IG9mIHRoZSBjb21wb25lbnRcbiAgICovXG4gIHJlYWRvbmx5IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudDxIVE1MRWxlbWVudD47XG5cbiAgLyoqXG4gICAqIFRoZSBjb21wb25lbnQgZml4dHVyZSBvZiB0aGUgY29tcG9uZW50XG4gICAqL1xuICByZWFkb25seSBmaXh0dXJlOiBDb21wb25lbnRGaXh0dXJlPEM+O1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY29tcG9uZW50IGZpeHR1cmUgb2YgdGhlIGdpdmVuIHR5cGUgd2l0aCB0aGUgVGVzdEJlZCBhbmQgd3JhcHMgaXQgaW50byBhIENvbXBvbmVudFRlc3RlclxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxDPihjb21wb25lbnRUeXBlOiBUeXBlPEM+KTogQ29tcG9uZW50VGVzdGVyPEM+IHtcbiAgICBjb25zdCBmaXh0dXJlID0gVGVzdEJlZC5jcmVhdGVDb21wb25lbnQoY29tcG9uZW50VHlwZSk7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRUZXN0ZXIoZml4dHVyZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIENvbXBvbmVudEZpeHR1cmUgZm9yIHRoZSBnaXZlbiBjb21wb25lbnQgdHlwZSB1c2luZyB0aGUgVGVzdEJlZCwgYW5kIGNyZWF0ZXMgYSBDb21wb25lbnRUZXN0ZXJcbiAgICogd3JhcHBpbmcgKGFuZCBkZWxlZ2F0aW5nKSB0byB0aGlzIGZpeHR1cmUuIElmIGEgZml4dHVyZSBpcyBwYXNzZWQsIHRoZW4gZGVsZWdhdGVzIHRvIHRoaXMgZml4dHVyZSBkaXJlY3RseS5cbiAgICpcbiAgICogTm90ZSB0aGF0IG5vIGBkZXRlY3RDaGFuZ2VzKClgIGNhbGwgaXMgbWFkZSBieSB0aGlzIGNvbnN0cnVjdG9yLiBJdCdzIHVwIHRvIHRoZSBzdWJjbGFzcyBjb25zdHJ1Y3RvcixcbiAgICogb3IgdG8gdGhlIHVzZXIgb2YgdGhlIGNyZWF0ZWQgQ29tcG9uZW50VGVzdGVyLCB0byBjYWxsIGBkZXRlY3RDaGFuZ2VzKClgIGF0IGxlYXN0IG9uY2UgdG8gdHJpZ2dlciBjaGFuZ2VcbiAgICogZGV0ZWN0aW9uLiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHNvbWUgY29tcG9uZW50IHRlbXBsYXRlcyBjYW4gb25seSBiZSBldmFsdWF0ZWQgb25jZSBpbnB1dHNcbiAgICogaGF2ZSBiZWVuIHNldCBvbiB0aGUgY29tcG9uZW50IGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0gYXJnIHRoZSB0eXBlIG9mIHRoZSBjb21wb25lbnQgdG8gd3JhcCwgb3IgYSBjb21wb25lbnQgZml4dHVyZSB0byB3cmFwXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihhcmc6IFR5cGU8Qz4gfCBDb21wb25lbnRGaXh0dXJlPEM+KSB7XG4gICAgdGhpcy5maXh0dXJlID0gYXJnIGluc3RhbmNlb2YgQ29tcG9uZW50Rml4dHVyZSA/IGFyZyA6IFRlc3RCZWQuY3JlYXRlQ29tcG9uZW50KGFyZyk7XG4gICAgdGhpcy50ZXN0RWxlbWVudCA9IFRlc3RFbGVtZW50UXVlcmllci53cmFwKHRoaXMuZGVidWdFbGVtZW50LCB0aGlzKSBhcyBUZXN0RWxlbWVudDxIVE1MRWxlbWVudD47XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5hdGl2ZSBET00gaG9zdCBlbGVtZW50IG9mIHRoZSBjb21wb25lbnRcbiAgICovXG4gIGdldCBuYXRpdmVFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5maXh0dXJlLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW5zdGFuY2Ugb2YgdGhlIHRlc3RlZCBjb21wb25lbnQgZnJvbSB0aGUgd3JhcHBlZCBmaXh0dXJlXG4gICAqL1xuICBnZXQgY29tcG9uZW50SW5zdGFuY2UoKTogQyB7XG4gICAgcmV0dXJuIHRoaXMuZml4dHVyZS5jb21wb25lbnRJbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBkZWJ1ZyBlbGVtZW50IGZyb20gdGhlIHdyYXBwZWQgZml4dHVyZVxuICAgKi9cbiAgZ2V0IGRlYnVnRWxlbWVudCgpOiBEZWJ1Z0VsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmZpeHR1cmUuZGVidWdFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0SHRtbEVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+IHwgbnVsbCA9IHRlc3Rlci5lbGVtZW50KCdkaXYnKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxLIGV4dGVuZHMga2V5b2YgSFRNTEVsZW1lbnRUYWdOYW1lTWFwPihzZWxlY3RvcjogSyk6IFRlc3RIdG1sRWxlbWVudDxIVE1MRWxlbWVudFRhZ05hbWVNYXBbS10+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4gfCBudWxsID0gdGVzdGVyLmVsZW1lbnQoJ2xpbmUnKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxLIGV4dGVuZHMga2V5b2YgU1ZHRWxlbWVudFRhZ05hbWVNYXA+KHNlbGVjdG9yOiBLKTogVGVzdEVsZW1lbnQ8U1ZHRWxlbWVudFRhZ05hbWVNYXBbS10+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudCB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCgnLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgd3JhcHBlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc2VsZWN0b3IuXG4gICAqL1xuICBlbGVtZW50KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBUZXN0RWxlbWVudCB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0SW5wdXQgfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTElucHV0RWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTElucHV0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RJbnB1dCB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0VGV4dEFyZWEgfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTFRleHRBcmVhRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTFRleHRBcmVhRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RUZXh0QXJlYSB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0U2VsZWN0IHwgbnVsbCA9IHRlc3Rlci5lbGVtZW50Jmx0O0hUTUxTZWxlY3RFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgd3JhcHBlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc2VsZWN0b3IuXG4gICAqL1xuICBlbGVtZW50PFQgZXh0ZW5kcyBIVE1MU2VsZWN0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RTZWxlY3QgfCBudWxsO1xuICAvKipcbiAgICogR2V0cyB0aGUgZmlyc3QgZWxlbWVudCBtYXRjaGluZyB0aGUgZ2l2ZW4gc2VsZWN0b3IgYW5kIHdyYXBzIGl0IGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50IGlzIGFuIGlucHV0IGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGEgVGVzdElucHV0LlxuICAgKiA8cD5Vc2FnZTo8L3A+XG4gICAqIDxjb2RlPlxuICAgKiBjb25zdCB0ZXN0RWxlbWVudDogVGVzdEJ1dHRvbiB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCZsdDtIVE1MQnV0dG9uRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTEJ1dHRvbkVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBUZXN0QnV0dG9uIHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyBpdCBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudCBpcyBhbiBpbnB1dCBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnQ6IFRlc3RIdG1sRWxlbWVudCZsdDtIVE1MRGl2RWxlbWVudD4gfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIGVsZW1lbnQsIG9yIG51bGwgaWYgbm8gZWxlbWVudCBtYXRjaGVzIHRoZSBzZWxlY3Rvci5cbiAgICovXG4gIGVsZW1lbnQ8VCBleHRlbmRzIEhUTUxFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogVGVzdEh0bWxFbGVtZW50PFQ+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyBpdCBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudCBpcyBhbiBpbnB1dCBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnQ6IFRlc3RFbGVtZW50Jmx0O1NWR0xpbmVFbGVtZW50PiB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RFbGVtZW50PFQ+IHwgbnVsbDtcbiAgZWxlbWVudChzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogVGVzdEVsZW1lbnQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5lbGVtZW50KHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEh0bWxFbGVtZW50Jmx0O0hUTUxEaXZFbGVtZW50Pj4gPSB0ZXN0ZXIuZWxlbWVudHMoJ2RpdicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8SyBleHRlbmRzIGtleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcD4oc2VsZWN0b3I6IEspOiBBcnJheTxUZXN0SHRtbEVsZW1lbnQ8SFRNTEVsZW1lbnRUYWdOYW1lTWFwW0tdPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEVsZW1lbnQmbHQ7U1ZHTGluZUVsZW1lbnQ+PiA9IHRlc3Rlci5lbGVtZW50cygnbGluZScpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8SyBleHRlbmRzIGtleW9mIFNWR0VsZW1lbnRUYWdOYW1lTWFwPihzZWxlY3RvcjogSyk6IEFycmF5PFRlc3RFbGVtZW50PFNWR0VsZW1lbnRUYWdOYW1lTWFwW0tdPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0RWxlbWVudD4gPSB0ZXN0ZXIuZWxlbWVudHMoJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIGFycmF5IG9mIG1hdGNoZWQgZWxlbWVudHMsIGVtcHR5IGlmIG5vIGVsZW1lbnQgd2FzIG1hdGNoZWRcbiAgICovXG4gIGVsZW1lbnRzKHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0SW5wdXQ+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O0hUTUxJbnB1dEVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTElucHV0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RJbnB1dD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0VGV4dEFyZWE+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O0hUTUxUZXh0QXJlYUVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTFRleHRBcmVhRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RUZXh0QXJlYT47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEJ1dHRvbj4gPSB0ZXN0ZXIuZWxlbWVudHMmbHQ7SFRNTEJ1dHRvbkVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTEJ1dHRvbkVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0QnV0dG9uPjtcbiAgLyoqXG4gICAqIEdldHMgYWxsIHRoZSBlbGVtZW50cyBtYXRjaGluZyB0aGUgZ2l2ZW4gc2VsZWN0b3IgYW5kIHdyYXBzIHRoZW0gaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIGVsZW1lbnRzIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnRzIGFyZSBpbnB1dHMgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYW4gYXJyYXkgb2YgVGVzdElucHV0LlxuICAgKiA8cD5Vc2FnZTo8L3A+XG4gICAqIDxjb2RlPlxuICAgKiBjb25zdCB0ZXN0RWxlbWVudHM6IEFycmF5Jmx0O1Rlc3RTZWxlY3Q+ID0gdGVzdGVyLmVsZW1lbnRzPEhUTUxTZWxlY3RFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8VCBleHRlbmRzIEhUTUxTZWxlY3RFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogQXJyYXk8VGVzdFNlbGVjdD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0SHRtbEVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+PiA9IHRlc3Rlci5lbGVtZW50cyZsdDtIVE1MRGl2RWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIGFycmF5IG9mIG1hdGNoZWQgZWxlbWVudHMsIGVtcHR5IGlmIG5vIGVsZW1lbnQgd2FzIG1hdGNoZWRcbiAgICovXG4gIGVsZW1lbnRzPFQgZXh0ZW5kcyBIVE1MRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RIdG1sRWxlbWVudDxUPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0RWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O1NWR0xpbmVFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8VCBleHRlbmRzIEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudDxUPj47XG4gIGVsZW1lbnRzKHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudD4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmVsZW1lbnRzKHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBpbnB1dCBtYXRjaGVkIGJ5IHRoZSBnaXZlbiBzZWxlY3Rvci4gVGhyb3dzIGFuIEVycm9yIGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYW4gaW5wdXQuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgaW5wdXQsIG9yIG51bGwgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgaW5wdXQoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RJbnB1dCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmlucHV0KHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBzZWxlY3QgbWF0Y2hlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3IuIFRocm93cyBhbiBFcnJvciBpZiB0aGUgbWF0Y2hlZCBlbGVtZW50IGlzbid0IGFjdHVhbGx5IGEgc2VsZWN0LlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIHNlbGVjdCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBzZWxlY3Qoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RTZWxlY3QgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5zZWxlY3Qoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IHRleHRhcmVhIG1hdGNoZWQgYnkgdGhlIGdpdmVuIHNlbGVjdG9yXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgdGV4dGFyZWEsIG9yIG51bGwgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZC4gVGhyb3dzIGFuIEVycm9yIGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYSB0ZXh0YXJlYS5cbiAgICogQHRocm93cyB7RXJyb3J9IGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYSB0ZXh0YXJlYVxuICAgKi9cbiAgdGV4dGFyZWEoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RUZXh0QXJlYSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRleHRhcmVhKHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBidXR0b24gbWF0Y2hlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3IuIFRocm93cyBhbiBFcnJvciBpZiB0aGUgbWF0Y2hlZCBlbGVtZW50IGlzbid0IGFjdHVhbGx5IGEgYnV0dG9uLlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIGJ1dHRvbiwgb3IgbnVsbCBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBidXR0b24oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RCdXR0b24gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5idXR0b24oc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGRpcmVjdGl2ZSBtYXRjaGluZyB0aGUgZ2l2ZW4gY29tcG9uZW50IGRpcmVjdGl2ZSBzZWxlY3RvciBhbmQgcmV0dXJucyBpdHMgY29tcG9uZW50IGluc3RhbmNlXG4gICAqIEBwYXJhbSBzZWxlY3RvciB0aGUgc2VsZWN0b3Igb2YgYSBjb21wb25lbnQgZGlyZWN0aXZlXG4gICAqL1xuICBjb21wb25lbnQ8Uj4oc2VsZWN0b3I6IFR5cGU8Uj4pOiBSIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jb21wb25lbnQoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGRpcmVjdGl2ZXMgbWF0Y2hpbmcgdGhlIGdpdmVuIGNvbXBvbmVudCBkaXJlY3RpdmUgc2VsZWN0b3IgYW5kIHJldHVybnMgdGhlaXIgY29tcG9uZW50IGluc3RhbmNlXG4gICAqIEBwYXJhbSBzZWxlY3RvciB0aGUgc2VsZWN0b3Igb2YgYSBjb21wb25lbnQgZGlyZWN0aXZlXG4gICAqL1xuICBjb21wb25lbnRzPFI+KHNlbGVjdG9yOiBUeXBlPFI+KTogQXJyYXk8Uj4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmNvbXBvbmVudHMoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCB0aGVuIGdldHMgdGhlIGdpdmVuIHRva2VuIGZyb20gaXRzIGluamVjdG9yLCBvciBudWxsIGlmIHRoZXJlIGlzIG5vIHN1Y2ggdG9rZW5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcGFyYW0gdG9rZW4gdGhlIHRva2VuIHRvIGdldCBmcm9tIHRoZSBtYXRjaGVkIGVsZW1lbnQgaW5qZWN0b3JcbiAgICovXG4gIHRva2VuPFI+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIHRva2VuOiBQcm92aWRlclRva2VuPFI+KTogUiB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRva2VuKHNlbGVjdG9yLCB0b2tlbik7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCB0aGVuIGdldHMgdGhlaXIgZ2l2ZW4gdG9rZW4gZnJvbSB0aGVpciBpbmplY3Rvciwgb3IgbnVsbCBpZiB0aGVyZSBpcyBubyBzdWNoIHRva2VuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHBhcmFtIHRva2VuIHRoZSB0b2tlbiB0byBnZXQgZnJvbSB0aGUgbWF0Y2hlZCBlbGVtZW50IGluamVjdG9yXG4gICAqL1xuICB0b2tlbnM8Uj4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55PiwgdG9rZW46IFByb3ZpZGVyVG9rZW48Uj4pOiBBcnJheTxSIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRva2VucyhzZWxlY3RvciwgdG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCBhbmQgaWYgZm91bmQsIGNyZWF0ZXMgYW5kIHJldHVybnMgYSBjdXN0b20gVGVzdEVsZW1lbnQgb2YgdGhlIHByb3ZpZGVkXG4gICAqIHR5cGUuIFRoaXMgaXMgdXNlZnVsIHRvIGNyZWF0ZSBjdXN0b20gaGlnaGVyLWxldmVsIGFic3RyYWN0aW9ucyBzaW1pbGFyIHRvIFRlc3RJbnB1dCwgVGVzdFNlbGVjdCwgZXRjLiBmb3JcbiAgICogY3VzdG9tIGVsZW1lbnRzIG9yIGNvbXBvbmVudHMuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHBhcmFtIGN1c3RvbVRlc3RFbGVtZW50VHlwZSB0aGUgdHlwZSBvZiB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgdGhhdCB3aWxsIHdyYXAgdGhlIGZvdW5kIGVsZW1lbnRcbiAgICovXG4gIGN1c3RvbTxFIGV4dGVuZHMgVGVzdEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIGN1c3RvbVRlc3RFbGVtZW50VHlwZTogVHlwZTxFPik6IEUgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jdXN0b20oc2VsZWN0b3IsIGN1c3RvbVRlc3RFbGVtZW50VHlwZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCBhbmQgY3JlYXRlcyBhbmQgcmV0dXJucyBjdXN0b20gVGVzdEVsZW1lbnRzIG9mIHRoZSBwcm92aWRlZFxuICAgKiB0eXBlLiBUaGlzIGlzIHVzZWZ1bCB0byBjcmVhdGUgY3VzdG9tIGhpZ2hlci1sZXZlbCBhYnN0cmFjdGlvbnMgc2ltaWxhciB0byBUZXN0SW5wdXQsIFRlc3RTZWxlY3QsIGV0Yy4gZm9yXG4gICAqIGN1c3RvbSBlbGVtZW50cyBvciBjb21wb25lbnRzLlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEBwYXJhbSBjdXN0b21UZXN0RWxlbWVudFR5cGUgdGhlIHR5cGUgb2YgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIHRoYXQgd2lsbCB3cmFwIHRoZSBmb3VuZCBlbGVtZW50c1xuICAgKi9cbiAgY3VzdG9tczxFIGV4dGVuZHMgVGVzdEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIGN1c3RvbVRlc3RFbGVtZW50VHlwZTogVHlwZTxFPik6IEFycmF5PEU+IHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jdXN0b21zKHNlbGVjdG9yLCBjdXN0b21UZXN0RWxlbWVudFR5cGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgY2hhbmdlIGRldGVjdGlvbiB1c2luZyB0aGUgd3JhcHBlZCBmaXh0dXJlXG4gICAqL1xuICBkZXRlY3RDaGFuZ2VzKGNoZWNrTm9DaGFuZ2VzPzogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuZml4dHVyZS5kZXRlY3RDaGFuZ2VzKGNoZWNrTm9DaGFuZ2VzKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { ActivatedRoute, ActivatedRouteSnapshot, convertToParamMap } from '@angular/router';
|
|
2
|
+
import { BehaviorSubject, map } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a fake partial ActivatedRoute for tests.
|
|
5
|
+
*
|
|
6
|
+
* If you pass params, then the created route's paramMap will contain the same values.
|
|
7
|
+
* The same goes for queryParams and queryParamMap.
|
|
8
|
+
*
|
|
9
|
+
* If you pass a parent route and a snapshot, and the passed snapshot doesn't have a parent, then the snapshot's
|
|
10
|
+
* parent will be set to the parent route snapshot. This allows the code under test to use
|
|
11
|
+
* `route.parent.snapshot` or `route.snapshot.parent`.
|
|
12
|
+
*
|
|
13
|
+
* If you pass a snapshot with a parent, but don't pass a parent or pass a parent without snapshot, then the route's
|
|
14
|
+
* parent snapshot will be set to the given snapshot's parent. This allows the code under test to use
|
|
15
|
+
* `route.parent.snapshot` or `route.snapshot.parent`.
|
|
16
|
+
*
|
|
17
|
+
* @returns a partially populated, fake ActivatedRoute, depending on what you passed in
|
|
18
|
+
* @deprecated favor stubRoute, which creates an easier to use and more logical stub
|
|
19
|
+
*/
|
|
20
|
+
export function fakeRoute(options) {
|
|
21
|
+
const result = {
|
|
22
|
+
url: options.url,
|
|
23
|
+
params: options.params,
|
|
24
|
+
paramMap: options.params && options.params.pipe(map(params => convertToParamMap(params))),
|
|
25
|
+
queryParams: options.queryParams,
|
|
26
|
+
queryParamMap: options.queryParams && options.queryParams.pipe(map(params => convertToParamMap(params))),
|
|
27
|
+
fragment: options.fragment,
|
|
28
|
+
data: options.data,
|
|
29
|
+
outlet: options.outlet,
|
|
30
|
+
component: options.component,
|
|
31
|
+
snapshot: options.snapshot,
|
|
32
|
+
routeConfig: options.routeConfig,
|
|
33
|
+
root: options.root,
|
|
34
|
+
parent: options.parent,
|
|
35
|
+
firstChild: options.firstChild,
|
|
36
|
+
children: options.children,
|
|
37
|
+
pathFromRoot: options.pathFromRoot
|
|
38
|
+
};
|
|
39
|
+
for (let route = result; route; route = route.parent) {
|
|
40
|
+
if (route.parent && route.parent.snapshot && !route.snapshot) {
|
|
41
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
42
|
+
route.snapshot = fakeSnapshot({});
|
|
43
|
+
}
|
|
44
|
+
if (route.parent && route.parent.snapshot && !route.snapshot.parent) {
|
|
45
|
+
route.snapshot.parent = route.parent.snapshot;
|
|
46
|
+
}
|
|
47
|
+
if (route.snapshot && route.snapshot.parent && !route.parent) {
|
|
48
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
49
|
+
route.parent = fakeRoute({});
|
|
50
|
+
}
|
|
51
|
+
if (route.snapshot && route.snapshot.parent && route.parent && !route.parent.snapshot) {
|
|
52
|
+
route.parent.snapshot = route.snapshot.parent;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Creates a fake partial ActivatedRouteSnapshot for tests.
|
|
59
|
+
*
|
|
60
|
+
* If you pass params, then the created snapshot's paramMap will contain the same values.
|
|
61
|
+
* The same goes for queryParams and queryParamMap.
|
|
62
|
+
*
|
|
63
|
+
* @returns a partially populated, fake ActivatedRoute, depending on what you passed in
|
|
64
|
+
* @deprecated favor stubRoute, which creates an easier to use and more logical stub for both the route and its snapshot
|
|
65
|
+
*/
|
|
66
|
+
export function fakeSnapshot(options) {
|
|
67
|
+
return {
|
|
68
|
+
url: options.url,
|
|
69
|
+
params: options.params,
|
|
70
|
+
paramMap: options.params && convertToParamMap(options.params),
|
|
71
|
+
queryParams: options.queryParams,
|
|
72
|
+
queryParamMap: options.queryParams && convertToParamMap(options.queryParams),
|
|
73
|
+
fragment: options.fragment,
|
|
74
|
+
data: options.data,
|
|
75
|
+
outlet: options.outlet,
|
|
76
|
+
component: options.component,
|
|
77
|
+
routeConfig: options.routeConfig,
|
|
78
|
+
root: options.root,
|
|
79
|
+
parent: options.parent,
|
|
80
|
+
firstChild: options.firstChild,
|
|
81
|
+
children: options.children,
|
|
82
|
+
pathFromRoot: options.pathFromRoot
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
class ActivatedRouteSnapshotStub extends ActivatedRouteSnapshot {
|
|
86
|
+
get parent() {
|
|
87
|
+
return this._parent;
|
|
88
|
+
}
|
|
89
|
+
set parent(value) {
|
|
90
|
+
this._parent = value;
|
|
91
|
+
}
|
|
92
|
+
get root() {
|
|
93
|
+
return this._root;
|
|
94
|
+
}
|
|
95
|
+
set root(value) {
|
|
96
|
+
this._root = value;
|
|
97
|
+
}
|
|
98
|
+
get firstChild() {
|
|
99
|
+
return this._firstChild;
|
|
100
|
+
}
|
|
101
|
+
set firstChild(value) {
|
|
102
|
+
this._firstChild = value;
|
|
103
|
+
}
|
|
104
|
+
get children() {
|
|
105
|
+
return this._children;
|
|
106
|
+
}
|
|
107
|
+
set children(value) {
|
|
108
|
+
this._children = value;
|
|
109
|
+
}
|
|
110
|
+
get pathFromRoot() {
|
|
111
|
+
return this._pathFromRoot;
|
|
112
|
+
}
|
|
113
|
+
set pathFromRoot(value) {
|
|
114
|
+
this._pathFromRoot = value;
|
|
115
|
+
}
|
|
116
|
+
get title() {
|
|
117
|
+
return this._title;
|
|
118
|
+
}
|
|
119
|
+
set title(value) {
|
|
120
|
+
this._title = value;
|
|
121
|
+
}
|
|
122
|
+
get paramMap() {
|
|
123
|
+
return convertToParamMap(this.params);
|
|
124
|
+
}
|
|
125
|
+
get queryParamMap() {
|
|
126
|
+
return convertToParamMap(this.queryParams);
|
|
127
|
+
}
|
|
128
|
+
constructor() {
|
|
129
|
+
super();
|
|
130
|
+
this._parent = null;
|
|
131
|
+
this._firstChild = null;
|
|
132
|
+
this._children = [];
|
|
133
|
+
this._pathFromRoot = [];
|
|
134
|
+
this._root = this;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A stub for ActivatedRoute. It behaves almost the same way as the actual ActivatedRoute, exposing a snapshot
|
|
139
|
+
* and observables for the params, query params etc., which are kept in sync.
|
|
140
|
+
*
|
|
141
|
+
* In addition, this stub allows simulating a navigation by changing the params, the query params, the fragment, etc.
|
|
142
|
+
* When that happens, the snapshot is modified, then the relevant observables emit the new values.
|
|
143
|
+
*
|
|
144
|
+
* There are some things that don't really work the same way as the real ActivatedRoute though:
|
|
145
|
+
* - the handling of the firstChild and of the children is entirely under the tester's responsibility. Setting the parent
|
|
146
|
+
* of a route stub does not add this route to the children of its parent, for example.
|
|
147
|
+
* - when changing the params, query params, fragment, etc., their associated observable emits unconditionally, instead of
|
|
148
|
+
* first checking if the value is actually different from before. It's thus the responsibility of the tester to not
|
|
149
|
+
* change the values if they're the same as before.
|
|
150
|
+
* - the params, paramMap, queryParams and queryParamMap objects of the route snapshot change when params or query params are set
|
|
151
|
+
* on the stub route. So if the code keeps a reference to params or paramMaps, it won't see the changes.
|
|
152
|
+
*/
|
|
153
|
+
export class ActivatedRouteStub extends ActivatedRoute {
|
|
154
|
+
/**
|
|
155
|
+
* Constructs a new instance, based on the given options.
|
|
156
|
+
* If an option is not provided (or if no option is provided at all), then the route has a default value for this option
|
|
157
|
+
* (empty parameters for example, null fragment, etc.)
|
|
158
|
+
* If no parent is passed, then this route has no parent and is thus set as the root. Otherwise, the root and the path
|
|
159
|
+
* from root are created based on the root and path from root of the given parent route.
|
|
160
|
+
*/
|
|
161
|
+
constructor(options) {
|
|
162
|
+
super();
|
|
163
|
+
const snapshot = new ActivatedRouteSnapshotStub();
|
|
164
|
+
this.snapshot = snapshot;
|
|
165
|
+
this._firstChild = options?.firstChild ?? null;
|
|
166
|
+
this._children = options?.children ?? [];
|
|
167
|
+
this._parent = options?.parent ?? null;
|
|
168
|
+
this._root = this.parent?.root ?? this;
|
|
169
|
+
this._pathFromRoot = this.parent ? [...this.parent.pathFromRoot, this] : [this];
|
|
170
|
+
snapshot.params = options?.params ?? {};
|
|
171
|
+
snapshot.queryParams = options?.queryParams ?? {};
|
|
172
|
+
snapshot.data = options?.data ?? {};
|
|
173
|
+
snapshot.title = options?.title;
|
|
174
|
+
snapshot.fragment = options?.fragment ?? null;
|
|
175
|
+
snapshot.url = options?.url ?? [];
|
|
176
|
+
// @ts-expect-error the routeConfig is readonly, but we need to overwrite it here
|
|
177
|
+
snapshot.routeConfig = options?.routeConfig ?? null;
|
|
178
|
+
snapshot.firstChild = this.firstChild?.snapshot ?? null;
|
|
179
|
+
snapshot.children = this.children?.map(route => route.snapshot) ?? [];
|
|
180
|
+
snapshot.parent = this.parent?.snapshot ?? null;
|
|
181
|
+
snapshot.root = this.root.snapshot;
|
|
182
|
+
snapshot.pathFromRoot = this.pathFromRoot.map(route => route.snapshot);
|
|
183
|
+
this.paramsSubject = new BehaviorSubject(this.snapshot.params);
|
|
184
|
+
this.queryParamsSubject = new BehaviorSubject(this.snapshot.queryParams);
|
|
185
|
+
this.dataSubject = new BehaviorSubject(this.snapshot.data);
|
|
186
|
+
this.titleSubject = new BehaviorSubject(this.snapshot.title);
|
|
187
|
+
this.fragmentSubject = new BehaviorSubject(this.snapshot.fragment);
|
|
188
|
+
this.urlSubject = new BehaviorSubject(this.snapshot.url);
|
|
189
|
+
this.params = this.paramsSubject.asObservable();
|
|
190
|
+
this.queryParams = this.queryParamsSubject.asObservable();
|
|
191
|
+
this.data = this.dataSubject.asObservable();
|
|
192
|
+
this.fragment = this.fragmentSubject.asObservable();
|
|
193
|
+
this.url = this.urlSubject.asObservable();
|
|
194
|
+
// @ts-expect-error the title is readonly, but we need to be able to initialize it here
|
|
195
|
+
this.title = this.titleSubject.asObservable();
|
|
196
|
+
}
|
|
197
|
+
get root() {
|
|
198
|
+
return this._root;
|
|
199
|
+
}
|
|
200
|
+
get parent() {
|
|
201
|
+
return this._parent;
|
|
202
|
+
}
|
|
203
|
+
get pathFromRoot() {
|
|
204
|
+
return this._pathFromRoot;
|
|
205
|
+
}
|
|
206
|
+
get firstChild() {
|
|
207
|
+
return this._firstChild;
|
|
208
|
+
}
|
|
209
|
+
get children() {
|
|
210
|
+
return this._children;
|
|
211
|
+
}
|
|
212
|
+
get routeConfig() {
|
|
213
|
+
return this.snapshot.routeConfig;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Triggers a navigation with the given new parameters. All the other parts (query params etc.) stay as they are.
|
|
217
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the parameters.
|
|
218
|
+
*/
|
|
219
|
+
setParams(params) {
|
|
220
|
+
this.triggerNavigation({ params });
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Triggers a navigation with the given new parameter. The other parameters, as well as all the other parts (query params etc.)
|
|
224
|
+
* stay as they are.
|
|
225
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change one parameter.
|
|
226
|
+
*/
|
|
227
|
+
setParam(name, value) {
|
|
228
|
+
this.setParams({ ...this.snapshot.params, [name]: value });
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Triggers a navigation with the given new query parameters. All the other parts (params etc.) stay as the are.
|
|
232
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the query parameters.
|
|
233
|
+
*/
|
|
234
|
+
setQueryParams(queryParams) {
|
|
235
|
+
this.triggerNavigation({ queryParams });
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Triggers a navigation with the given new parameter. The other query parameters, as well as all the other parts (params etc.)
|
|
239
|
+
* stay as the are.
|
|
240
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change one query parameter.
|
|
241
|
+
*/
|
|
242
|
+
setQueryParam(name, value) {
|
|
243
|
+
this.setQueryParams({ ...this.snapshot.queryParams, [name]: value });
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Triggers a navigation with the given new data. The other parameters, as well as all the other parts (params etc.)
|
|
247
|
+
* stay as the are.
|
|
248
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the data.
|
|
249
|
+
*/
|
|
250
|
+
setData(data) {
|
|
251
|
+
this.triggerNavigation({ data });
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Triggers a navigation with the given new data item. The other data, as well as all the other parts (params etc.)
|
|
255
|
+
* stay as the are.
|
|
256
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change one data item.
|
|
257
|
+
*/
|
|
258
|
+
setDataItem(name, value) {
|
|
259
|
+
this.setData({ ...this.snapshot.data, [name]: value });
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Triggers a navigation with the given new title. The other parameters, as well as all the other parts (params etc.)
|
|
263
|
+
* stay as the are.
|
|
264
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the title.
|
|
265
|
+
*/
|
|
266
|
+
setTitle(title) {
|
|
267
|
+
this.triggerNavigation({ title: { value: title } });
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Triggers a navigation with the given new fragment. The other parts (params etc.) stay as the are.
|
|
271
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the fragment.
|
|
272
|
+
*/
|
|
273
|
+
setFragment(fragment) {
|
|
274
|
+
this.triggerNavigation({ fragment });
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Triggers a navigation with the given new url. The other parts (params etc.) stay as the are.
|
|
278
|
+
* This is a shortcut to `triggerNavigation` that can be used to only change the url.
|
|
279
|
+
*/
|
|
280
|
+
setUrl(url) {
|
|
281
|
+
this.triggerNavigation({ url });
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Triggers a navigation based on the given options. If an option is undefined or null, it's ignored. Except for fragment, which is only
|
|
285
|
+
* ignored if it's undefined, because null is a valid value for a fragment.
|
|
286
|
+
*
|
|
287
|
+
* The non-ignored values are used to change the snapshot of the route. Once the snapshot has been modified,
|
|
288
|
+
* the observables corresponding to the updated parts emit the new value.
|
|
289
|
+
*
|
|
290
|
+
* So, setting params and query params will make the params and queryParams observables emit, but not the fragment, data and
|
|
291
|
+
* url observables for example. This is consistent to how the router behaves.
|
|
292
|
+
*
|
|
293
|
+
* Note: since the title of a route can become undefined, in order to be able to distinguish between a navigation which leaves the title
|
|
294
|
+
* as it is and a navigation that sets the title to undefined, a wrapper object is used for the title. So
|
|
295
|
+
*
|
|
296
|
+
* - `triggerNavigation({ params:... })` leaves the title as is because it's undefined in the options
|
|
297
|
+
* - `triggerNavigation({ title: { value: 'test' } })` sets the title to 'test'
|
|
298
|
+
* - `triggerNavigation({ title: { value: undefined } })` sets the title to undefined
|
|
299
|
+
*/
|
|
300
|
+
triggerNavigation(options) {
|
|
301
|
+
// set the snapshot first
|
|
302
|
+
if (options.params) {
|
|
303
|
+
this.snapshot.params = options.params;
|
|
304
|
+
}
|
|
305
|
+
if (options.queryParams) {
|
|
306
|
+
this.snapshot.queryParams = options.queryParams;
|
|
307
|
+
}
|
|
308
|
+
if (options.fragment !== undefined) {
|
|
309
|
+
this.snapshot.fragment = options.fragment;
|
|
310
|
+
}
|
|
311
|
+
if (options.data) {
|
|
312
|
+
this.snapshot.data = options.data;
|
|
313
|
+
}
|
|
314
|
+
if (options.title) {
|
|
315
|
+
// @ts-expect-error the title is readonly, but we need to be able to overwrite it here
|
|
316
|
+
this.snapshot.title = options.title.value;
|
|
317
|
+
}
|
|
318
|
+
if (options.url) {
|
|
319
|
+
this.snapshot.url = options.url;
|
|
320
|
+
}
|
|
321
|
+
// then emit everything that has changed
|
|
322
|
+
if (options.params) {
|
|
323
|
+
this.paramsSubject.next(this.snapshot.params);
|
|
324
|
+
}
|
|
325
|
+
if (options.queryParams) {
|
|
326
|
+
this.queryParamsSubject.next(this.snapshot.queryParams);
|
|
327
|
+
}
|
|
328
|
+
if (options.fragment !== undefined) {
|
|
329
|
+
this.fragmentSubject.next(this.snapshot.fragment);
|
|
330
|
+
}
|
|
331
|
+
if (options.data) {
|
|
332
|
+
this.dataSubject.next(this.snapshot.data);
|
|
333
|
+
}
|
|
334
|
+
if (options.title) {
|
|
335
|
+
this.titleSubject.next(this.snapshot.title);
|
|
336
|
+
}
|
|
337
|
+
if (options.url) {
|
|
338
|
+
this.urlSubject.next(this.snapshot.url);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
toString() {
|
|
342
|
+
return 'ActivatedRouteStub';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Creates a new ActivatedRouteStub, by calling its constructor.
|
|
347
|
+
*/
|
|
348
|
+
export function stubRoute(options) {
|
|
349
|
+
return new ActivatedRouteStub(options);
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc3BlY3Vsb29zL3NyYy9saWIvcm91dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxzQkFBc0IsRUFBRSxpQkFBaUIsRUFBNkMsTUFBTSxpQkFBaUIsQ0FBQztBQUN2SSxPQUFPLEVBQUUsZUFBZSxFQUFFLEdBQUcsRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUd4RDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsT0E0QnpCO0lBQ0MsTUFBTSxNQUFNLEdBQUc7UUFDYixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7UUFDaEIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3RCLFFBQVEsRUFBRSxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDekYsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO1FBQ2hDLGFBQWEsRUFBRSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDeEcsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1FBQzFCLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtRQUNsQixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO1FBQzVCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtRQUMxQixXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVc7UUFDaEMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1FB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QUksT0FBTyxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUU7WUFDbEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNuRDtRQUNELElBQUksT0FBTyxDQUFDLElBQUksRUFBRTtZQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQzNDO1FBQ0QsSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDN0M7UUFDRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDZixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3pDO0lBQ0gsQ0FBQztJQUVNLFFBQVE7UUFDYixPQUFPLG9CQUFvQixDQUFDO0lBQzlCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFVLFNBQVMsQ0FBQyxPQUFtQztJQUMzRCxPQUFPLElBQUksa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDekMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBjb252ZXJ0VG9QYXJhbU1hcCwgRGF0YSwgUGFyYW1NYXAsIFBhcmFtcywgUm91dGUsIFVybFNlZ21lbnQgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBtYXAsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqXG4gKiBDcmVhdGVzIGEgZmFrZSBwYXJ0aWFsIEFjdGl2YXRlZFJvdXRlIGZvciB0ZXN0cy5cbiAqXG4gKiBJZiB5b3UgcGFzcyBwYXJhbXMsIHRoZW4gdGhlIGNyZWF0ZWQgcm91dGUncyBwYXJhbU1hcCB3aWxsIGNvbnRhaW4gdGhlIHNhbWUgdmFsdWVzLlxuICogVGhlIHNhbWUgZ29lcyBmb3IgcXVlcnlQYXJhbXMgYW5kIHF1ZXJ5UGFyYW1NYXAuXG4gKlxuICogSWYgeW91IHBhc3MgYSBwYXJlbnQgcm91dGUgYW5kIGEgc25hcHNob3QsIGFuZCB0aGUgcGFzc2VkIHNuYXBzaG90IGRvZXNuJ3QgaGF2ZSBhIHBhcmVudCwgdGhlbiB0aGUgc25hcHNob3Qnc1xuICogcGFyZW50IHdpbGwgYmUgc2V0IHRvIHRoZSBwYXJlbnQgcm91dGUgc25hcHNob3QuIFRoaXMgYWxsb3dzIHRoZSBjb2RlIHVuZGVyIHRlc3QgdG8gdXNlXG4gKiBgcm91dGUucGFyZW50LnNuYXBzaG90YCBvciBgcm91dGUuc25hcHNob3QucGFyZW50YC5cbiAqXG4gKiBJZiB5b3UgcGFzcyBhIHNuYXBzaG90IHdpdGggYSBwYXJlbnQsIGJ1dCBkb24ndCBwYXNzIGEgcGFyZW50IG9yIHBhc3MgYSBwYXJlbnQgd2l0aG91dCBzbmFwc2hvdCwgdGhlbiB0aGUgcm91dGUnc1xuICogcGFyZW50IHNuYXBzaG90IHdpbGwgYmUgc2V0IHRvIHRoZSBnaXZlbiBzbmFwc2hvdCdzIHBhcmVudC4gVGhpcyBhbGxvd3MgdGhlIGNvZGUgdW5kZXIgdGVzdCB0byB1c2VcbiAqIGByb3V0ZS5wYXJlbnQuc25hcHNob3RgIG9yIGByb3V0ZS5zbmFwc2hvdC5wYXJlbnRgLlxuICpcbiAqIEByZXR1cm5zIGEgcGFydGlhbGx5IHBvcHVsYXRlZCwgZmFrZSBBY3RpdmF0ZWRSb3V0ZSwgZGVwZW5kaW5nIG9uIHdoYXQgeW91IHBhc3NlZCBpblxuICogQGRlcHJlY2F0ZWQgZmF2b3Igc3R1YlJvdXRlLCB3aGljaCBjcmVhdGVzIGFuIGVhc2llciB0byB1c2UgYW5kIG1vcmUgbG9naWNhbCBzdHViXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmYWtlUm91dGUob3B0aW9uczoge1xuICB1cmw/OiBPYnNlcnZhYmxlPFVybFNlZ21lbnRbXT47XG4gIC8qKiBBbiBvYnNlcnZhYmxlIG9mIHRoZSBtYXRyaXggcGFyYW1ldGVycyBzY29wZWQgdG8gdGhpcyByb3V0ZSAqL1xuICBwYXJhbXM/OiBPYnNlcnZhYmxlPFBhcmFtcz47XG4gIC8qKiBBbiBvYnNlcnZhYmxlIG9mIHRoZSBxdWVyeSBwYXJhbWV0ZXJzIHNoYXJlZCBieSBhbGwgdGhlIHJvdXRlcyAqL1xuICBxdWVyeVBhcmFtcz86IE9ic2VydmFibGU8UGFyYW1zPjtcbiAgLyoqIEFuIG9ic2VydmFibGUgb2YgdGhlIFVSTCBmcmFnbWVudCBzaGFyZWQgYnkgYWxsIHRoZSByb3V0ZXMgKi9cbiAgZnJhZ21lbnQ/OiBPYnNlcnZhYmxlPHN0cmluZz47XG4gIC8qKiBBbiBvYnNlcnZhYmxlIG9mIHRoZSBzdGF0aWMgYW5kIHJlc29sdmVkIGRhdGEgb2YgdGhpcyByb3V0ZS4gKi9cbiAgZGF0YT86IE9ic2VydmFibGU8RGF0YT47XG4gIC8qKiBUaGUgb3V0bGV0IG5hbWUgb2YgdGhlIHJvdXRlLiBJdCdzIGEgY29uc3RhbnQgKi9cbiAgb3V0bGV0Pzogc3RyaW5nO1xuICAvKiogVGhlIGNvbXBvbmVudCBvZiB0aGUgcm91dGUuIEl0J3MgYSBjb25zdGFudCAqL1xuICBjb21wb25lbnQ/OiBUeXBlPHVua25vd24+IHwgc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFRoZSBjdXJyZW50IHNuYXBzaG90IG9mIHRoaXMgcm91dGUgKi9cbiAgc25hcHNob3Q/OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90O1xuICAvKiogVGhlIGNvbmZpZ3VyYXRpb24gdXNlZCB0byBtYXRjaCB0aGlzIHJvdXRlICovXG4gIHJvdXRlQ29uZmlnPzogUm91dGUgfCBudWxsO1xuICAvKiogVGhlIHJvb3Qgb2YgdGhlIHJvdXRlciBzdGF0ZSAqL1xuICByb290PzogQWN0aXZhdGVkUm91dGU7XG4gIC8qKiBUaGUgcGFyZW50IG9mIHRoaXMgcm91dGUgaW4gdGhlIHJvdXRlciBzdGF0ZSB0cmVlICovXG4gIHBhcmVudD86IEFjdGl2YXRlZFJvdXRlIHwgbnVsbDtcbiAgLyoqIFRoZSBmaXJzdCBjaGlsZCBvZiB0aGlzIHJvdXRlIGluIHRoZSByb3V0ZXIgc3RhdGUgdHJlZSAqL1xuICBmaXJzdENoaWxkPzogQWN0aXZhdGVkUm91dGU7XG4gIC8qKiBUaGUgY2hpbGRyZW4gb2YgdGhpcyByb3V0ZSBpbiB0aGUgcm91dGVyIHN0YXRlIHRyZWUgKi9cbiAgY2hpbGRyZW4/OiBBY3RpdmF0ZWRSb3V0ZVtdO1xuICAvKiogVGhlIHBhdGggZnJvbSB0aGUgcm9vdCBvZiB0aGUgcm91dGVyIHN0YXRlIHRyZWUgdG8gdGhpcyByb3V0ZSAqL1xuICBwYXRoRnJvbVJvb3Q/OiBBY3RpdmF0ZWRSb3V0ZVtdO1xufSk6IEFjdGl2YXRlZFJvdXRlIHtcbiAgY29uc3QgcmVzdWx0ID0ge1xuICAgIHVybDogb3B0aW9ucy51cmwsXG4gICAgcGFyYW1zOiBvcHRpb25zLnBhcmFtcyxcbiAgICBwYXJhbU1hcDogb3B0aW9ucy5wYXJhbXMgJiYgb3B0aW9ucy5wYXJhbXMucGlwZShtYXAocGFyYW1zID0+IGNvbnZlcnRUb1BhcmFtTWFwKHBhcmFtcykpKSxcbiAgICBxdWVyeVBhcmFtczogb3B0aW9ucy5xdWVyeVBhcmFtcyxcbiAgICBxdWVyeVBhcmFtTWFwOiBvcHRpb25zLnF1ZXJ5UGFyYW1zICYmIG9wdGlvbnMucXVlcnlQYXJhbXMucGlwZShtYXAocGFyYW1zID0+IGNvbnZlcnRUb1BhcmFtTWFwKHBhcmFtcykpKSxcbiAgICBmcmFnbWVudDogb3B0aW9ucy5mcmFnbWVudCxcbiAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgb3V0bGV0OiBvcHRpb25zLm91dGxldCxcbiAgICBjb21wb25lbnQ6IG9wdGlvbnMuY29tcG9uZW50LFxuICAgIHNuYXBzaG90OiBvcHRpb25zLnNuYXBzaG90LFxuICAgIHJvdXRlQ29uZmlnOiBvcHRpb25zLnJvdXRlQ29uZmlnLFxuICAgIHJvb3Q6IG9wdGlvbnMucm9vdCxcbiAgICBwYXJlbnQ6IG9wdGlvbnMucGFyZW50LFxuICAgIGZpcnN0Q2hpbGQ6IG9wdGlvbnMuZmlyc3RDaGlsZCxcbiAgICBjaGlsZHJlbjogb3B0aW9ucy5jaGlsZHJlbixcbiAgICBwYXRoRnJvbVJvb3Q6IG9wdGlvbnMucGF0aEZyb21Sb290XG4gIH0gYXMgQWN0aXZhdGVkUm91dGU7XG5cbiAgZm9yIChsZXQgcm91dGU6IG51bGwgfCBBY3RpdmF0ZWRSb3V0ZSA9IHJlc3VsdDsgcm91dGU7IHJvdXRlID0gcm91dGUucGFyZW50KSB7XG4gICAgaWYgKHJvdXRlLnBhcmVudCAmJiByb3V0ZS5wYXJlbnQuc25hcHNob3QgJiYgIXJvdXRlLnNuYXBzaG90KSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb25cbiAgICAgIHJvdXRlLnNuYXBzaG90ID0gZmFrZVNuYXBzaG90KHt9KTtcbiAgICB9XG4gICAgaWYgKHJvdXRlLnBhcmVudCAmJiByb3V0ZS5wYXJlbnQuc25hcHNob3QgJiYgIXJvdXRlLnNuYXBzaG90LnBhcmVudCkge1xuICAgICAgKHJvdXRlLnNuYXBzaG90IGFzIE9taXQ8QWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgJ3BhcmVudCc+ICYgeyBwYXJlbnQ6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QgfSkucGFyZW50ID0gcm91dGUucGFyZW50LnNuYXBzaG90O1xuICAgIH1cblxuICAgIGlmIChyb3V0ZS5zbmFwc2hvdCAmJiByb3V0ZS5zbmFwc2hvdC5wYXJlbnQgJiYgIXJvdXRlLnBhcmVudCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uXG4gICAgICAocm91dGUgYXMgT21pdDxBY3RpdmF0ZWRSb3V0ZSwgJ3BhcmVudCc+ICYgeyBwYXJlbnQ6IEFjdGl2YXRlZFJvdXRlIH0pLnBhcmVudCA9IGZha2VSb3V0ZSh7fSk7XG4gICAgfVxuICAgIGlmIChyb3V0ZS5zbmFwc2hvdCAmJiByb3V0ZS5zbmFwc2hvdC5wYXJlbnQgJiYgcm91dGUucGFyZW50ICYmICFyb3V0ZS5wYXJlbnQuc25hcHNob3QpIHtcbiAgICAgIHJvdXRlLnBhcmVudC5zbmFwc2hvdCA9IHJvdXRlLnNuYXBzaG90LnBhcmVudDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBmYWtlIHBhcnRpYWwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCBmb3IgdGVzdHMuXG4gKlxuICogSWYgeW91IHBhc3MgcGFyYW1zLCB0aGVuIHRoZSBjcmVhdGVkIHNuYXBzaG90J3MgcGFyYW1NYXAgd2lsbCBjb250YWluIHRoZSBzYW1lIHZhbHVlcy5cbiAqIFRoZSBzYW1lIGdvZXMgZm9yIHF1ZXJ5UGFyYW1zIGFuZCBxdWVyeVBhcmFtTWFwLlxuICpcbiAqIEByZXR1cm5zIGEgcGFydGlhbGx5IHBvcHVsYXRlZCwgZmFrZSBBY3RpdmF0ZWRSb3V0ZSwgZGVwZW5kaW5nIG9uIHdoYXQgeW91IHBhc3NlZCBpblxuICogQGRlcHJlY2F0ZWQgZmF2b3Igc3R1YlJvdXRlLCB3aGljaCBjcmVhdGVzIGFuIGVhc2llciB0byB1c2UgYW5kIG1vcmUgbG9naWNhbCBzdHViIGZvciBib3RoIHRoZSByb3V0ZSBhbmQgaXRzIHNuYXBzaG90XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmYWtlU25hcHNob3Qob3B0aW9uczoge1xuICB1cmw/OiBVcmxTZWdtZW50W107XG4gIC8qKiBUaGUgbWF0cml4IHBhcmFtZXRlcnMgc2NvcGVkIHRvIHRoaXMgcm91dGUgKi9cbiAgcGFyYW1zPzogUGFyYW1zO1xuICAvKiogVGhlIHF1ZXJ5IHBhcmFtZXRlcnMgc2hhcmVkIGJ5IGFsbCB0aGUgcm91dGVzICovXG4gIHF1ZXJ5UGFyYW1zPzogUGFyYW1zO1xuICAvKiogVGhlIFVSTCBmcmFnbWVudCBzaGFyZWQgYnkgYWxsIHRoZSByb3V0ZXMgKi9cbiAgZnJhZ21lbnQ/OiBzdHJpbmc7XG4gIC8qKiBUaGUgc3RhdGljIGFuZCByZXNvbHZlZCBkYXRhIG9mIHRoaXMgcm91dGUgKi9cbiAgZGF0YT86IERhdGE7XG4gIC8qKiBUaGUgb3V0bGV0IG5hbWUgb2YgdGhlIHJvdXRlICovXG4gIG91dGxldD86IHN0cmluZztcbiAgLyoqIFRoZSBjb21wb25lbnQgb2YgdGhlIHJvdXRlICovXG4gIGNvbXBvbmVudD86IFR5cGU8dW5rbm93bj4gfCBzdHJpbmcgfCBudWxsO1xuICAvKiogVGhlIGNvbmZpZ3VyYXRpb24gdXNlZCB0byBtYXRjaCB0aGlzIHJvdXRlICovXG4gIHJvdXRlQ29uZmlnPzogUm91dGU7XG4gIC8qKiBUaGUgcm9vdCBvZiB0aGUgcm91dGVyIHN0YXRlICovXG4gIHJvb3Q/OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90O1xuICAvKiogVGhlIHBhcmVudCBvZiB0aGlzIHJvdXRlIGluIHRoZSByb3V0ZXIgc3RhdGUgdHJlZSAqL1xuICBwYXJlbnQ/OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHwgbnVsbDtcbiAgLyoqIFRoZSBmaXJzdCBjaGlsZCBvZiB0aGlzIHJvdXRlIGluIHRoZSByb3V0ZXIgc3RhdGUgdHJlZSAqL1xuICBmaXJzdENoaWxkPzogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB8IG51bGw7XG4gIC8qKiBUaGUgY2hpbGRyZW4gb2YgdGhpcyByb3V0ZSBpbiB0aGUgcm91dGVyIHN0YXRlIHRyZWUgKi9cbiAgY2hpbGRyZW4/OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90W107XG4gIC8qKiBUaGUgcGF0aCBmcm9tIHRoZSByb290IG9mIHRoZSByb3V0ZXIgc3RhdGUgdHJlZSB0byB0aGlzIHJvdXRlICovXG4gIHBhdGhGcm9tUm9vdD86IEFjdGl2YXRlZFJvdXRlU25hcHNob3RbXTtcbn0pOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHtcbiAgcmV0dXJuIHtcbiAgICB1cmw6IG9wdGlvbnMudXJsLFxuICAgIHBhcmFtczogb3B0aW9ucy5wYXJhbXMsXG4gICAgcGFyYW1NYXA6IG9wdGlvbnMucGFyYW1zICYmIGNvbnZlcnRUb1BhcmFtTWFwKG9wdGlvbnMucGFyYW1zKSxcbiAgICBxdWVyeVBhcmFtczogb3B0aW9ucy5xdWVyeVBhcmFtcyxcbiAgICBxdWVyeVBhcmFtTWFwOiBvcHRpb25zLnF1ZXJ5UGFyYW1zICYmIGNvbnZlcnRUb1BhcmFtTWFwKG9wdGlvbnMucXVlcnlQYXJhbXMpLFxuICAgIGZyYWdtZW50OiBvcHRpb25zLmZyYWdtZW50LFxuICAgIGRhdGE6IG9wdGlvbnMuZGF0YSxcbiAgICBvdXRsZXQ6IG9wdGlvbnMub3V0bGV0LFxuICAgIGNvbXBvbmVudDogb3B0aW9ucy5jb21wb25lbnQsXG4gICAgcm91dGVDb25maWc6IG9wdGlvbnMucm91dGVDb25maWcsXG4gICAgcm9vdDogb3B0aW9ucy5yb290LFxuICAgIHBhcmVudDogb3B0aW9ucy5wYXJlbnQsXG4gICAgZmlyc3RDaGlsZDogb3B0aW9ucy5maXJzdENoaWxkLFxuICAgIGNoaWxkcmVuOiBvcHRpb25zLmNoaWxkcmVuLFxuICAgIHBhdGhGcm9tUm9vdDogb3B0aW9ucy5wYXRoRnJvbVJvb3RcbiAgfSBhcyBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90O1xufVxuXG4vKipcbiAqIFRoZSBvcHRpb25zIHRoYXQgYXJlIHBhc3NlZCB3aGVuIGNyZWF0aW5nIGFuIEFjdGl2YXRlZFJvdXRlU3R1Yi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBY3RpdmF0ZWRSb3V0ZVN0dWJPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsIHZhbHVlcyBvZiB0aGUgcGFyYW1ldGVycyBvZiB0aGUgcm91dGVcbiAgICovXG4gIHBhcmFtcz86IFBhcmFtcztcbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsIHZhbHVlcyBvZiB0aGUgcXVlcnkgcGFyYW1ldGVycyBvZiB0aGUgcm91dGVcbiAgICovXG4gIHF1ZXJ5UGFyYW1zPzogUGFyYW1zO1xuICAvKipcbiAgICogVGhlIGluaXRpYWwgdmFsdWVzIG9mIHRoZSBkYXRhIG9mIHRoZSByb3V0ZVxuICAgKi9cbiAgZGF0YT86IERhdGE7XG4gIC8qKlxuICAgKiBUaGUgaW5pdGlhbCB2YWx1ZXMgb2YgdGhlIHRpdGxlIG9mIHRoZSByb3V0ZVxuICAgKi9cbiAgdGl0bGU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgaW5pdGlhbCBmcmFnbWVudCBvZiB0aGUgcm91dGVcbiAgICovXG4gIGZyYWdtZW50Pzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsIHVybCBvZiB0aGUgcm91dGVcbiAgICovXG4gIHVybD86IFVybFNlZ21lbnRbXTtcbiAgLyoqXG4gICAqIFRoZSBwYXJlbnQgb2YgdGhlIHJvdXRlXG4gICAqL1xuICBwYXJlbnQ/OiBBY3RpdmF0ZWRSb3V0ZVN0dWIgfCBudWxsO1xuICAvKipcbiAgICogVGhlIGZpcnN0IGNoaWxkIG9mIHRoZSByb3V0ZVxuICAgKi9cbiAgZmlyc3RDaGlsZD86IEFjdGl2YXRlZFJvdXRlU3R1YiB8IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgY2hpbGRyZW4gb2YgdGhlIHJvdXRlXG4gICAqL1xuICBjaGlsZHJlbj86IEFjdGl2YXRlZFJvdXRlU3R1YltdIHwgbnVsbDtcbiAgLyoqXG4gICAqIFRoZSBjb25maWd1cmF0aW9uIG9mIHRoZSByb3V0ZVxuICAgKi9cbiAgcm91dGVDb25maWc/OiBSb3V0ZSB8IG51bGw7XG59XG5cbmNsYXNzIEFjdGl2YXRlZFJvdXRlU25hcHNob3RTdHViIGV4dGVuZHMgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB7XG4gIHByaXZhdGUgX3BhcmVudDogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9yb290OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90O1xuICBwcml2YXRlIF9maXJzdENoaWxkOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX2NoaWxkcmVuOiBBcnJheTxBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90PiA9IFtdO1xuICBwcml2YXRlIF9wYXRoRnJvbVJvb3Q6IEFycmF5PEFjdGl2YXRlZFJvdXRlU25hcHNob3Q+ID0gW107XG4gIHByaXZhdGUgX3RpdGxlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgZ2V0IHBhcmVudCgpOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX3BhcmVudDtcbiAgfVxuXG4gIHNldCBwYXJlbnQodmFsdWU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QgfCBudWxsKSB7XG4gICAgdGhpcy5fcGFyZW50ID0gdmFsdWU7XG4gIH1cblxuICBnZXQgcm9vdCgpOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHtcbiAgICByZXR1cm4gdGhpcy5fcm9vdDtcbiAgfVxuXG4gIHNldCByb290KHZhbHVlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSB7XG4gICAgdGhpcy5fcm9vdCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IGZpcnN0Q2hpbGQoKTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9maXJzdENoaWxkO1xuICB9XG5cbiAgc2V0IGZpcnN0Q2hpbGQodmFsdWU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QgfCBudWxsKSB7XG4gICAgdGhpcy5fZmlyc3RDaGlsZCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IGNoaWxkcmVuKCk6IEFycmF5PEFjdGl2YXRlZFJvdXRlU25hcHNob3Q+IHtcbiAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW47XG4gIH1cblxuICBzZXQgY2hpbGRyZW4odmFsdWU6IEFycmF5PEFjdGl2YXRlZFJvdXRlU25hcHNob3Q+KSB7XG4gICAgdGhpcy5fY2hpbGRyZW4gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBwYXRoRnJvbVJvb3QoKTogQXJyYXk8QWN0aXZhdGVkUm91dGVTbmFwc2hvdD4ge1xuICAgIHJldHVybiB0aGlzLl9wYXRoRnJvbVJvb3Q7XG4gIH1cblxuICBzZXQgcGF0aEZyb21Sb290KHZhbHVlOiBBcnJheTxBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90Pikge1xuICAgIHRoaXMuX3BhdGhGcm9tUm9vdCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IHRpdGxlKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3RpdGxlO1xuICB9XG5cbiAgc2V0IHRpdGxlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl90aXRsZSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IHBhcmFtTWFwKCk6IFBhcmFtTWFwIHtcbiAgICByZXR1cm4gY29udmVydFRvUGFyYW1NYXAodGhpcy5wYXJhbXMpO1xuICB9XG5cbiAgZ2V0IHF1ZXJ5UGFyYW1NYXAoKTogUGFyYW1NYXAge1xuICAgIHJldHVybiBjb252ZXJ0VG9QYXJhbU1hcCh0aGlzLnF1ZXJ5UGFyYW1zKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5fcm9vdCA9IHRoaXM7XG4gIH1cbn1cblxuLyoqXG4gKiBBIHN0dWIgZm9yIEFjdGl2YXRlZFJvdXRlLiBJdCBiZWhhdmVzIGFsbW9zdCB0aGUgc2FtZSB3YXkgYXMgdGhlIGFjdHVhbCBBY3RpdmF0ZWRSb3V0ZSwgZXhwb3NpbmcgYSBzbmFwc2hvdFxuICogYW5kIG9ic2VydmFibGVzIGZvciB0aGUgcGFyYW1zLCBxdWVyeSBwYXJhbXMgZXRjLiwgd2hpY2ggYXJlIGtlcHQgaW4gc3luYy5cbiAqXG4gKiBJbiBhZGRpdGlvbiwgdGhpcyBzdHViIGFsbG93cyBzaW11bGF0aW5nIGEgbmF2aWdhdGlvbiBieSBjaGFuZ2luZyB0aGUgcGFyYW1zLCB0aGUgcXVlcnkgcGFyYW1zLCB0aGUgZnJhZ21lbnQsIGV0Yy5cbiAqIFdoZW4gdGhhdCBoYXBwZW5zLCB0aGUgc25hcHNob3QgaXMgbW9kaWZpZWQsIHRoZW4gdGhlIHJlbGV2YW50IG9ic2VydmFibGVzIGVtaXQgdGhlIG5ldyB2YWx1ZXMuXG4gKlxuICogVGhlcmUgYXJlIHNvbWUgdGhpbmdzIHRoYXQgZG9uJ3QgcmVhbGx5IHdvcmsgdGhlIHNhbWUgd2F5IGFzIHRoZSByZWFsIEFjdGl2YXRlZFJvdXRlIHRob3VnaDpcbiAqIC0gdGhlIGhhbmRsaW5nIG9mIHRoZSBmaXJzdENoaWxkIGFuZCBvZiB0aGUgY2hpbGRyZW4gaXMgZW50aXJlbHkgdW5kZXIgdGhlIHRlc3RlcidzIHJlc3BvbnNpYmlsaXR5LiBTZXR0aW5nIHRoZSBwYXJlbnRcbiAqICAgb2YgYSByb3V0ZSBzdHViIGRvZXMgbm90IGFkZCB0aGlzIHJvdXRlIHRvIHRoZSBjaGlsZHJlbiBvZiBpdHMgcGFyZW50LCBmb3IgZXhhbXBsZS5cbiAqIC0gd2hlbiBjaGFuZ2luZyB0aGUgcGFyYW1zLCBxdWVyeSBwYXJhbXMsIGZyYWdtZW50LCBldGMuLCB0aGVpciBhc3NvY2lhdGVkIG9ic2VydmFibGUgZW1pdHMgdW5jb25kaXRpb25hbGx5LCBpbnN0ZWFkIG9mXG4gKiAgIGZpcnN0IGNoZWNraW5nIGlmIHRoZSB2YWx1ZSBpcyBhY3R1YWxseSBkaWZmZXJlbnQgZnJvbSBiZWZvcmUuIEl0J3MgdGh1cyB0aGUgcmVzcG9uc2liaWxpdHkgb2YgdGhlIHRlc3RlciB0byBub3RcbiAqICAgY2hhbmdlIHRoZSB2YWx1ZXMgaWYgdGhleSdyZSB0aGUgc2FtZSBhcyBiZWZvcmUuXG4gKiAtIHRoZSBwYXJhbXMsIHBhcmFtTWFwLCBxdWVyeVBhcmFtcyBhbmQgcXVlcnlQYXJhbU1hcCBvYmplY3RzIG9mIHRoZSByb3V0ZSBzbmFwc2hvdCBjaGFuZ2Ugd2hlbiBwYXJhbXMgb3IgcXVlcnkgcGFyYW1zIGFyZSBzZXRcbiAqICAgb24gdGhlIHN0dWIgcm91dGUuIFNvIGlmIHRoZSBjb2RlIGtlZXBzIGEgcmVmZXJlbmNlIHRvIHBhcmFtcyBvciBwYXJhbU1hcHMsIGl0IHdvbid0IHNlZSB0aGUgY2hhbmdlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIEFjdGl2YXRlZFJvdXRlU3R1YiBleHRlbmRzIEFjdGl2YXRlZFJvdXRlIHtcbiAgcHJpdmF0ZSBfZmlyc3RDaGlsZDogQWN0aXZhdGVkUm91dGVTdHViIHwgbnVsbDtcbiAgcHJpdmF0ZSBfY2hpbGRyZW46IEFycmF5PEFjdGl2YXRlZFJvdXRlU3R1Yj47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBwYXJhbXNTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8UGFyYW1zPjtcbiAgcHJpdmF0ZSByZWFkb25seSBxdWVyeVBhcmFtc1N1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxQYXJhbXM+O1xuICBwcml2YXRlIHJlYWRvbmx5IGRhdGFTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8RGF0YT47XG4gIHByaXZhdGUgcmVhZG9ubHkgZnJhZ21lbnRTdWJqZWN0OiBCZWhhdmlvclN1YmplY3Q8c3RyaW5nIHwgbnVsbD47XG4gIHByaXZhdGUgcmVhZG9ubHkgdXJsU3ViamVjdDogQmVoYXZpb3JTdWJqZWN0PEFycmF5PFVybFNlZ21lbnQ+PjtcbiAgcHJpdmF0ZSByZWFkb25seSB0aXRsZVN1YmplY3Q6IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCB1bmRlZmluZWQ+O1xuXG4gIHByaXZhdGUgX3BhcmVudDogQWN0aXZhdGVkUm91dGVTdHViIHwgbnVsbDtcbiAgcHJpdmF0ZSBfcm9vdDogQWN0aXZhdGVkUm91dGVTdHViO1xuICBwcml2YXRlIF9wYXRoRnJvbVJvb3Q6IEFycmF5PEFjdGl2YXRlZFJvdXRlU3R1Yj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSBuZXcgaW5zdGFuY2UsIGJhc2VkIG9uIHRoZSBnaXZlbiBvcHRpb25zLlxuICAgKiBJZiBhbiBvcHRpb24gaXMgbm90IHByb3ZpZGVkIChvciBpZiBubyBvcHRpb24gaXMgcHJvdmlkZWQgYXQgYWxsKSwgdGhlbiB0aGUgcm91dGUgaGFzIGEgZGVmYXVsdCB2YWx1ZSBmb3IgdGhpcyBvcHRpb25cbiAgICogKGVtcHR5IHBhcmFtZXRlcnMgZm9yIGV4YW1wbGUsIG51bGwgZnJhZ21lbnQsIGV0Yy4pXG4gICAqIElmIG5vIHBhcmVudCBpcyBwYXNzZWQsIHRoZW4gdGhpcyByb3V0ZSBoYXMgbm8gcGFyZW50IGFuZCBpcyB0aHVzIHNldCBhcyB0aGUgcm9vdC4gT3RoZXJ3aXNlLCB0aGUgcm9vdCBhbmQgdGhlIHBhdGhcbiAgICogZnJvbSByb290IGFyZSBjcmVhdGVkIGJhc2VkIG9uIHRoZSByb290IGFuZCBwYXRoIGZyb20gcm9vdCBvZiB0aGUgZ2l2ZW4gcGFyZW50IHJvdXRlLlxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucz86IEFjdGl2YXRlZFJvdXRlU3R1Yk9wdGlvbnMpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29uc3Qgc25hcHNob3QgPSBuZXcgQWN0aXZhdGVkUm91dGVTbmFwc2hvdFN0dWIoKTtcbiAgICB0aGlzLnNuYXBzaG90ID0gc25hcHNob3Q7XG5cbiAgICB0aGlzLl9maXJzdENoaWxkID0gb3B0aW9ucz8uZmlyc3RDaGlsZCA/PyBudWxsO1xuICAgIHRoaXMuX2NoaWxkcmVuID0gb3B0aW9ucz8uY2hpbGRyZW4gPz8gW107XG4gICAgdGhpcy5fcGFyZW50ID0gb3B0aW9ucz8ucGFyZW50ID8/IG51bGw7XG4gICAgdGhpcy5fcm9vdCA9IHRoaXMucGFyZW50Py5yb290ID8/IHRoaXM7XG4gICAgdGhpcy5fcGF0aEZyb21Sb290ID0gdGhpcy5wYXJlbnQgPyBbLi4udGhpcy5wYXJlbnQucGF0aEZyb21Sb290LCB0aGlzXSA6IFt0aGlzXTtcblxuICAgIHNuYXBzaG90LnBhcmFtcyA9IG9wdGlvbnM/LnBhcmFtcyA/PyB7fTtcbiAgICBzbmFwc2hvdC5xdWVyeVBhcmFtcyA9IG9wdGlvbnM/LnF1ZXJ5UGFyYW1zID8/IHt9O1xuICAgIHNuYXBzaG90LmRhdGEgPSBvcHRpb25zPy5kYXRhID8/IHt9O1xuICAgIHNuYXBzaG90LnRpdGxlID0gb3B0aW9ucz8udGl0bGU7XG4gICAgc25hcHNob3QuZnJhZ21lbnQgPSBvcHRpb25zPy5mcmFnbWVudCA/PyBudWxsO1xuICAgIHNuYXBzaG90LnVybCA9IG9wdGlvbnM/LnVybCA/PyBbXTtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHRoZSByb3V0ZUNvbmZpZyBpcyByZWFkb25seSwgYnV0IHdlIG5lZWQgdG8gb3ZlcndyaXRlIGl0IGhlcmVcbiAgICBzbmFwc2hvdC5yb3V0ZUNvbmZpZyA9IG9wdGlvbnM/LnJvdXRlQ29uZmlnID8/IG51bGw7XG5cbiAgICBzbmFwc2hvdC5maXJzdENoaWxkID0gdGhpcy5maXJzdENoaWxkPy5zbmFwc2hvdCA/PyBudWxsO1xuICAgIHNuYXBzaG90LmNoaWxkcmVuID0gdGhpcy5jaGlsZHJlbj8ubWFwKHJvdXRlID0+IHJvdXRlLnNuYXBzaG90KSA/PyBbXTtcbiAgICBzbmFwc2hvdC5wYXJlbnQgPSB0aGlzLnBhcmVudD8uc25hcHNob3QgPz8gbnVsbDtcbiAgICBzbmFwc2hvdC5yb290ID0gdGhpcy5yb290LnNuYXBzaG90O1xuICAgIHNuYXBzaG90LnBhdGhGcm9tUm9vdCA9IHRoaXMucGF0aEZyb21Sb290Lm1hcChyb3V0ZSA9PiByb3V0ZS5zbmFwc2hvdCk7XG5cbiAgICB0aGlzLnBhcmFtc1N1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFBhcmFtcz4odGhpcy5zbmFwc2hvdC5wYXJhbXMpO1xuICAgIHRoaXMucXVlcnlQYXJhbXNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxQYXJhbXM+KHRoaXMuc25hcHNob3QucXVlcnlQYXJhbXMpO1xuICAgIHRoaXMuZGF0YVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PERhdGE+KHRoaXMuc25hcHNob3QuZGF0YSk7XG4gICAgdGhpcy50aXRsZVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IHVuZGVmaW5lZD4odGhpcy5zbmFwc2hvdC50aXRsZSk7XG4gICAgdGhpcy5mcmFnbWVudFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IG51bGw+KHRoaXMuc25hcHNob3QuZnJhZ21lbnQpO1xuICAgIHRoaXMudXJsU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXJyYXk8VXJsU2VnbWVudD4+KHRoaXMuc25hcHNob3QudXJsKTtcblxuICAgIHRoaXMucGFyYW1zID0gdGhpcy5wYXJhbXNTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIHRoaXMucXVlcnlQYXJhbXMgPSB0aGlzLnF1ZXJ5UGFyYW1zU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB0aGlzLmRhdGEgPSB0aGlzLmRhdGFTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIHRoaXMuZnJhZ21lbnQgPSB0aGlzLmZyYWdtZW50U3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICB0aGlzLnVybCA9IHRoaXMudXJsU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHRoZSB0aXRsZSBpcyByZWFkb25seSwgYnV0IHdlIG5lZWQgdG8gYmUgYWJsZSB0byBpbml0aWFsaXplIGl0ICBoZXJlXG4gICAgdGhpcy50aXRsZSA9IHRoaXMudGl0bGVTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgZ2V0IHJvb3QoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Jvb3Q7XG4gIH1cblxuICBnZXQgcGFyZW50KCk6IEFjdGl2YXRlZFJvdXRlU3R1YiB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9wYXJlbnQ7XG4gIH1cblxuICBnZXQgcGF0aEZyb21Sb290KCk6IEFycmF5PEFjdGl2YXRlZFJvdXRlU3R1Yj4ge1xuICAgIHJldHVybiB0aGlzLl9wYXRoRnJvbVJvb3Q7XG4gIH1cblxuICBnZXQgZmlyc3RDaGlsZCgpOiBBY3RpdmF0ZWRSb3V0ZVN0dWIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZmlyc3RDaGlsZDtcbiAgfVxuXG4gIGdldCBjaGlsZHJlbigpOiBBcnJheTxBY3RpdmF0ZWRSb3V0ZVN0dWI+IHtcbiAgICByZXR1cm4gdGhpcy5fY2hpbGRyZW47XG4gIH1cblxuICBnZXQgcm91dGVDb25maWcoKTogUm91dGUgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5zbmFwc2hvdC5yb3V0ZUNvbmZpZztcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhIG5hdmlnYXRpb24gd2l0aCB0aGUgZ2l2ZW4gbmV3IHBhcmFtZXRlcnMuIEFsbCB0aGUgb3RoZXIgcGFydHMgKHF1ZXJ5IHBhcmFtcyBldGMuKSBzdGF5IGFzIHRoZXkgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIHRoZSBwYXJhbWV0ZXJzLlxuICAgKi9cbiAgcHVibGljIHNldFBhcmFtcyhwYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgIHRoaXMudHJpZ2dlck5hdmlnYXRpb24oeyBwYXJhbXMgfSk7XG4gIH1cblxuICAvKipcbiAgICogVHJpZ2dlcnMgYSBuYXZpZ2F0aW9uIHdpdGggdGhlIGdpdmVuIG5ldyBwYXJhbWV0ZXIuIFRoZSBvdGhlciBwYXJhbWV0ZXJzLCBhcyB3ZWxsIGFzIGFsbCB0aGUgb3RoZXIgcGFydHMgKHF1ZXJ5IHBhcmFtcyBldGMuKVxuICAgKiBzdGF5IGFzIHRoZXkgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIG9uZSBwYXJhbWV0ZXIuXG4gICAqL1xuICBwdWJsaWMgc2V0UGFyYW0obmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5zZXRQYXJhbXMoeyAuLi50aGlzLnNuYXBzaG90LnBhcmFtcywgW25hbWVdOiB2YWx1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhIG5hdmlnYXRpb24gd2l0aCB0aGUgZ2l2ZW4gbmV3IHF1ZXJ5IHBhcmFtZXRlcnMuIEFsbCB0aGUgb3RoZXIgcGFydHMgKHBhcmFtcyBldGMuKSBzdGF5IGFzIHRoZSBhcmUuXG4gICAqIFRoaXMgaXMgYSBzaG9ydGN1dCB0byBgdHJpZ2dlck5hdmlnYXRpb25gIHRoYXQgY2FuIGJlIHVzZWQgdG8gb25seSBjaGFuZ2UgdGhlIHF1ZXJ5IHBhcmFtZXRlcnMuXG4gICAqL1xuICBwdWJsaWMgc2V0UXVlcnlQYXJhbXMocXVlcnlQYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgIHRoaXMudHJpZ2dlck5hdmlnYXRpb24oeyBxdWVyeVBhcmFtcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhIG5hdmlnYXRpb24gd2l0aCB0aGUgZ2l2ZW4gbmV3IHBhcmFtZXRlci4gVGhlIG90aGVyIHF1ZXJ5IHBhcmFtZXRlcnMsIGFzIHdlbGwgYXMgYWxsIHRoZSBvdGhlciBwYXJ0cyAocGFyYW1zIGV0Yy4pXG4gICAqIHN0YXkgYXMgdGhlIGFyZS5cbiAgICogVGhpcyBpcyBhIHNob3J0Y3V0IHRvIGB0cmlnZ2VyTmF2aWdhdGlvbmAgdGhhdCBjYW4gYmUgdXNlZCB0byBvbmx5IGNoYW5nZSBvbmUgcXVlcnkgcGFyYW1ldGVyLlxuICAgKi9cbiAgcHVibGljIHNldFF1ZXJ5UGFyYW0obmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5zZXRRdWVyeVBhcmFtcyh7IC4uLnRoaXMuc25hcHNob3QucXVlcnlQYXJhbXMsIFtuYW1lXTogdmFsdWUgfSk7XG4gIH1cblxuICAvKipcbiAgICogVHJpZ2dlcnMgYSBuYXZpZ2F0aW9uIHdpdGggdGhlIGdpdmVuIG5ldyBkYXRhLiBUaGUgb3RoZXIgcGFyYW1ldGVycywgYXMgd2VsbCBhcyBhbGwgdGhlIG90aGVyIHBhcnRzIChwYXJhbXMgZXRjLilcbiAgICogc3RheSBhcyB0aGUgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIHRoZSBkYXRhLlxuICAgKi9cbiAgcHVibGljIHNldERhdGEoZGF0YTogRGF0YSk6IHZvaWQge1xuICAgIHRoaXMudHJpZ2dlck5hdmlnYXRpb24oeyBkYXRhIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgbmF2aWdhdGlvbiB3aXRoIHRoZSBnaXZlbiBuZXcgZGF0YSBpdGVtLiBUaGUgb3RoZXIgZGF0YSwgYXMgd2VsbCBhcyBhbGwgdGhlIG90aGVyIHBhcnRzIChwYXJhbXMgZXRjLilcbiAgICogc3RheSBhcyB0aGUgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIG9uZSBkYXRhIGl0ZW0uXG4gICAqL1xuICBwdWJsaWMgc2V0RGF0YUl0ZW0obmFtZTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMuc2V0RGF0YSh7IC4uLnRoaXMuc25hcHNob3QuZGF0YSwgW25hbWVdOiB2YWx1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhIG5hdmlnYXRpb24gd2l0aCB0aGUgZ2l2ZW4gbmV3IHRpdGxlLiBUaGUgb3RoZXIgcGFyYW1ldGVycywgYXMgd2VsbCBhcyBhbGwgdGhlIG90aGVyIHBhcnRzIChwYXJhbXMgZXRjLilcbiAgICogc3RheSBhcyB0aGUgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIHRoZSB0aXRsZS5cbiAgICovXG4gIHB1YmxpYyBzZXRUaXRsZSh0aXRsZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gICAgdGhpcy50cmlnZ2VyTmF2aWdhdGlvbih7IHRpdGxlOiB7IHZhbHVlOiB0aXRsZSB9IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgbmF2aWdhdGlvbiB3aXRoIHRoZSBnaXZlbiBuZXcgZnJhZ21lbnQuIFRoZSBvdGhlciBwYXJ0cyAocGFyYW1zIGV0Yy4pICBzdGF5IGFzIHRoZSBhcmUuXG4gICAqIFRoaXMgaXMgYSBzaG9ydGN1dCB0byBgdHJpZ2dlck5hdmlnYXRpb25gIHRoYXQgY2FuIGJlIHVzZWQgdG8gb25seSBjaGFuZ2UgdGhlIGZyYWdtZW50LlxuICAgKi9cbiAgcHVibGljIHNldEZyYWdtZW50KGZyYWdtZW50OiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy50cmlnZ2VyTmF2aWdhdGlvbih7IGZyYWdtZW50IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgbmF2aWdhdGlvbiB3aXRoIHRoZSBnaXZlbiBuZXcgdXJsLiBUaGUgb3RoZXIgcGFydHMgKHBhcmFtcyBldGMuKSAgc3RheSBhcyB0aGUgYXJlLlxuICAgKiBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYHRyaWdnZXJOYXZpZ2F0aW9uYCB0aGF0IGNhbiBiZSB1c2VkIHRvIG9ubHkgY2hhbmdlIHRoZSB1cmwuXG4gICAqL1xuICBwdWJsaWMgc2V0VXJsKHVybDogQXJyYXk8VXJsU2VnbWVudD4pOiB2b2lkIHtcbiAgICB0aGlzLnRyaWdnZXJOYXZpZ2F0aW9uKHsgdXJsIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgbmF2aWdhdGlvbiBiYXNlZCBvbiB0aGUgZ2l2ZW4gb3B0aW9ucy4gSWYgYW4gb3B0aW9uIGlzIHVuZGVmaW5lZCBvciBudWxsLCBpdCdzIGlnbm9yZWQuIEV4Y2VwdCBmb3IgZnJhZ21lbnQsIHdoaWNoIGlzIG9ubHlcbiAgICogaWdub3JlZCBpZiBpdCdzIHVuZGVmaW5lZCwgYmVjYXVzZSBudWxsIGlzIGEgdmFsaWQgdmFsdWUgZm9yIGEgZnJhZ21lbnQuXG4gICAqXG4gICAqIFRoZSBub24taWdub3JlZCB2YWx1ZXMgYXJlIHVzZWQgdG8gY2hhbmdlIHRoZSBzbmFwc2hvdCBvZiB0aGUgcm91dGUuIE9uY2UgdGhlIHNuYXBzaG90IGhhcyBiZWVuIG1vZGlmaWVkLFxuICAgKiB0aGUgb2JzZXJ2YWJsZXMgY29ycmVzcG9uZGluZyB0byB0aGUgdXBkYXRlZCBwYXJ0cyBlbWl0IHRoZSBuZXcgdmFsdWUuXG4gICAqXG4gICAqIFNvLCBzZXR0aW5nIHBhcmFtcyBhbmQgcXVlcnkgcGFyYW1zIHdpbGwgbWFrZSB0aGUgcGFyYW1zIGFuZCBxdWVyeVBhcmFtcyBvYnNlcnZhYmxlcyBlbWl0LCBidXQgbm90IHRoZSBmcmFnbWVudCwgZGF0YSBhbmRcbiAgICogdXJsIG9ic2VydmFibGVzIGZvciBleGFtcGxlLiBUaGlzIGlzIGNvbnNpc3RlbnQgdG8gaG93IHRoZSByb3V0ZXIgYmVoYXZlcy5cbiAgICpcbiAgICogTm90ZTogc2luY2UgdGhlIHRpdGxlIG9mIGEgcm91dGUgY2FuIGJlY29tZSB1bmRlZmluZWQsIGluIG9yZGVyIHRvIGJlIGFibGUgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBhIG5hdmlnYXRpb24gd2hpY2ggbGVhdmVzIHRoZSB0aXRsZVxuICAgKiBhcyBpdCBpcyBhbmQgYSBuYXZpZ2F0aW9uIHRoYXQgc2V0cyB0aGUgdGl0bGUgdG8gdW5kZWZpbmVkLCBhIHdyYXBwZXIgb2JqZWN0IGlzIHVzZWQgZm9yIHRoZSB0aXRsZS4gU29cbiAgICpcbiAgICogLSBgdHJpZ2dlck5hdmlnYXRpb24oeyBwYXJhbXM6Li4uIH0pYCBsZWF2ZXMgdGhlIHRpdGxlIGFzIGlzIGJlY2F1c2UgaXQncyB1bmRlZmluZWQgaW4gdGhlIG9wdGlvbnNcbiAgICogLSBgdHJpZ2dlck5hdmlnYXRpb24oeyB0aXRsZTogeyB2YWx1ZTogJ3Rlc3QnIH0gfSlgIHNldHMgdGhlIHRpdGxlIHRvICd0ZXN0J1xuICAgKiAtIGB0cmlnZ2VyTmF2aWdhdGlvbih7IHRpdGxlOiB7IHZhbHVlOiB1bmRlZmluZWQgfSB9KWAgc2V0cyB0aGUgdGl0bGUgdG8gdW5kZWZpbmVkXG4gICAqL1xuICBwdWJsaWMgdHJpZ2dlck5hdmlnYXRpb24ob3B0aW9uczoge1xuICAgIHBhcmFtcz86IFBhcmFtcztcbiAgICBxdWVyeVBhcmFtcz86IFBhcmFtcztcbiAgICBmcmFnbWVudD86IHN0cmluZyB8IG51bGw7XG4gICAgZGF0YT86IERhdGEgfCBudWxsO1xuICAgIHRpdGxlPzogeyB2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkIH0gfCBudWxsO1xuICAgIHVybD86IEFycmF5PFVybFNlZ21lbnQ+IHwgbnVsbDtcbiAgfSk6IHZvaWQge1xuICAgIC8vIHNldCB0aGUgc25hcHNob3QgZmlyc3RcbiAgICBpZiAob3B0aW9ucy5wYXJhbXMpIHtcbiAgICAgIHRoaXMuc25hcHNob3QucGFyYW1zID0gb3B0aW9ucy5wYXJhbXM7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnF1ZXJ5UGFyYW1zKSB7XG4gICAgICB0aGlzLnNuYXBzaG90LnF1ZXJ5UGFyYW1zID0gb3B0aW9ucy5xdWVyeVBhcmFtcztcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuZnJhZ21lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5zbmFwc2hvdC5mcmFnbWVudCA9IG9wdGlvbnMuZnJhZ21lbnQ7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIHRoaXMuc25hcHNob3QuZGF0YSA9IG9wdGlvbnMuZGF0YTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMudGl0bGUpIHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgdGhlIHRpdGxlIGlzIHJlYWRvbmx5LCBidXQgd2UgbmVlZCB0byBiZSBhYmxlIHRvIG92ZXJ3cml0ZSBpdCBoZXJlXG4gICAgICB0aGlzLnNuYXBzaG90LnRpdGxlID0gb3B0aW9ucy50aXRsZS52YWx1ZTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMudXJsKSB7XG4gICAgICB0aGlzLnNuYXBzaG90LnVybCA9IG9wdGlvbnMudXJsO1xuICAgIH1cblxuICAgIC8vIHRoZW4gZW1pdCBldmVyeXRoaW5nIHRoYXQgaGFzIGNoYW5nZWRcbiAgICBpZiAob3B0aW9ucy5wYXJhbXMpIHtcbiAgICAgIHRoaXMucGFyYW1zU3ViamVjdC5uZXh0KHRoaXMuc25hcHNob3QucGFyYW1zKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMucXVlcnlQYXJhbXMpIHtcbiAgICAgIHRoaXMucXVlcnlQYXJhbXNTdWJqZWN0Lm5leHQodGhpcy5zbmFwc2hvdC5xdWVyeVBhcmFtcyk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmZyYWdtZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuZnJhZ21lbnRTdWJqZWN0Lm5leHQodGhpcy5zbmFwc2hvdC5mcmFnbWVudCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgIHRoaXMuZGF0YVN1YmplY3QubmV4dCh0aGlzLnNuYXBzaG90LmRhdGEpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy50aXRsZSkge1xuICAgICAgdGhpcy50aXRsZVN1YmplY3QubmV4dCh0aGlzLnNuYXBzaG90LnRpdGxlKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMudXJsKSB7XG4gICAgICB0aGlzLnVybFN1YmplY3QubmV4dCh0aGlzLnNuYXBzaG90LnVybCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdBY3RpdmF0ZWRSb3V0ZVN0dWInO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBBY3RpdmF0ZWRSb3V0ZVN0dWIsIGJ5IGNhbGxpbmcgaXRzIGNvbnN0cnVjdG9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3R1YlJvdXRlKG9wdGlvbnM/OiBBY3RpdmF0ZWRSb3V0ZVN0dWJPcHRpb25zKTogQWN0aXZhdGVkUm91dGVTdHViIHtcbiAgcmV0dXJuIG5ldyBBY3RpdmF0ZWRSb3V0ZVN0dWIob3B0aW9ucyk7XG59XG4iXX0=
|