velocious 1.0.643 → 1.0.645
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/README.md +21 -10
- package/build/authorization/ability.js +36 -13
- package/build/background-jobs/adapter.js +9 -0
- package/build/background-jobs/main.js +35 -10
- package/build/background-jobs/store.js +217 -38
- package/build/background-jobs/types.js +15 -0
- package/build/configuration-types.js +1 -1
- package/build/configuration.js +45 -9
- package/build/database/drivers/base-column.js +8 -0
- package/build/database/drivers/mssql/sql/update.js +1 -3
- package/build/database/drivers/mysql/sql/update.js +1 -3
- package/build/database/drivers/pgsql/column.js +22 -0
- package/build/database/drivers/pgsql/sql/update.js +1 -3
- package/build/database/drivers/sqlite/sql/alter-table.js +11 -1
- package/build/database/drivers/sqlite/sql/update.js +1 -3
- package/build/database/query/index.js +2 -2
- package/build/database/query/model-class-query.js +26 -10
- package/build/database/query/preloader/has-many.js +4 -1
- package/build/database/query/query-data.js +2 -1
- package/build/database/query/update-base.js +14 -0
- package/build/database/query/with-count.js +3 -1
- package/build/database/record/acts-as-list.js +37 -13
- package/build/database/record/attachments/store.js +336 -26
- package/build/database/record/auditing.js +6 -3
- package/build/database/record/index.js +197 -42
- package/build/database/record/instance-relationships/belongs-to.js +2 -1
- package/build/database/record/validators/uniqueness.js +8 -5
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
- package/build/frontend-model-controller.js +136 -53
- package/build/frontend-model-resource/base-resource.js +87 -37
- package/build/frontend-model-resource/velocious-attachment-resource.js +98 -31
- package/build/frontend-models/base.js +307 -59
- package/build/frontend-models/preloader.js +6 -3
- package/build/frontend-models/query.js +15 -6
- package/build/frontend-models/resource-definition.js +21 -2
- package/build/frontend-models/use-destroyed-event.js +1 -1
- package/build/frontend-models/use-model-class-event.js +2 -2
- package/build/frontend-models/use-updated-event.js +1 -1
- package/build/frontend-models/websocket-channel.js +256 -93
- package/build/frontend-models/websocket-publishers.js +218 -18
- package/build/http-server/client/websocket-session.js +13 -1
- package/build/http-server/websocket-channel.js +15 -2
- package/build/src/authorization/ability.d.ts +9 -3
- package/build/src/authorization/ability.d.ts.map +1 -1
- package/build/src/authorization/ability.js +33 -14
- package/build/src/background-jobs/adapter.d.ts +6 -0
- package/build/src/background-jobs/adapter.d.ts.map +1 -1
- package/build/src/background-jobs/adapter.js +9 -1
- package/build/src/background-jobs/main.d.ts +6 -0
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +34 -11
- package/build/src/background-jobs/store.d.ts +66 -12
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +191 -35
- package/build/src/background-jobs/types.d.ts +55 -0
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +16 -1
- package/build/src/configuration-types.d.ts +3 -3
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +2 -2
- package/build/src/configuration.d.ts +18 -8
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +38 -7
- package/build/src/database/drivers/base-column.d.ts +5 -0
- package/build/src/database/drivers/base-column.d.ts.map +1 -1
- package/build/src/database/drivers/base-column.js +8 -1
- package/build/src/database/drivers/mssql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/sql/update.js +2 -4
- package/build/src/database/drivers/mysql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/sql/update.js +2 -4
- package/build/src/database/drivers/pgsql/column.d.ts +5 -0
- package/build/src/database/drivers/pgsql/column.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/column.js +19 -1
- package/build/src/database/drivers/pgsql/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/sql/update.js +2 -4
- package/build/src/database/drivers/sqlite/sql/alter-table.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/sql/alter-table.js +6 -2
- package/build/src/database/drivers/sqlite/sql/update.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/sql/update.js +2 -4
- package/build/src/database/query/index.d.ts +4 -4
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +3 -3
- package/build/src/database/query/model-class-query.d.ts +8 -2
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +25 -11
- package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-many.js +4 -2
- package/build/src/database/query/query-data.d.ts.map +1 -1
- package/build/src/database/query/query-data.js +3 -2
- package/build/src/database/query/update-base.d.ts +7 -0
- package/build/src/database/query/update-base.d.ts.map +1 -1
- package/build/src/database/query/update-base.js +13 -1
- package/build/src/database/query/with-count.d.ts.map +1 -1
- package/build/src/database/query/with-count.js +3 -2
- package/build/src/database/record/acts-as-list.d.ts.map +1 -1
- package/build/src/database/record/acts-as-list.js +35 -14
- package/build/src/database/record/attachments/store.d.ts +67 -0
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +301 -25
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +7 -4
- package/build/src/database/record/index.d.ts +78 -26
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +171 -42
- package/build/src/database/record/instance-relationships/belongs-to.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/belongs-to.js +3 -2
- package/build/src/database/record/validators/uniqueness.d.ts.map +1 -1
- package/build/src/database/record/validators/uniqueness.js +8 -6
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +4 -4
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -12
- package/build/src/frontend-model-controller.d.ts +29 -8
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +122 -51
- package/build/src/frontend-model-resource/base-resource.d.ts +51 -24
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +83 -37
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts +45 -26
- package/build/src/frontend-model-resource/velocious-attachment-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/velocious-attachment-resource.js +89 -31
- package/build/src/frontend-models/base.d.ts +53 -20
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +275 -59
- package/build/src/frontend-models/preloader.d.ts.map +1 -1
- package/build/src/frontend-models/preloader.js +6 -4
- package/build/src/frontend-models/query.d.ts +2 -2
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +14 -7
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +20 -3
- package/build/src/frontend-models/use-destroyed-event.d.ts +1 -1
- package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-destroyed-event.js +2 -2
- package/build/src/frontend-models/use-model-class-event.d.ts +2 -2
- package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-model-class-event.js +3 -3
- package/build/src/frontend-models/use-updated-event.d.ts +1 -1
- package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-updated-event.js +2 -2
- package/build/src/frontend-models/websocket-channel.d.ts +60 -41
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +225 -85
- package/build/src/frontend-models/websocket-publishers.d.ts +9 -0
- package/build/src/frontend-models/websocket-publishers.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-publishers.js +190 -19
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +11 -2
- package/build/src/http-server/websocket-channel.d.ts +20 -8
- package/build/src/http-server/websocket-channel.d.ts.map +1 -1
- package/build/src/http-server/websocket-channel.js +15 -3
- package/build/src/sync/assets/cache.d.ts +288 -0
- package/build/src/sync/assets/cache.d.ts.map +1 -0
- package/build/src/sync/assets/cache.js +883 -0
- package/build/src/sync/assets/types.d.ts +199 -0
- package/build/src/sync/assets/types.d.ts.map +1 -0
- package/build/src/sync/assets/types.js +56 -0
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +4 -3
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +3 -2
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +6 -5
- package/build/src/sync/sync-publisher.d.ts.map +1 -1
- package/build/src/sync/sync-publisher.js +4 -3
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts +2 -2
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +3 -3
- package/build/src/testing/test-profiler.d.ts +4 -4
- package/build/src/testing/test-profiler.d.ts.map +1 -1
- package/build/src/testing/test-profiler.js +3 -3
- package/build/src/testing/test-runner.d.ts +279 -117
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +503 -933
- package/build/src/testing/test.d.ts +11 -72
- package/build/src/testing/test.d.ts.map +1 -1
- package/build/src/testing/test.js +131 -284
- package/build/src/testing/velocious-attempt-executor.d.ts +54 -0
- package/build/src/testing/velocious-attempt-executor.d.ts.map +1 -0
- package/build/src/testing/velocious-attempt-executor.js +408 -0
- package/build/src/testing/velocious-runner-reporter.d.ts +67 -0
- package/build/src/testing/velocious-runner-reporter.d.ts.map +1 -0
- package/build/src/testing/velocious-runner-reporter.js +240 -0
- package/build/src/testing/velocious-suite-hook-executor.d.ts +19 -0
- package/build/src/testing/velocious-suite-hook-executor.d.ts.map +1 -0
- package/build/src/testing/velocious-suite-hook-executor.js +41 -0
- package/build/src/testing/velocious-test-arguments.d.ts +39 -0
- package/build/src/testing/velocious-test-arguments.d.ts.map +1 -0
- package/build/src/testing/velocious-test-arguments.js +55 -0
- package/build/src/utils/model-primary-key.d.ts +73 -0
- package/build/src/utils/model-primary-key.d.ts.map +1 -0
- package/build/src/utils/model-primary-key.js +144 -0
- package/build/src/utils/sha256-bytes-hex.d.ts +7 -0
- package/build/src/utils/sha256-bytes-hex.d.ts.map +1 -0
- package/build/src/utils/sha256-bytes-hex.js +117 -0
- package/build/src/utils/sha256-hex.d.ts +2 -4
- package/build/src/utils/sha256-hex.d.ts.map +1 -1
- package/build/src/utils/sha256-hex.js +6 -120
- package/build/sync/assets/cache.js +998 -0
- package/build/sync/assets/types.js +62 -0
- package/build/sync/sync-api-client.js +3 -2
- package/build/sync/sync-client.js +2 -1
- package/build/sync/sync-envelope-replay-service.js +5 -4
- package/build/sync/sync-publisher.js +3 -2
- package/build/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
- package/build/testing/test-profiler.js +2 -2
- package/build/testing/test-runner.js +496 -990
- package/build/testing/test.js +164 -306
- package/build/testing/velocious-attempt-executor.js +441 -0
- package/build/testing/velocious-runner-reporter.js +264 -0
- package/build/testing/velocious-suite-hook-executor.js +43 -0
- package/build/testing/velocious-test-arguments.js +64 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/utils/model-primary-key.js +171 -0
- package/build/utils/sha256-bytes-hex.js +132 -0
- package/build/utils/sha256-hex.js +7 -135
- package/package.json +5 -4
- package/src/authorization/ability.js +36 -13
- package/src/background-jobs/adapter.js +9 -0
- package/src/background-jobs/main.js +35 -10
- package/src/background-jobs/store.js +217 -38
- package/src/background-jobs/types.js +15 -0
- package/src/configuration-types.js +1 -1
- package/src/configuration.js +45 -9
- package/src/database/drivers/base-column.js +8 -0
- package/src/database/drivers/mssql/sql/update.js +1 -3
- package/src/database/drivers/mysql/sql/update.js +1 -3
- package/src/database/drivers/pgsql/column.js +22 -0
- package/src/database/drivers/pgsql/sql/update.js +1 -3
- package/src/database/drivers/sqlite/sql/alter-table.js +11 -1
- package/src/database/drivers/sqlite/sql/update.js +1 -3
- package/src/database/query/index.js +2 -2
- package/src/database/query/model-class-query.js +26 -10
- package/src/database/query/preloader/has-many.js +4 -1
- package/src/database/query/query-data.js +2 -1
- package/src/database/query/update-base.js +14 -0
- package/src/database/query/with-count.js +3 -1
- package/src/database/record/acts-as-list.js +37 -13
- package/src/database/record/attachments/store.js +336 -26
- package/src/database/record/auditing.js +6 -3
- package/src/database/record/index.js +197 -42
- package/src/database/record/instance-relationships/belongs-to.js +2 -1
- package/src/database/record/validators/uniqueness.js +8 -5
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +24 -8
- package/src/frontend-model-controller.js +136 -53
- package/src/frontend-model-resource/base-resource.js +87 -37
- package/src/frontend-model-resource/velocious-attachment-resource.js +98 -31
- package/src/frontend-models/base.js +307 -59
- package/src/frontend-models/preloader.js +6 -3
- package/src/frontend-models/query.js +15 -6
- package/src/frontend-models/resource-definition.js +21 -2
- package/src/frontend-models/use-destroyed-event.js +1 -1
- package/src/frontend-models/use-model-class-event.js +2 -2
- package/src/frontend-models/use-updated-event.js +1 -1
- package/src/frontend-models/websocket-channel.js +256 -93
- package/src/frontend-models/websocket-publishers.js +218 -18
- package/src/http-server/client/websocket-session.js +13 -1
- package/src/http-server/websocket-channel.js +15 -2
- package/src/sync/assets/cache.js +998 -0
- package/src/sync/assets/types.js +62 -0
- package/src/sync/sync-api-client.js +3 -2
- package/src/sync/sync-client.js +2 -1
- package/src/sync/sync-envelope-replay-service.js +5 -4
- package/src/sync/sync-publisher.js +3 -2
- package/src/testing/browser-frontend-model-event-hook-scenarios.js +2 -2
- package/src/testing/test-profiler.js +2 -2
- package/src/testing/test-runner.js +496 -990
- package/src/testing/test.js +164 -306
- package/src/testing/velocious-attempt-executor.js +441 -0
- package/src/testing/velocious-runner-reporter.js +264 -0
- package/src/testing/velocious-suite-hook-executor.js +43 -0
- package/src/testing/velocious-test-arguments.js +64 -0
- package/src/utils/model-primary-key.js +171 -0
- package/src/utils/sha256-bytes-hex.js +132 -0
- package/src/utils/sha256-hex.js +7 -135
- package/build/src/testing/testing-package-adapter.d.ts +0 -9
- package/build/src/testing/testing-package-adapter.d.ts.map +0 -1
- package/build/src/testing/testing-package-adapter.js +0 -69
- package/build/testing/testing-package-adapter.js +0 -76
- package/src/testing/testing-package-adapter.js +0 -76
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { TestDatabaseAccessRevokedError } from "../environment-handlers/base.js";
|
|
3
|
+
import { clearDeliveries } from "../mailer.js";
|
|
4
|
+
import restArgsError from "../utils/rest-args-error.js";
|
|
5
|
+
import { clearTimeout as realClearTimeout, setTimeout as realSetTimeout } from "node:timers";
|
|
6
|
+
/** @typedef {import("@velocious/testing/runner").AttemptExecutorInput["beforeEach"][number]} PackageHookDeclaration */
|
|
7
|
+
/**
|
|
8
|
+
* Marks one whole-lifecycle timeout while its underlying promise keeps running.
|
|
9
|
+
* @typedef {Error & {velociousTestTimeout?: true}} TestTimeoutError
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Runs one promise with a lifecycle timeout.
|
|
13
|
+
* @param {Promise<ReturnType<typeof JSON.parse>> | ReturnType<typeof JSON.parse>} promise - Promise or value.
|
|
14
|
+
* @param {number} timeoutMs - Timeout in milliseconds.
|
|
15
|
+
* @param {string} testDescription - Test description.
|
|
16
|
+
* @returns {Promise<ReturnType<typeof JSON.parse>>} - Lifecycle result.
|
|
17
|
+
*/
|
|
18
|
+
function runWithTimeout(promise, timeoutMs, testDescription) {
|
|
19
|
+
const timeoutSeconds = (timeoutMs / 1000).toFixed(3).replace(/\.?0+$/, "");
|
|
20
|
+
/** @type {TestTimeoutError} */
|
|
21
|
+
const timeoutError = new Error(`Timed out after ${timeoutSeconds}s: ${testDescription}`);
|
|
22
|
+
timeoutError.velociousTestTimeout = true;
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const timeout = realSetTimeout(() => reject(timeoutError), timeoutMs);
|
|
25
|
+
Promise.resolve(promise).then((result) => {
|
|
26
|
+
realClearTimeout(timeout);
|
|
27
|
+
resolve(result);
|
|
28
|
+
}).catch((error) => {
|
|
29
|
+
realClearTimeout(timeout);
|
|
30
|
+
reject(error);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Waits for detached lifecycle cleanup up to the timeout grace period.
|
|
36
|
+
* @param {Promise<ReturnType<typeof JSON.parse>>} lifecycle - Detached lifecycle promise.
|
|
37
|
+
* @param {number} graceMs - Maximum wait.
|
|
38
|
+
* @returns {Promise<{settled: false} | {settled: true, status: "fulfilled"} | {settled: true, status: "rejected", reason: ReturnType<typeof JSON.parse>}>} - Settlement outcome.
|
|
39
|
+
*/
|
|
40
|
+
function awaitSettledOrGrace(lifecycle, graceMs) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
let settled = false;
|
|
43
|
+
const graceTimer = realSetTimeout(() => {
|
|
44
|
+
if (settled)
|
|
45
|
+
return;
|
|
46
|
+
settled = true;
|
|
47
|
+
resolve({ settled: false });
|
|
48
|
+
}, graceMs);
|
|
49
|
+
Promise.resolve(lifecycle).then(() => {
|
|
50
|
+
if (settled)
|
|
51
|
+
return;
|
|
52
|
+
settled = true;
|
|
53
|
+
realClearTimeout(graceTimer);
|
|
54
|
+
resolve({ settled: true, status: "fulfilled" });
|
|
55
|
+
}, (reason) => {
|
|
56
|
+
if (settled)
|
|
57
|
+
return;
|
|
58
|
+
settled = true;
|
|
59
|
+
realClearTimeout(graceTimer);
|
|
60
|
+
resolve({ settled: true, status: "rejected", reason });
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Checks whether a late lifecycle stopped only because its attempt access was revoked.
|
|
66
|
+
* @param {ReturnType<typeof JSON.parse>} error - Lifecycle rejection.
|
|
67
|
+
* @returns {boolean} - Whether every contained error is expected revocation.
|
|
68
|
+
*/
|
|
69
|
+
function isTestDatabaseAccessRevocation(error) {
|
|
70
|
+
if (error instanceof TestDatabaseAccessRevokedError)
|
|
71
|
+
return true;
|
|
72
|
+
if (error instanceof AggregateError) {
|
|
73
|
+
return error.errors.length > 0 && error.errors.every((nestedError) => isTestDatabaseAccessRevocation(nestedError));
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
export default class VelociousAttemptExecutor {
|
|
78
|
+
/**
|
|
79
|
+
* Creates an executor for framework-owned attempt lifecycle work.
|
|
80
|
+
* @param {object} args - Constructor arguments.
|
|
81
|
+
* @param {import("./test-runner.js").default} args.testRunner - Owning Velocious runner.
|
|
82
|
+
*/
|
|
83
|
+
constructor({ testRunner, ...restArgs }) {
|
|
84
|
+
restArgsError(restArgs);
|
|
85
|
+
this.testRunner = testRunner;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Normalizes the legacy timeout contract at the framework adapter boundary.
|
|
89
|
+
* @param {number | undefined} timeoutMs - Declared package timeout.
|
|
90
|
+
* @returns {number | undefined} - Positive finite timeout, or no timeout.
|
|
91
|
+
*/
|
|
92
|
+
normalizeTimeoutMs(timeoutMs) {
|
|
93
|
+
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Executes exactly one complete Velocious-owned test attempt.
|
|
97
|
+
* @param {import("@velocious/testing/runner").AttemptExecutorInput} input - Package attempt.
|
|
98
|
+
* @returns {Promise<void>} - Resolves after one complete framework attempt.
|
|
99
|
+
*/
|
|
100
|
+
async execute({ afterEach, args, attemptNumber, beforeEach, context, defaultExecute, fullName, suite, test, timeoutMs, ...restArgs }) {
|
|
101
|
+
restArgsError(restArgs);
|
|
102
|
+
void context;
|
|
103
|
+
void defaultExecute;
|
|
104
|
+
void suite;
|
|
105
|
+
const testRunner = this.testRunner;
|
|
106
|
+
const effectiveTimeoutMs = this.normalizeTimeoutMs(timeoutMs);
|
|
107
|
+
const compatibility = await testRunner.testCompatibility(test);
|
|
108
|
+
const { testArgs, testData } = compatibility;
|
|
109
|
+
const metadata = testRunner.testMetadata(test);
|
|
110
|
+
const { descriptions, testDescription } = metadata;
|
|
111
|
+
/** @type {ReturnType<typeof JSON.parse>} */
|
|
112
|
+
let caughtError;
|
|
113
|
+
let failed = false;
|
|
114
|
+
/** @type {Promise<ReturnType<typeof JSON.parse>> | undefined} */
|
|
115
|
+
let testLifecycle;
|
|
116
|
+
/** @type {{pool: import("../database/pool/base.js").default, registration: import("../database/pool/base.js").TestSharedConnectionRegistration}[]} */
|
|
117
|
+
let testSharedConnectionRegistrations = [];
|
|
118
|
+
let testSharedConnectionsActive = false;
|
|
119
|
+
/** @type {import("./test-runner.js").SharedTransactionBrokerRegistration | undefined} */
|
|
120
|
+
let sharedTransactionBrokerRegistration;
|
|
121
|
+
/** @type {import("./test-runner.js").SharedTransactionBrokerRegistration | undefined} */
|
|
122
|
+
let sharedTransactionBrokerPreparation;
|
|
123
|
+
/** @type {import("./test-runner.js").TransactionalTenantRegistration[]} */
|
|
124
|
+
const transactionalTenantRegistrations = [];
|
|
125
|
+
/** @type {import("./test-runner.js").BrowserDummyConnectionRegistration[]} */
|
|
126
|
+
const browserDummyConnectionRegistrations = [];
|
|
127
|
+
const testDatabaseAccessScope = { revoked: false };
|
|
128
|
+
/** @type {Set<Error>} */
|
|
129
|
+
const recordedTimeoutCleanupErrors = new Set();
|
|
130
|
+
let abortRemainingTests = false;
|
|
131
|
+
let attemptTimedOut = false;
|
|
132
|
+
testArgs.registerTransactionalTenant = async (args) => {
|
|
133
|
+
await testRunner.registerTransactionalTenant(args, transactionalTenantRegistrations);
|
|
134
|
+
};
|
|
135
|
+
const profiler = testRunner._profiler;
|
|
136
|
+
const profileAttempt = profiler?.startAttempt({
|
|
137
|
+
descriptions,
|
|
138
|
+
attemptNumber,
|
|
139
|
+
testData,
|
|
140
|
+
testDescription
|
|
141
|
+
});
|
|
142
|
+
try {
|
|
143
|
+
const runLifecycleCallback = async () => await testRunner.runWithDummyIfNeeded(testArgs, async () => {
|
|
144
|
+
const useTransaction = testArgs.databaseCleaning?.transaction === true;
|
|
145
|
+
const shouldTruncate = testArgs.databaseCleaning?.truncate ?? !useTransaction;
|
|
146
|
+
const useSharedTestConnections = useTransaction || testArgs.type == "request";
|
|
147
|
+
const useTestConnections = useSharedTestConnections || shouldTruncate;
|
|
148
|
+
const runTestAttempt = async () => {
|
|
149
|
+
if (useSharedTestConnections) {
|
|
150
|
+
testSharedConnectionRegistrations = testRunner.activateTestSharedConnections();
|
|
151
|
+
testSharedConnectionsActive = true;
|
|
152
|
+
}
|
|
153
|
+
/** @type {ReturnType<typeof JSON.parse>[]} */
|
|
154
|
+
const lifecycleErrors = [];
|
|
155
|
+
let runCleanupHooks = false;
|
|
156
|
+
try {
|
|
157
|
+
if (useSharedTestConnections) {
|
|
158
|
+
sharedTransactionBrokerPreparation = await testRunner.prepareSharedTransactionBroker();
|
|
159
|
+
}
|
|
160
|
+
runCleanupHooks = true;
|
|
161
|
+
clearDeliveries();
|
|
162
|
+
await this.runBeforeEaches({ beforeEaches: beforeEach, testArgs, testData });
|
|
163
|
+
if (useSharedTestConnections) {
|
|
164
|
+
const activeConnections = testRunner.sharedTransactionConnections({ transactionsOnly: true });
|
|
165
|
+
if (sharedTransactionBrokerPreparation && !testRunner.sharedTransactionBrokerMatchesConnections(sharedTransactionBrokerPreparation, activeConnections)) {
|
|
166
|
+
testRunner.clearTestSharedConnections(testSharedConnectionRegistrations);
|
|
167
|
+
testSharedConnectionRegistrations = [];
|
|
168
|
+
testSharedConnectionsActive = false;
|
|
169
|
+
}
|
|
170
|
+
sharedTransactionBrokerRegistration = await testRunner.startSharedTransactionBroker(sharedTransactionBrokerPreparation, activeConnections);
|
|
171
|
+
sharedTransactionBrokerPreparation = undefined;
|
|
172
|
+
if (sharedTransactionBrokerRegistration && !testSharedConnectionsActive) {
|
|
173
|
+
testSharedConnectionRegistrations = testRunner.activateTestSharedConnections();
|
|
174
|
+
testSharedConnectionsActive = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
testRunner._lastTestContext = {
|
|
178
|
+
fullDescription: fullName,
|
|
179
|
+
filePath: testData.filePath ?? "<unknown>",
|
|
180
|
+
line: testData.line ?? 0
|
|
181
|
+
};
|
|
182
|
+
await testRunner.runProfileSpan({ phase: "test body", filePath: testData.ownerFilePath ?? testData.filePath }, async () => {
|
|
183
|
+
await test.callback(...args);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
lifecycleErrors.push(error);
|
|
188
|
+
}
|
|
189
|
+
if (runCleanupHooks) {
|
|
190
|
+
try {
|
|
191
|
+
await testRunner.getConfiguration().awaitPendingBroadcasts();
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
lifecycleErrors.push(error);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
if (testSharedConnectionsActive) {
|
|
198
|
+
testRunner.clearTestSharedConnections(testSharedConnectionRegistrations);
|
|
199
|
+
testSharedConnectionRegistrations = [];
|
|
200
|
+
testSharedConnectionsActive = false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
lifecycleErrors.push(error);
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
await testRunner.stopSharedTransactionBroker(sharedTransactionBrokerRegistration || sharedTransactionBrokerPreparation);
|
|
208
|
+
sharedTransactionBrokerRegistration = undefined;
|
|
209
|
+
sharedTransactionBrokerPreparation = undefined;
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
lifecycleErrors.push(error);
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
await this.runAfterEaches({ afterEaches: [...afterEach].reverse(), testArgs, testData });
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
lifecycleErrors.push(error);
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
await testRunner.cleanupTransactionalTenants(transactionalTenantRegistrations);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
lifecycleErrors.push(error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (testSharedConnectionsActive) {
|
|
228
|
+
try {
|
|
229
|
+
testRunner.clearTestSharedConnections(testSharedConnectionRegistrations);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
lifecycleErrors.push(error);
|
|
233
|
+
}
|
|
234
|
+
testSharedConnectionsActive = false;
|
|
235
|
+
}
|
|
236
|
+
if (lifecycleErrors.length == 1)
|
|
237
|
+
throw lifecycleErrors[0];
|
|
238
|
+
if (lifecycleErrors.length > 1) {
|
|
239
|
+
throw new AggregateError(lifecycleErrors, "Test lifecycle and cleanup failed", { cause: lifecycleErrors[0] });
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
if (useTestConnections) {
|
|
243
|
+
await testRunner.getConfiguration().ensureConnections({ name: `Test: ${testDescription}` }, runTestAttempt);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
await runTestAttempt();
|
|
247
|
+
}
|
|
248
|
+
}, browserDummyConnectionRegistrations);
|
|
249
|
+
const lifecycleCallback = async () => await testRunner.getConfiguration().runWithTestDatabaseAccessScope(testDatabaseAccessScope, runLifecycleCallback);
|
|
250
|
+
testLifecycle = profileAttempt && profiler
|
|
251
|
+
? profiler.runAttempt(profileAttempt, lifecycleCallback)
|
|
252
|
+
: lifecycleCallback();
|
|
253
|
+
if (effectiveTimeoutMs !== undefined) {
|
|
254
|
+
await runWithTimeout(testLifecycle, effectiveTimeoutMs, testDescription);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
await testLifecycle;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
failed = true;
|
|
262
|
+
caughtError = error;
|
|
263
|
+
const timedOut = Boolean(/** @type {TestTimeoutError} */ (error)?.velociousTestTimeout);
|
|
264
|
+
attemptTimedOut = timedOut;
|
|
265
|
+
if (timedOut && testLifecycle) {
|
|
266
|
+
const emergencyCleanupErrors = [];
|
|
267
|
+
if (profileAttempt && profiler)
|
|
268
|
+
profiler.finishAttempt(profileAttempt, "timed-out");
|
|
269
|
+
const lifecycleOutcome = await awaitSettledOrGrace(testLifecycle, effectiveTimeoutMs ?? 60000);
|
|
270
|
+
if (lifecycleOutcome.settled && lifecycleOutcome.status === "rejected") {
|
|
271
|
+
emergencyCleanupErrors.push(lifecycleOutcome.reason);
|
|
272
|
+
}
|
|
273
|
+
if (!lifecycleOutcome.settled) {
|
|
274
|
+
testDatabaseAccessScope.revoked = true;
|
|
275
|
+
void testLifecycle.catch((cleanupError) => {
|
|
276
|
+
if (isTestDatabaseAccessRevocation(cleanupError))
|
|
277
|
+
return;
|
|
278
|
+
testRunner.recordTimeoutCleanupFailure(cleanupError, "test lifecycle", recordedTimeoutCleanupErrors);
|
|
279
|
+
});
|
|
280
|
+
const quarantine = testRunner.quarantineBrowserDummyConnections(browserDummyConnectionRegistrations);
|
|
281
|
+
const quarantineOutcome = await awaitSettledOrGrace(quarantine, effectiveTimeoutMs ?? 60000);
|
|
282
|
+
const usesBrowserTransactions = testArgs.databaseCleaning?.transaction === true;
|
|
283
|
+
const usesBrowserTruncation = testArgs.databaseCleaning?.truncate ?? !usesBrowserTransactions;
|
|
284
|
+
abortRemainingTests = testRunner.isBrowserTestMode()
|
|
285
|
+
&& testRunner.hasTag(testArgs, "dummy")
|
|
286
|
+
&& (usesBrowserTransactions || usesBrowserTruncation);
|
|
287
|
+
if (quarantineOutcome.settled && quarantineOutcome.status === "rejected") {
|
|
288
|
+
emergencyCleanupErrors.push(quarantineOutcome.reason);
|
|
289
|
+
}
|
|
290
|
+
else if (!quarantineOutcome.settled) {
|
|
291
|
+
void quarantine.catch((cleanupError) => {
|
|
292
|
+
testRunner.recordTimeoutCleanupFailure(cleanupError, "browser dummy connection quarantine", recordedTimeoutCleanupErrors);
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
if (testSharedConnectionsActive) {
|
|
298
|
+
testRunner.clearTestSharedConnections(testSharedConnectionRegistrations);
|
|
299
|
+
testSharedConnectionRegistrations = [];
|
|
300
|
+
testSharedConnectionsActive = false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (cleanupError) {
|
|
304
|
+
emergencyCleanupErrors.push(cleanupError);
|
|
305
|
+
}
|
|
306
|
+
const brokerCleanup = testRunner.stopSharedTransactionBroker(sharedTransactionBrokerRegistration || sharedTransactionBrokerPreparation);
|
|
307
|
+
const brokerCleanupOutcome = await awaitSettledOrGrace(brokerCleanup, effectiveTimeoutMs ?? 60000);
|
|
308
|
+
if (brokerCleanupOutcome.settled && brokerCleanupOutcome.status === "rejected") {
|
|
309
|
+
emergencyCleanupErrors.push(brokerCleanupOutcome.reason);
|
|
310
|
+
}
|
|
311
|
+
else if (!brokerCleanupOutcome.settled) {
|
|
312
|
+
void brokerCleanup.catch((cleanupError) => {
|
|
313
|
+
testRunner.recordTimeoutCleanupFailure(cleanupError, "shared transaction broker", recordedTimeoutCleanupErrors);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
sharedTransactionBrokerRegistration = undefined;
|
|
317
|
+
sharedTransactionBrokerPreparation = undefined;
|
|
318
|
+
const emergencyCleanup = testRunner.cleanupTransactionalTenants(transactionalTenantRegistrations, { discard: true });
|
|
319
|
+
const emergencyCleanupOutcome = await awaitSettledOrGrace(emergencyCleanup, effectiveTimeoutMs ?? 60000);
|
|
320
|
+
if (emergencyCleanupOutcome.settled && emergencyCleanupOutcome.status === "rejected") {
|
|
321
|
+
emergencyCleanupErrors.push(emergencyCleanupOutcome.reason);
|
|
322
|
+
}
|
|
323
|
+
else if (!emergencyCleanupOutcome.settled) {
|
|
324
|
+
void emergencyCleanup.catch((cleanupError) => {
|
|
325
|
+
testRunner.recordTimeoutCleanupFailure(cleanupError, "transactional tenant", recordedTimeoutCleanupErrors);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (emergencyCleanupErrors.length > 0) {
|
|
329
|
+
caughtError = new AggregateError([caughtError, ...emergencyCleanupErrors], "Test timeout and emergency cleanup failed", { cause: caughtError });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (browserDummyConnectionRegistrations.some((registration) => registration.quarantined)) {
|
|
333
|
+
testDatabaseAccessScope.revoked = true;
|
|
334
|
+
abortRemainingTests = true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
finally {
|
|
338
|
+
testDatabaseAccessScope.revoked = true;
|
|
339
|
+
if (profileAttempt && profiler) {
|
|
340
|
+
profiler.finishAttempt(profileAttempt, failed
|
|
341
|
+
? (attemptTimedOut ? "timed-out" : "failed")
|
|
342
|
+
: "passed");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
testRunner.recordAttemptOutcome(test, attemptNumber, {
|
|
346
|
+
abortRemainingTests,
|
|
347
|
+
error: caughtError,
|
|
348
|
+
failed
|
|
349
|
+
});
|
|
350
|
+
if (failed)
|
|
351
|
+
throw caughtError;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Runs before-each hooks in inherited declaration order.
|
|
355
|
+
* @param {object} args - Hook arguments.
|
|
356
|
+
* @param {PackageHookDeclaration[]} args.beforeEaches - Setup hooks.
|
|
357
|
+
* @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
|
|
358
|
+
* @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
|
|
359
|
+
* @returns {Promise<void>} - Resolves after all setup hooks complete.
|
|
360
|
+
*/
|
|
361
|
+
async runBeforeEaches({ beforeEaches, testArgs, testData }) {
|
|
362
|
+
for (const hook of beforeEaches) {
|
|
363
|
+
const metadata = this.testRunner.hookMetadata(hook);
|
|
364
|
+
await this.testRunner.runProfileSpan({
|
|
365
|
+
phase: "beforeEach",
|
|
366
|
+
declarationIndex: metadata.declarationIndex,
|
|
367
|
+
declarationScopeId: metadata.declarationScopeId,
|
|
368
|
+
filePath: metadata.ownerFilePath
|
|
369
|
+
}, async () => {
|
|
370
|
+
await hook.callback({ configuration: this.testRunner.getConfiguration(), testArgs, testData });
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Runs every after-each hook while preserving all failures.
|
|
376
|
+
* @param {object} args - Hook arguments.
|
|
377
|
+
* @param {PackageHookDeclaration[]} args.afterEaches - Cleanup hooks.
|
|
378
|
+
* @param {import("./velocious-test-arguments.js").TestArgs} args.testArgs - Stable test arguments.
|
|
379
|
+
* @param {import("./velocious-test-arguments.js").TestData} args.testData - Test registration.
|
|
380
|
+
* @returns {Promise<void>} - Resolves after every cleanup hook settles.
|
|
381
|
+
*/
|
|
382
|
+
async runAfterEaches({ afterEaches, testArgs, testData }) {
|
|
383
|
+
/** @type {ReturnType<typeof JSON.parse>[]} */
|
|
384
|
+
const errors = [];
|
|
385
|
+
for (const hook of afterEaches) {
|
|
386
|
+
const metadata = this.testRunner.hookMetadata(hook);
|
|
387
|
+
try {
|
|
388
|
+
await this.testRunner.runProfileSpan({
|
|
389
|
+
phase: "afterEach",
|
|
390
|
+
declarationIndex: metadata.declarationIndex,
|
|
391
|
+
declarationScopeId: metadata.declarationScopeId,
|
|
392
|
+
filePath: metadata.ownerFilePath
|
|
393
|
+
}, async () => {
|
|
394
|
+
await hook.callback({ configuration: this.testRunner.getConfiguration(), testArgs, testData });
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
errors.push(error);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (errors.length == 1)
|
|
402
|
+
throw errors[0];
|
|
403
|
+
if (errors.length > 1) {
|
|
404
|
+
throw new AggregateError(errors, "Multiple afterEach hooks failed", { cause: errors[0] });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVsb2Npb3VzLWF0dGVtcHQtZXhlY3V0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdGluZy92ZWxvY2lvdXMtYXR0ZW1wdC1leGVjdXRvci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0saUNBQWlDLENBQUE7QUFDaEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQTtBQUM5QyxPQUFPLGFBQWEsTUFBTSw2QkFBNkIsQ0FBQTtBQUN2RCxPQUFPLEVBQUMsWUFBWSxJQUFJLGdCQUFnQixFQUFFLFVBQVUsSUFBSSxjQUFjLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFFMUYsdUhBQXVIO0FBRXZIOzs7R0FHRztBQUVIOzs7Ozs7R0FNRztBQUNILFNBQVMsY0FBYyxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZTtJQUN6RCxNQUFNLGNBQWMsR0FBRyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUMxRSwrQkFBK0I7SUFDL0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxLQUFLLENBQUMsbUJBQW1CLGNBQWMsTUFBTSxlQUFlLEVBQUUsQ0FBQyxDQUFBO0lBQ3hGLFlBQVksQ0FBQyxvQkFBb0IsR0FBRyxJQUFJLENBQUE7SUFFeEMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNyQyxNQUFNLE9BQU8sR0FBRyxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBRXJFLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDdkMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUE7WUFDekIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ2pCLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2pCLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQ3pCLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUNmLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxPQUFPO0lBQzdDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUM3QixJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUE7UUFDbkIsTUFBTSxVQUFVLEdBQUcsY0FBYyxDQUFDLEdBQUcsRUFBRTtZQUNyQyxJQUFJLE9BQU87Z0JBQUUsT0FBTTtZQUVuQixPQUFPLEdBQUcsSUFBSSxDQUFBO1lBQ2QsT0FBTyxDQUFDLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7UUFDM0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBRVgsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQzdCLEdBQUcsRUFBRTtZQUNILElBQUksT0FBTztnQkFBRSxPQUFNO1lBRW5CLE9BQU8sR0FBRyxJQUFJLENBQUE7WUFDZCxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUM1QixPQUFPLENBQUMsRUFBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUMsQ0FBQyxDQUFBO1FBQy9DLENBQUMsRUFDRCxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ1QsSUFBSSxPQUFPO2dCQUFFLE9BQU07WUFFbkIsT0FBTyxHQUFHLElBQUksQ0FBQTtZQUNkLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFBO1lBQzVCLE9BQU8sQ0FBQyxFQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUMsQ0FBQyxDQUFBO1FBQ3RELENBQUMsQ0FDRixDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsOEJBQThCLENBQUMsS0FBSztJQUMzQyxJQUFJLEtBQUssWUFBWSw4QkFBOEI7UUFBRSxPQUFPLElBQUksQ0FBQTtJQUNoRSxJQUFJLEtBQUssWUFBWSxjQUFjLEVBQUUsQ0FBQztRQUNwQyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsOEJBQThCLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQTtJQUNwSCxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUE7QUFDZCxDQUFDO0FBRUQsTUFBTSxDQUFDLE9BQU8sT0FBTyx3QkFBd0I7SUFDM0M7Ozs7T0FJRztJQUNILFlBQVksRUFBQyxVQUFVLEVBQUUsR0FBRyxRQUFRLEVBQUM7UUFDbkMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO0lBQzlCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsU0FBUztRQUMxQixPQUFPLE9BQU8sU0FBUyxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO0lBQzdHLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLFFBQVEsRUFBQztRQUNoSSxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDdkIsS0FBSyxPQUFPLENBQUE7UUFDWixLQUFLLGNBQWMsQ0FBQTtRQUNuQixLQUFLLEtBQUssQ0FBQTtRQUNWLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUE7UUFDbEMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDN0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxVQUFVLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDOUQsTUFBTSxFQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUMsR0FBRyxhQUFhLENBQUE7UUFDMUMsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUM5QyxNQUFNLEVBQUMsWUFBWSxFQUFFLGVBQWUsRUFBQyxHQUFHLFFBQVEsQ0FBQTtRQUNoRCw0Q0FBNEM7UUFDNUMsSUFBSSxXQUFXLENBQUE7UUFDZixJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUE7UUFDbEIsaUVBQWlFO1FBQ2pFLElBQUksYUFBYSxDQUFBO1FBQ2pCLHNKQUFzSjtRQUN0SixJQUFJLGlDQUFpQyxHQUFHLEVBQUUsQ0FBQTtRQUMxQyxJQUFJLDJCQUEyQixHQUFHLEtBQUssQ0FBQTtRQUN2Qyx5RkFBeUY7UUFDekYsSUFBSSxtQ0FBbUMsQ0FBQTtRQUN2Qyx5RkFBeUY7UUFDekYsSUFBSSxrQ0FBa0MsQ0FBQTtRQUN0QywyRUFBMkU7UUFDM0UsTUFBTSxnQ0FBZ0MsR0FBRyxFQUFFLENBQUE7UUFDM0MsOEVBQThFO1FBQzlFLE1BQU0sbUNBQW1DLEdBQUcsRUFBRSxDQUFBO1FBQzlDLE1BQU0sdUJBQXVCLEdBQUcsRUFBQyxPQUFPLEVBQUUsS0FBSyxFQUFDLENBQUE7UUFDaEQseUJBQXlCO1FBQ3pCLE1BQU0sNEJBQTRCLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUM5QyxJQUFJLG1CQUFtQixHQUFHLEtBQUssQ0FBQTtRQUMvQixJQUFJLGVBQWUsR0FBRyxLQUFLLENBQUE7UUFDM0IsUUFBUSxDQUFDLDJCQUEyQixHQUFHLEtBQUssRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUNwRCxNQUFNLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLEVBQUUsZ0NBQWdDLENBQUMsQ0FBQTtRQUN0RixDQUFDLENBQUE7UUFDRCxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFBO1FBQ3JDLE1BQU0sY0FBYyxHQUFHLFFBQVEsRUFBRSxZQUFZLENBQUM7WUFDNUMsWUFBWTtZQUNaLGFBQWE7WUFDYixRQUFRO1lBQ1IsZUFBZTtTQUNoQixDQUFDLENBQUE7UUFFRixJQUFJLENBQUM7WUFDSCxNQUFNLG9CQUFvQixHQUFHLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxVQUFVLENBQUMsb0JBQW9CLENBQUMsUUFBUSxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNsRyxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxLQUFLLElBQUksQ0FBQTtnQkFDdEUsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsSUFBSSxDQUFDLGNBQWMsQ0FBQTtnQkFDN0UsTUFBTSx3QkFBd0IsR0FBRyxjQUFjLElBQUksUUFBUSxDQUFDLElBQUksSUFBSSxTQUFTLENBQUE7Z0JBQzdFLE1BQU0sa0JBQWtCLEdBQUcsd0JBQXdCLElBQUksY0FBYyxDQUFBO2dCQUNyRSxNQUFNLGNBQWMsR0FBRyxLQUFLLElBQUksRUFBRTtvQkFDaEMsSUFBSSx3QkFBd0IsRUFBRSxDQUFDO3dCQUM3QixpQ0FBaUMsR0FBRyxVQUFVLENBQUMsNkJBQTZCLEVBQUUsQ0FBQTt3QkFDOUUsMkJBQTJCLEdBQUcsSUFBSSxDQUFBO29CQUNwQyxDQUFDO29CQUNELDhDQUE4QztvQkFDOUMsTUFBTSxlQUFlLEdBQUcsRUFBRSxDQUFBO29CQUMxQixJQUFJLGVBQWUsR0FBRyxLQUFLLENBQUE7b0JBRTNCLElBQUksQ0FBQzt3QkFDSCxJQUFJLHdCQUF3QixFQUFFLENBQUM7NEJBQzdCLGtDQUFrQyxHQUFHLE1BQU0sVUFBVSxDQUFDLDhCQUE4QixFQUFFLENBQUE7d0JBQ3hGLENBQUM7d0JBQ0QsZUFBZSxHQUFHLElBQUksQ0FBQTt3QkFFdEIsZUFBZSxFQUFFLENBQUE7d0JBQ2pCLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFDLFlBQVksRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQUE7d0JBRTFFLElBQUksd0JBQXdCLEVBQUUsQ0FBQzs0QkFDN0IsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsNEJBQTRCLENBQUMsRUFBQyxnQkFBZ0IsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFBOzRCQUMzRixJQUFJLGtDQUFrQyxJQUFJLENBQUMsVUFBVSxDQUFDLHlDQUF5QyxDQUFDLGtDQUFrQyxFQUFFLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztnQ0FDdkosVUFBVSxDQUFDLDBCQUEwQixDQUFDLGlDQUFpQyxDQUFDLENBQUE7Z0NBQ3hFLGlDQUFpQyxHQUFHLEVBQUUsQ0FBQTtnQ0FDdEMsMkJBQTJCLEdBQUcsS0FBSyxDQUFBOzRCQUNyQyxDQUFDOzRCQUVELG1DQUFtQyxHQUFHLE1BQU0sVUFBVSxDQUFDLDRCQUE0QixDQUFDLGtDQUFrQyxFQUFFLGlCQUFpQixDQUFDLENBQUE7NEJBQzFJLGtDQUFrQyxHQUFHLFNBQVMsQ0FBQTs0QkFDOUMsSUFBSSxtQ0FBbUMsSUFBSSxDQUFDLDJCQUEyQixFQUFFLENBQUM7Z0NBQ3hFLGlDQUFpQyxHQUFHLFVBQVUsQ0FBQyw2QkFBNkIsRUFBRSxDQUFBO2dDQUM5RSwyQkFBMkIsR0FBRyxJQUFJLENBQUE7NEJBQ3BDLENBQUM7d0JBQ0gsQ0FBQzt3QkFFRCxVQUFVLENBQUMsZ0JBQWdCLEdBQUc7NEJBQzVCLGVBQWUsRUFBRSxRQUFROzRCQUN6QixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVEsSUFBSSxXQUFXOzRCQUMxQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDO3lCQUN6QixDQUFBO3dCQUNELE1BQU0sVUFBVSxDQUFDLGNBQWMsQ0FBQyxFQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxhQUFhLElBQUksUUFBUSxDQUFDLFFBQVEsRUFBQyxFQUFFLEtBQUssSUFBSSxFQUFFOzRCQUN0SCxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQTt3QkFDOUIsQ0FBQyxDQUFDLENBQUE7b0JBQ0osQ0FBQztvQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO3dCQUNmLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7b0JBQzdCLENBQUM7b0JBRUQsSUFBSSxlQUFlLEVBQUUsQ0FBQzt3QkFDcEIsSUFBSSxDQUFDOzRCQUNILE1BQU0sVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUMsc0JBQXNCLEVBQUUsQ0FBQTt3QkFDOUQsQ0FBQzt3QkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDOzRCQUNmLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7d0JBQzdCLENBQUM7d0JBRUQsSUFBSSxDQUFDOzRCQUNILElBQUksMkJBQTJCLEVBQUUsQ0FBQztnQ0FDaEMsVUFBVSxDQUFDLDBCQUEwQixDQUFDLGlDQUFpQyxDQUFDLENBQUE7Z0NBQ3hFLGlDQUFpQyxHQUFHLEVBQUUsQ0FBQTtnQ0FDdEMsMkJBQTJCLEdBQUcsS0FBSyxDQUFBOzRCQUNyQyxDQUFDO3dCQUNILENBQUM7d0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQzs0QkFDZixlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO3dCQUM3QixDQUFDO3dCQUVELElBQUksQ0FBQzs0QkFDSCxNQUFNLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxtQ0FBbUMsSUFBSSxrQ0FBa0MsQ0FBQyxDQUFBOzRCQUN2SCxtQ0FBbUMsR0FBRyxTQUFTLENBQUE7NEJBQy9DLGtDQUFrQyxHQUFHLFNBQVMsQ0FBQTt3QkFDaEQsQ0FBQzt3QkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDOzRCQUNmLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7d0JBQzdCLENBQUM7d0JBRUQsSUFBSSxDQUFDOzRCQUNILE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFDLFdBQVcsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQUE7d0JBQ3hGLENBQUM7d0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQzs0QkFDZixlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO3dCQUM3QixDQUFDO3dCQUVELElBQUksQ0FBQzs0QkFDSCxNQUFNLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFBO3dCQUNoRixDQUFDO3dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7NEJBQ2YsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTt3QkFDN0IsQ0FBQztvQkFDSCxDQUFDO29CQUVELElBQUksMkJBQTJCLEVBQUUsQ0FBQzt3QkFDaEMsSUFBSSxDQUFDOzRCQUNILFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFBO3dCQUMxRSxDQUFDO3dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7NEJBQ2YsZUFBZSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTt3QkFDN0IsQ0FBQzt3QkFDRCwyQkFBMkIsR0FBRyxLQUFLLENBQUE7b0JBQ3JDLENBQUM7b0JBRUQsSUFBSSxlQUFlLENBQUMsTUFBTSxJQUFJLENBQUM7d0JBQUUsTUFBTSxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUE7b0JBQ3pELElBQUksZUFBZSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQzt3QkFDL0IsTUFBTSxJQUFJLGNBQWMsQ0FBQyxlQUFlLEVBQUUsbUNBQW1DLEVBQUUsRUFBQyxLQUFLLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQTtvQkFDN0csQ0FBQztnQkFDSCxDQUFDLENBQUE7Z0JBRUQsSUFBSSxrQkFBa0IsRUFBRSxDQUFDO29CQUN2QixNQUFNLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLGlCQUFpQixDQUFDLEVBQUMsSUFBSSxFQUFFLFNBQVMsZUFBZSxFQUFFLEVBQUMsRUFBRSxjQUFjLENBQUMsQ0FBQTtnQkFDM0csQ0FBQztxQkFBTSxDQUFDO29CQUNOLE1BQU0sY0FBYyxFQUFFLENBQUE7Z0JBQ3hCLENBQUM7WUFDSCxDQUFDLEVBQUUsbUNBQW1DLENBQUMsQ0FBQTtZQUN2QyxNQUFNLGlCQUFpQixHQUFHLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxVQUFVLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyw4QkFBOEIsQ0FBQyx1QkFBdUIsRUFBRSxvQkFBb0IsQ0FBQyxDQUFBO1lBQ3ZKLGFBQWEsR0FBRyxjQUFjLElBQUksUUFBUTtnQkFDeEMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsY0FBYyxFQUFFLGlCQUFpQixDQUFDO2dCQUN4RCxDQUFDLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtZQUV2QixJQUFJLGtCQUFrQixLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNyQyxNQUFNLGNBQWMsQ0FBQyxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxDQUFDLENBQUE7WUFDMUUsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sYUFBYSxDQUFBO1lBQ3JCLENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sR0FBRyxJQUFJLENBQUE7WUFDYixXQUFXLEdBQUcsS0FBSyxDQUFBO1lBQ25CLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQywrQkFBK0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLG9CQUFvQixDQUFDLENBQUE7WUFDdkYsZUFBZSxHQUFHLFFBQVEsQ0FBQTtZQUUxQixJQUFJLFFBQVEsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDOUIsTUFBTSxzQkFBc0IsR0FBRyxFQUFFLENBQUE7Z0JBRWpDLElBQUksY0FBYyxJQUFJLFFBQVE7b0JBQUUsUUFBUSxDQUFDLGFBQWEsQ0FBQyxjQUFjLEVBQUUsV0FBVyxDQUFDLENBQUE7Z0JBQ25GLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxhQUFhLEVBQUUsa0JBQWtCLElBQUksS0FBSyxDQUFDLENBQUE7Z0JBRTlGLElBQUksZ0JBQWdCLENBQUMsT0FBTyxJQUFJLGdCQUFnQixDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztvQkFDdkUsc0JBQXNCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUN0RCxDQUFDO2dCQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDOUIsdUJBQXVCLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQTtvQkFDdEMsS0FBSyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7d0JBQ3hDLElBQUksOEJBQThCLENBQUMsWUFBWSxDQUFDOzRCQUFFLE9BQU07d0JBQ3hELFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsNEJBQTRCLENBQUMsQ0FBQTtvQkFDdEcsQ0FBQyxDQUFDLENBQUE7b0JBQ0YsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLGlDQUFpQyxDQUFDLG1DQUFtQyxDQUFDLENBQUE7b0JBQ3BHLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsa0JBQWtCLElBQUksS0FBSyxDQUFDLENBQUE7b0JBQzVGLE1BQU0sdUJBQXVCLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixFQUFFLFdBQVcsS0FBSyxJQUFJLENBQUE7b0JBQy9FLE1BQU0scUJBQXFCLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsSUFBSSxDQUFDLHVCQUF1QixDQUFBO29CQUU3RixtQkFBbUIsR0FBRyxVQUFVLENBQUMsaUJBQWlCLEVBQUU7MkJBQy9DLFVBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQzsyQkFDcEMsQ0FBQyx1QkFBdUIsSUFBSSxxQkFBcUIsQ0FBQyxDQUFBO29CQUV2RCxJQUFJLGlCQUFpQixDQUFDLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQ3pFLHNCQUFzQixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtvQkFDdkQsQ0FBQzt5QkFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7d0JBQ3RDLEtBQUssVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksRUFBRSxFQUFFOzRCQUNyQyxVQUFVLENBQUMsMkJBQTJCLENBQUMsWUFBWSxFQUFFLHFDQUFxQyxFQUFFLDRCQUE0QixDQUFDLENBQUE7d0JBQzNILENBQUMsQ0FBQyxDQUFBO29CQUNKLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsSUFBSSwyQkFBMkIsRUFBRSxDQUFDO3dCQUNoQyxVQUFVLENBQUMsMEJBQTBCLENBQUMsaUNBQWlDLENBQUMsQ0FBQTt3QkFDeEUsaUNBQWlDLEdBQUcsRUFBRSxDQUFBO3dCQUN0QywyQkFBMkIsR0FBRyxLQUFLLENBQUE7b0JBQ3JDLENBQUM7Z0JBQ0gsQ0FBQztnQkFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO29CQUN0QixzQkFBc0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7Z0JBQzNDLENBQUM7Z0JBRUQsTUFBTSxhQUFhLEdBQUcsVUFBVSxDQUFDLDJCQUEyQixDQUFDLG1DQUFtQyxJQUFJLGtDQUFrQyxDQUFDLENBQUE7Z0JBQ3ZJLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQyxhQUFhLEVBQUUsa0JBQWtCLElBQUksS0FBSyxDQUFDLENBQUE7Z0JBRWxHLElBQUksb0JBQW9CLENBQUMsT0FBTyxJQUFJLG9CQUFvQixDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztvQkFDL0Usc0JBQXNCLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUMxRCxDQUFDO3FCQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDekMsS0FBSyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7d0JBQ3hDLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxZQUFZLEVBQUUsMkJBQTJCLEVBQUUsNEJBQTRCLENBQUMsQ0FBQTtvQkFDakgsQ0FBQyxDQUFDLENBQUE7Z0JBQ0osQ0FBQztnQkFDRCxtQ0FBbUMsR0FBRyxTQUFTLENBQUE7Z0JBQy9DLGtDQUFrQyxHQUFHLFNBQVMsQ0FBQTtnQkFDOUMsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUMsMkJBQTJCLENBQUMsZ0NBQWdDLEVBQUUsRUFBQyxPQUFPLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtnQkFDbEgsTUFBTSx1QkFBdUIsR0FBRyxNQUFNLG1CQUFtQixDQUFDLGdCQUFnQixFQUFFLGtCQUFrQixJQUFJLEtBQUssQ0FBQyxDQUFBO2dCQUV4RyxJQUFJLHVCQUF1QixDQUFDLE9BQU8sSUFBSSx1QkFBdUIsQ0FBQyxNQUFNLEtBQUssVUFBVSxFQUFFLENBQUM7b0JBQ3JGLHNCQUFzQixDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtnQkFDN0QsQ0FBQztxQkFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQzVDLEtBQUssZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7d0JBQzNDLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxZQUFZLEVBQUUsc0JBQXNCLEVBQUUsNEJBQTRCLENBQUMsQ0FBQTtvQkFDNUcsQ0FBQyxDQUFDLENBQUE7Z0JBQ0osQ0FBQztnQkFFRCxJQUFJLHNCQUFzQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDdEMsV0FBVyxHQUFHLElBQUksY0FBYyxDQUM5QixDQUFDLFdBQVcsRUFBRSxHQUFHLHNCQUFzQixDQUFDLEVBQ3hDLDJDQUEyQyxFQUMzQyxFQUFDLEtBQUssRUFBRSxXQUFXLEVBQUMsQ0FDckIsQ0FBQTtnQkFDSCxDQUFDO1lBQ0gsQ0FBQztZQUVELElBQUksbUNBQW1DLENBQUMsSUFBSSxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDekYsdUJBQXVCLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQTtnQkFDdEMsbUJBQW1CLEdBQUcsSUFBSSxDQUFBO1lBQzVCLENBQUM7UUFDSCxDQUFDO2dCQUFTLENBQUM7WUFDVCx1QkFBdUIsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFBO1lBRXRDLElBQUksY0FBYyxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUMvQixRQUFRLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxNQUFNO29CQUMzQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO29CQUM1QyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDZixDQUFDO1FBQ0gsQ0FBQztRQUVELFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO1lBQ25ELG1CQUFtQjtZQUNuQixLQUFLLEVBQUUsV0FBVztZQUNsQixNQUFNO1NBQ1AsQ0FBQyxDQUFBO1FBRUYsSUFBSSxNQUFNO1lBQUUsTUFBTSxXQUFXLENBQUE7SUFDL0IsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUM7UUFDdEQsS0FBSyxNQUFNLElBQUksSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNoQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUVuRCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO2dCQUNuQyxLQUFLLEVBQUUsWUFBWTtnQkFDbkIsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLGdCQUFnQjtnQkFDM0Msa0JBQWtCLEVBQUUsUUFBUSxDQUFDLGtCQUFrQjtnQkFDL0MsUUFBUSxFQUFFLFFBQVEsQ0FBQyxhQUFhO2FBQ2pDLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ1osTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQTtZQUM5RixDQUFDLENBQUMsQ0FBQTtRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBQyxXQUFXLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQztRQUNwRCw4Q0FBOEM7UUFDOUMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFBO1FBRWpCLEtBQUssTUFBTSxJQUFJLElBQUksV0FBVyxFQUFFLENBQUM7WUFDL0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFbkQsSUFBSSxDQUFDO2dCQUNILE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUM7b0JBQ25DLEtBQUssRUFBRSxXQUFXO29CQUNsQixnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO29CQUMzQyxrQkFBa0IsRUFBRSxRQUFRLENBQUMsa0JBQWtCO29CQUMvQyxRQUFRLEVBQUUsUUFBUSxDQUFDLGFBQWE7aUJBQ2pDLEVBQUUsS0FBSyxJQUFJLEVBQUU7b0JBQ1osTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQTtnQkFDOUYsQ0FBQyxDQUFDLENBQUE7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3BCLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUM7WUFBRSxNQUFNLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUN2QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdEIsTUFBTSxJQUFJLGNBQWMsQ0FBQyxNQUFNLEVBQUUsaUNBQWlDLEVBQUUsRUFBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQTtRQUN6RixDQUFDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7IFRlc3REYXRhYmFzZUFjY2Vzc1Jldm9rZWRFcnJvciB9IGZyb20gXCIuLi9lbnZpcm9ubWVudC1oYW5kbGVycy9iYXNlLmpzXCJcbmltcG9ydCB7IGNsZWFyRGVsaXZlcmllcyB9IGZyb20gXCIuLi9tYWlsZXIuanNcIlxuaW1wb3J0IHJlc3RBcmdzRXJyb3IgZnJvbSBcIi4uL3V0aWxzL3Jlc3QtYXJncy1lcnJvci5qc1wiXG5pbXBvcnQge2NsZWFyVGltZW91dCBhcyByZWFsQ2xlYXJUaW1lb3V0LCBzZXRUaW1lb3V0IGFzIHJlYWxTZXRUaW1lb3V0fSBmcm9tIFwibm9kZTp0aW1lcnNcIlxuXG4vKiogQHR5cGVkZWYge2ltcG9ydChcIkB2ZWxvY2lvdXMvdGVzdGluZy9ydW5uZXJcIikuQXR0ZW1wdEV4ZWN1dG9ySW5wdXRbXCJiZWZvcmVFYWNoXCJdW251bWJlcl19IFBhY2thZ2VIb29rRGVjbGFyYXRpb24gKi9cblxuLyoqXG4gKiBNYXJrcyBvbmUgd2hvbGUtbGlmZWN5Y2xlIHRpbWVvdXQgd2hpbGUgaXRzIHVuZGVybHlpbmcgcHJvbWlzZSBrZWVwcyBydW5uaW5nLlxuICogQHR5cGVkZWYge0Vycm9yICYge3ZlbG9jaW91c1Rlc3RUaW1lb3V0PzogdHJ1ZX19IFRlc3RUaW1lb3V0RXJyb3JcbiAqL1xuXG4vKipcbiAqIFJ1bnMgb25lIHByb21pc2Ugd2l0aCBhIGxpZmVjeWNsZSB0aW1lb3V0LlxuICogQHBhcmFtIHtQcm9taXNlPFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+PiB8IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBwcm9taXNlIC0gUHJvbWlzZSBvciB2YWx1ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0TXMgLSBUaW1lb3V0IGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXN0RGVzY3JpcHRpb24gLSBUZXN0IGRlc2NyaXB0aW9uLlxuICogQHJldHVybnMge1Byb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAtIExpZmVjeWNsZSByZXN1bHQuXG4gKi9cbmZ1bmN0aW9uIHJ1bldpdGhUaW1lb3V0KHByb21pc2UsIHRpbWVvdXRNcywgdGVzdERlc2NyaXB0aW9uKSB7XG4gIGNvbnN0IHRpbWVvdXRTZWNvbmRzID0gKHRpbWVvdXRNcyAvIDEwMDApLnRvRml4ZWQoMykucmVwbGFjZSgvXFwuPzArJC8sIFwiXCIpXG4gIC8qKiBAdHlwZSB7VGVzdFRpbWVvdXRFcnJvcn0gKi9cbiAgY29uc3QgdGltZW91dEVycm9yID0gbmV3IEVycm9yKGBUaW1lZCBvdXQgYWZ0ZXIgJHt0aW1lb3V0U2Vjb25kc31zOiAke3Rlc3REZXNjcmlwdGlvbn1gKVxuICB0aW1lb3V0RXJyb3IudmVsb2Npb3VzVGVzdFRpbWVvdXQgPSB0cnVlXG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCB0aW1lb3V0ID0gcmVhbFNldFRpbWVvdXQoKCkgPT4gcmVqZWN0KHRpbWVvdXRFcnJvciksIHRpbWVvdXRNcylcblxuICAgIFByb21pc2UucmVzb2x2ZShwcm9taXNlKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgIHJlYWxDbGVhclRpbWVvdXQodGltZW91dClcbiAgICAgIHJlc29sdmUocmVzdWx0KVxuICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgcmVhbENsZWFyVGltZW91dCh0aW1lb3V0KVxuICAgICAgcmVqZWN0KGVycm9yKVxuICAgIH0pXG4gIH0pXG59XG5cbi8qKlxuICogV2FpdHMgZm9yIGRldGFjaGVkIGxpZmVjeWNsZSBjbGVhbnVwIHVwIHRvIHRoZSB0aW1lb3V0IGdyYWNlIHBlcmlvZC5cbiAqIEBwYXJhbSB7UHJvbWlzZTxSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IGxpZmVjeWNsZSAtIERldGFjaGVkIGxpZmVjeWNsZSBwcm9taXNlLlxuICogQHBhcmFtIHtudW1iZXJ9IGdyYWNlTXMgLSBNYXhpbXVtIHdhaXQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx7c2V0dGxlZDogZmFsc2V9IHwge3NldHRsZWQ6IHRydWUsIHN0YXR1czogXCJmdWxmaWxsZWRcIn0gfCB7c2V0dGxlZDogdHJ1ZSwgc3RhdHVzOiBcInJlamVjdGVkXCIsIHJlYXNvbjogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59Pn0gLSBTZXR0bGVtZW50IG91dGNvbWUuXG4gKi9cbmZ1bmN0aW9uIGF3YWl0U2V0dGxlZE9yR3JhY2UobGlmZWN5Y2xlLCBncmFjZU1zKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBzZXR0bGVkID0gZmFsc2VcbiAgICBjb25zdCBncmFjZVRpbWVyID0gcmVhbFNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHNldHRsZWQpIHJldHVyblxuXG4gICAgICBzZXR0bGVkID0gdHJ1ZVxuICAgICAgcmVzb2x2ZSh7c2V0dGxlZDogZmFsc2V9KVxuICAgIH0sIGdyYWNlTXMpXG5cbiAgICBQcm9taXNlLnJlc29sdmUobGlmZWN5Y2xlKS50aGVuKFxuICAgICAgKCkgPT4ge1xuICAgICAgICBpZiAoc2V0dGxlZCkgcmV0dXJuXG5cbiAgICAgICAgc2V0dGxlZCA9IHRydWVcbiAgICAgICAgcmVhbENsZWFyVGltZW91dChncmFjZVRpbWVyKVxuICAgICAgICByZXNvbHZlKHtzZXR0bGVkOiB0cnVlLCBzdGF0dXM6IFwiZnVsZmlsbGVkXCJ9KVxuICAgICAgfSxcbiAgICAgIChyZWFzb24pID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVyblxuXG4gICAgICAgIHNldHRsZWQgPSB0cnVlXG4gICAgICAgIHJlYWxDbGVhclRpbWVvdXQoZ3JhY2VUaW1lcilcbiAgICAgICAgcmVzb2x2ZSh7c2V0dGxlZDogdHJ1ZSwgc3RhdHVzOiBcInJlamVjdGVkXCIsIHJlYXNvbn0pXG4gICAgICB9XG4gICAgKVxuICB9KVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGEgbGF0ZSBsaWZlY3ljbGUgc3RvcHBlZCBvbmx5IGJlY2F1c2UgaXRzIGF0dGVtcHQgYWNjZXNzIHdhcyByZXZva2VkLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gZXJyb3IgLSBMaWZlY3ljbGUgcmVqZWN0aW9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciBldmVyeSBjb250YWluZWQgZXJyb3IgaXMgZXhwZWN0ZWQgcmV2b2NhdGlvbi5cbiAqL1xuZnVuY3Rpb24gaXNUZXN0RGF0YWJhc2VBY2Nlc3NSZXZvY2F0aW9uKGVycm9yKSB7XG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIFRlc3REYXRhYmFzZUFjY2Vzc1Jldm9rZWRFcnJvcikgcmV0dXJuIHRydWVcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgQWdncmVnYXRlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyb3IuZXJyb3JzLmxlbmd0aCA+IDAgJiYgZXJyb3IuZXJyb3JzLmV2ZXJ5KChuZXN0ZWRFcnJvcikgPT4gaXNUZXN0RGF0YWJhc2VBY2Nlc3NSZXZvY2F0aW9uKG5lc3RlZEVycm9yKSlcbiAgfVxuXG4gIHJldHVybiBmYWxzZVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBWZWxvY2lvdXNBdHRlbXB0RXhlY3V0b3Ige1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBleGVjdXRvciBmb3IgZnJhbWV3b3JrLW93bmVkIGF0dGVtcHQgbGlmZWN5Y2xlIHdvcmsuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gQ29uc3RydWN0b3IgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdGVzdC1ydW5uZXIuanNcIikuZGVmYXVsdH0gYXJncy50ZXN0UnVubmVyIC0gT3duaW5nIFZlbG9jaW91cyBydW5uZXIuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7dGVzdFJ1bm5lciwgLi4ucmVzdEFyZ3N9KSB7XG4gICAgcmVzdEFyZ3NFcnJvcihyZXN0QXJncylcbiAgICB0aGlzLnRlc3RSdW5uZXIgPSB0ZXN0UnVubmVyXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyB0aGUgbGVnYWN5IHRpbWVvdXQgY29udHJhY3QgYXQgdGhlIGZyYW1ld29yayBhZGFwdGVyIGJvdW5kYXJ5LlxuICAgKiBAcGFyYW0ge251bWJlciB8IHVuZGVmaW5lZH0gdGltZW91dE1zIC0gRGVjbGFyZWQgcGFja2FnZSB0aW1lb3V0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyIHwgdW5kZWZpbmVkfSAtIFBvc2l0aXZlIGZpbml0ZSB0aW1lb3V0LCBvciBubyB0aW1lb3V0LlxuICAgKi9cbiAgbm9ybWFsaXplVGltZW91dE1zKHRpbWVvdXRNcykge1xuICAgIHJldHVybiB0eXBlb2YgdGltZW91dE1zID09PSBcIm51bWJlclwiICYmIE51bWJlci5pc0Zpbml0ZSh0aW1lb3V0TXMpICYmIHRpbWVvdXRNcyA+IDAgPyB0aW1lb3V0TXMgOiB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyBleGFjdGx5IG9uZSBjb21wbGV0ZSBWZWxvY2lvdXMtb3duZWQgdGVzdCBhdHRlbXB0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIkB2ZWxvY2lvdXMvdGVzdGluZy9ydW5uZXJcIikuQXR0ZW1wdEV4ZWN1dG9ySW5wdXR9IGlucHV0IC0gUGFja2FnZSBhdHRlbXB0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciBvbmUgY29tcGxldGUgZnJhbWV3b3JrIGF0dGVtcHQuXG4gICAqL1xuICBhc3luYyBleGVjdXRlKHthZnRlckVhY2gsIGFyZ3MsIGF0dGVtcHROdW1iZXIsIGJlZm9yZUVhY2gsIGNvbnRleHQsIGRlZmF1bHRFeGVjdXRlLCBmdWxsTmFtZSwgc3VpdGUsIHRlc3QsIHRpbWVvdXRNcywgLi4ucmVzdEFyZ3N9KSB7XG4gICAgcmVzdEFyZ3NFcnJvcihyZXN0QXJncylcbiAgICB2b2lkIGNvbnRleHRcbiAgICB2b2lkIGRlZmF1bHRFeGVjdXRlXG4gICAgdm9pZCBzdWl0ZVxuICAgIGNvbnN0IHRlc3RSdW5uZXIgPSB0aGlzLnRlc3RSdW5uZXJcbiAgICBjb25zdCBlZmZlY3RpdmVUaW1lb3V0TXMgPSB0aGlzLm5vcm1hbGl6ZVRpbWVvdXRNcyh0aW1lb3V0TXMpXG4gICAgY29uc3QgY29tcGF0aWJpbGl0eSA9IGF3YWl0IHRlc3RSdW5uZXIudGVzdENvbXBhdGliaWxpdHkodGVzdClcbiAgICBjb25zdCB7dGVzdEFyZ3MsIHRlc3REYXRhfSA9IGNvbXBhdGliaWxpdHlcbiAgICBjb25zdCBtZXRhZGF0YSA9IHRlc3RSdW5uZXIudGVzdE1ldGFkYXRhKHRlc3QpXG4gICAgY29uc3Qge2Rlc2NyaXB0aW9ucywgdGVzdERlc2NyaXB0aW9ufSA9IG1ldGFkYXRhXG4gICAgLyoqIEB0eXBlIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gKi9cbiAgICBsZXQgY2F1Z2h0RXJyb3JcbiAgICBsZXQgZmFpbGVkID0gZmFsc2VcbiAgICAvKiogQHR5cGUge1Byb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+IHwgdW5kZWZpbmVkfSAqL1xuICAgIGxldCB0ZXN0TGlmZWN5Y2xlXG4gICAgLyoqIEB0eXBlIHt7cG9vbDogaW1wb3J0KFwiLi4vZGF0YWJhc2UvcG9vbC9iYXNlLmpzXCIpLmRlZmF1bHQsIHJlZ2lzdHJhdGlvbjogaW1wb3J0KFwiLi4vZGF0YWJhc2UvcG9vbC9iYXNlLmpzXCIpLlRlc3RTaGFyZWRDb25uZWN0aW9uUmVnaXN0cmF0aW9ufVtdfSAqL1xuICAgIGxldCB0ZXN0U2hhcmVkQ29ubmVjdGlvblJlZ2lzdHJhdGlvbnMgPSBbXVxuICAgIGxldCB0ZXN0U2hhcmVkQ29ubmVjdGlvbnNBY3RpdmUgPSBmYWxzZVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90ZXN0LXJ1bm5lci5qc1wiKS5TaGFyZWRUcmFuc2FjdGlvbkJyb2tlclJlZ2lzdHJhdGlvbiB8IHVuZGVmaW5lZH0gKi9cbiAgICBsZXQgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJSZWdpc3RyYXRpb25cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vdGVzdC1ydW5uZXIuanNcIikuU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJSZWdpc3RyYXRpb24gfCB1bmRlZmluZWR9ICovXG4gICAgbGV0IHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyUHJlcGFyYXRpb25cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vdGVzdC1ydW5uZXIuanNcIikuVHJhbnNhY3Rpb25hbFRlbmFudFJlZ2lzdHJhdGlvbltdfSAqL1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uYWxUZW5hbnRSZWdpc3RyYXRpb25zID0gW11cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vdGVzdC1ydW5uZXIuanNcIikuQnJvd3NlckR1bW15Q29ubmVjdGlvblJlZ2lzdHJhdGlvbltdfSAqL1xuICAgIGNvbnN0IGJyb3dzZXJEdW1teUNvbm5lY3Rpb25SZWdpc3RyYXRpb25zID0gW11cbiAgICBjb25zdCB0ZXN0RGF0YWJhc2VBY2Nlc3NTY29wZSA9IHtyZXZva2VkOiBmYWxzZX1cbiAgICAvKiogQHR5cGUge1NldDxFcnJvcj59ICovXG4gICAgY29uc3QgcmVjb3JkZWRUaW1lb3V0Q2xlYW51cEVycm9ycyA9IG5ldyBTZXQoKVxuICAgIGxldCBhYm9ydFJlbWFpbmluZ1Rlc3RzID0gZmFsc2VcbiAgICBsZXQgYXR0ZW1wdFRpbWVkT3V0ID0gZmFsc2VcbiAgICB0ZXN0QXJncy5yZWdpc3RlclRyYW5zYWN0aW9uYWxUZW5hbnQgPSBhc3luYyAoYXJncykgPT4ge1xuICAgICAgYXdhaXQgdGVzdFJ1bm5lci5yZWdpc3RlclRyYW5zYWN0aW9uYWxUZW5hbnQoYXJncywgdHJhbnNhY3Rpb25hbFRlbmFudFJlZ2lzdHJhdGlvbnMpXG4gICAgfVxuICAgIGNvbnN0IHByb2ZpbGVyID0gdGVzdFJ1bm5lci5fcHJvZmlsZXJcbiAgICBjb25zdCBwcm9maWxlQXR0ZW1wdCA9IHByb2ZpbGVyPy5zdGFydEF0dGVtcHQoe1xuICAgICAgZGVzY3JpcHRpb25zLFxuICAgICAgYXR0ZW1wdE51bWJlcixcbiAgICAgIHRlc3REYXRhLFxuICAgICAgdGVzdERlc2NyaXB0aW9uXG4gICAgfSlcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBydW5MaWZlY3ljbGVDYWxsYmFjayA9IGFzeW5jICgpID0+IGF3YWl0IHRlc3RSdW5uZXIucnVuV2l0aER1bW15SWZOZWVkZWQodGVzdEFyZ3MsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgdXNlVHJhbnNhY3Rpb24gPSB0ZXN0QXJncy5kYXRhYmFzZUNsZWFuaW5nPy50cmFuc2FjdGlvbiA9PT0gdHJ1ZVxuICAgICAgICBjb25zdCBzaG91bGRUcnVuY2F0ZSA9IHRlc3RBcmdzLmRhdGFiYXNlQ2xlYW5pbmc/LnRydW5jYXRlID8/ICF1c2VUcmFuc2FjdGlvblxuICAgICAgICBjb25zdCB1c2VTaGFyZWRUZXN0Q29ubmVjdGlvbnMgPSB1c2VUcmFuc2FjdGlvbiB8fCB0ZXN0QXJncy50eXBlID09IFwicmVxdWVzdFwiXG4gICAgICAgIGNvbnN0IHVzZVRlc3RDb25uZWN0aW9ucyA9IHVzZVNoYXJlZFRlc3RDb25uZWN0aW9ucyB8fCBzaG91bGRUcnVuY2F0ZVxuICAgICAgICBjb25zdCBydW5UZXN0QXR0ZW1wdCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBpZiAodXNlU2hhcmVkVGVzdENvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgICB0ZXN0U2hhcmVkQ29ubmVjdGlvblJlZ2lzdHJhdGlvbnMgPSB0ZXN0UnVubmVyLmFjdGl2YXRlVGVzdFNoYXJlZENvbm5lY3Rpb25zKClcbiAgICAgICAgICAgIHRlc3RTaGFyZWRDb25uZWN0aW9uc0FjdGl2ZSA9IHRydWVcbiAgICAgICAgICB9XG4gICAgICAgICAgLyoqIEB0eXBlIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPltdfSAqL1xuICAgICAgICAgIGNvbnN0IGxpZmVjeWNsZUVycm9ycyA9IFtdXG4gICAgICAgICAgbGV0IHJ1bkNsZWFudXBIb29rcyA9IGZhbHNlXG5cbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKHVzZVNoYXJlZFRlc3RDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclByZXBhcmF0aW9uID0gYXdhaXQgdGVzdFJ1bm5lci5wcmVwYXJlU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXIoKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcnVuQ2xlYW51cEhvb2tzID0gdHJ1ZVxuXG4gICAgICAgICAgICBjbGVhckRlbGl2ZXJpZXMoKVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5ydW5CZWZvcmVFYWNoZXMoe2JlZm9yZUVhY2hlczogYmVmb3JlRWFjaCwgdGVzdEFyZ3MsIHRlc3REYXRhfSlcblxuICAgICAgICAgICAgaWYgKHVzZVNoYXJlZFRlc3RDb25uZWN0aW9ucykge1xuICAgICAgICAgICAgICBjb25zdCBhY3RpdmVDb25uZWN0aW9ucyA9IHRlc3RSdW5uZXIuc2hhcmVkVHJhbnNhY3Rpb25Db25uZWN0aW9ucyh7dHJhbnNhY3Rpb25zT25seTogdHJ1ZX0pXG4gICAgICAgICAgICAgIGlmIChzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclByZXBhcmF0aW9uICYmICF0ZXN0UnVubmVyLnNoYXJlZFRyYW5zYWN0aW9uQnJva2VyTWF0Y2hlc0Nvbm5lY3Rpb25zKHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyUHJlcGFyYXRpb24sIGFjdGl2ZUNvbm5lY3Rpb25zKSkge1xuICAgICAgICAgICAgICAgIHRlc3RSdW5uZXIuY2xlYXJUZXN0U2hhcmVkQ29ubmVjdGlvbnModGVzdFNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zKVxuICAgICAgICAgICAgICAgIHRlc3RTaGFyZWRDb25uZWN0aW9uUmVnaXN0cmF0aW9ucyA9IFtdXG4gICAgICAgICAgICAgICAgdGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlID0gZmFsc2VcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyUmVnaXN0cmF0aW9uID0gYXdhaXQgdGVzdFJ1bm5lci5zdGFydFNoYXJlZFRyYW5zYWN0aW9uQnJva2VyKHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyUHJlcGFyYXRpb24sIGFjdGl2ZUNvbm5lY3Rpb25zKVxuICAgICAgICAgICAgICBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclByZXBhcmF0aW9uID0gdW5kZWZpbmVkXG4gICAgICAgICAgICAgIGlmIChzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclJlZ2lzdHJhdGlvbiAmJiAhdGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGVzdFNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zID0gdGVzdFJ1bm5lci5hY3RpdmF0ZVRlc3RTaGFyZWRDb25uZWN0aW9ucygpXG4gICAgICAgICAgICAgICAgdGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlID0gdHJ1ZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRlc3RSdW5uZXIuX2xhc3RUZXN0Q29udGV4dCA9IHtcbiAgICAgICAgICAgICAgZnVsbERlc2NyaXB0aW9uOiBmdWxsTmFtZSxcbiAgICAgICAgICAgICAgZmlsZVBhdGg6IHRlc3REYXRhLmZpbGVQYXRoID8/IFwiPHVua25vd24+XCIsXG4gICAgICAgICAgICAgIGxpbmU6IHRlc3REYXRhLmxpbmUgPz8gMFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgdGVzdFJ1bm5lci5ydW5Qcm9maWxlU3Bhbih7cGhhc2U6IFwidGVzdCBib2R5XCIsIGZpbGVQYXRoOiB0ZXN0RGF0YS5vd25lckZpbGVQYXRoID8/IHRlc3REYXRhLmZpbGVQYXRofSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICBhd2FpdCB0ZXN0LmNhbGxiYWNrKC4uLmFyZ3MpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBsaWZlY3ljbGVFcnJvcnMucHVzaChlcnJvcilcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocnVuQ2xlYW51cEhvb2tzKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBhd2FpdCB0ZXN0UnVubmVyLmdldENvbmZpZ3VyYXRpb24oKS5hd2FpdFBlbmRpbmdCcm9hZGNhc3RzKClcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIGxpZmVjeWNsZUVycm9ycy5wdXNoKGVycm9yKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBpZiAodGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdGVzdFJ1bm5lci5jbGVhclRlc3RTaGFyZWRDb25uZWN0aW9ucyh0ZXN0U2hhcmVkQ29ubmVjdGlvblJlZ2lzdHJhdGlvbnMpXG4gICAgICAgICAgICAgICAgdGVzdFNoYXJlZENvbm5lY3Rpb25SZWdpc3RyYXRpb25zID0gW11cbiAgICAgICAgICAgICAgICB0ZXN0U2hhcmVkQ29ubmVjdGlvbnNBY3RpdmUgPSBmYWxzZVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICBsaWZlY3ljbGVFcnJvcnMucHVzaChlcnJvcilcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgdGVzdFJ1bm5lci5zdG9wU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXIoc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJSZWdpc3RyYXRpb24gfHwgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJQcmVwYXJhdGlvbilcbiAgICAgICAgICAgICAgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJSZWdpc3RyYXRpb24gPSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJQcmVwYXJhdGlvbiA9IHVuZGVmaW5lZFxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgbGlmZWN5Y2xlRXJyb3JzLnB1c2goZXJyb3IpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMucnVuQWZ0ZXJFYWNoZXMoe2FmdGVyRWFjaGVzOiBbLi4uYWZ0ZXJFYWNoXS5yZXZlcnNlKCksIHRlc3RBcmdzLCB0ZXN0RGF0YX0pXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICBsaWZlY3ljbGVFcnJvcnMucHVzaChlcnJvcilcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgYXdhaXQgdGVzdFJ1bm5lci5jbGVhbnVwVHJhbnNhY3Rpb25hbFRlbmFudHModHJhbnNhY3Rpb25hbFRlbmFudFJlZ2lzdHJhdGlvbnMpXG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICBsaWZlY3ljbGVFcnJvcnMucHVzaChlcnJvcilcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICB0ZXN0UnVubmVyLmNsZWFyVGVzdFNoYXJlZENvbm5lY3Rpb25zKHRlc3RTaGFyZWRDb25uZWN0aW9uUmVnaXN0cmF0aW9ucylcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIGxpZmVjeWNsZUVycm9ycy5wdXNoKGVycm9yKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlID0gZmFsc2VcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobGlmZWN5Y2xlRXJyb3JzLmxlbmd0aCA9PSAxKSB0aHJvdyBsaWZlY3ljbGVFcnJvcnNbMF1cbiAgICAgICAgICBpZiAobGlmZWN5Y2xlRXJyb3JzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihsaWZlY3ljbGVFcnJvcnMsIFwiVGVzdCBsaWZlY3ljbGUgYW5kIGNsZWFudXAgZmFpbGVkXCIsIHtjYXVzZTogbGlmZWN5Y2xlRXJyb3JzWzBdfSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodXNlVGVzdENvbm5lY3Rpb25zKSB7XG4gICAgICAgICAgYXdhaXQgdGVzdFJ1bm5lci5nZXRDb25maWd1cmF0aW9uKCkuZW5zdXJlQ29ubmVjdGlvbnMoe25hbWU6IGBUZXN0OiAke3Rlc3REZXNjcmlwdGlvbn1gfSwgcnVuVGVzdEF0dGVtcHQpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYXdhaXQgcnVuVGVzdEF0dGVtcHQoKVxuICAgICAgICB9XG4gICAgICB9LCBicm93c2VyRHVtbXlDb25uZWN0aW9uUmVnaXN0cmF0aW9ucylcbiAgICAgIGNvbnN0IGxpZmVjeWNsZUNhbGxiYWNrID0gYXN5bmMgKCkgPT4gYXdhaXQgdGVzdFJ1bm5lci5nZXRDb25maWd1cmF0aW9uKCkucnVuV2l0aFRlc3REYXRhYmFzZUFjY2Vzc1Njb3BlKHRlc3REYXRhYmFzZUFjY2Vzc1Njb3BlLCBydW5MaWZlY3ljbGVDYWxsYmFjaylcbiAgICAgIHRlc3RMaWZlY3ljbGUgPSBwcm9maWxlQXR0ZW1wdCAmJiBwcm9maWxlclxuICAgICAgICA/IHByb2ZpbGVyLnJ1bkF0dGVtcHQocHJvZmlsZUF0dGVtcHQsIGxpZmVjeWNsZUNhbGxiYWNrKVxuICAgICAgICA6IGxpZmVjeWNsZUNhbGxiYWNrKClcblxuICAgICAgaWYgKGVmZmVjdGl2ZVRpbWVvdXRNcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGF3YWl0IHJ1bldpdGhUaW1lb3V0KHRlc3RMaWZlY3ljbGUsIGVmZmVjdGl2ZVRpbWVvdXRNcywgdGVzdERlc2NyaXB0aW9uKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGVzdExpZmVjeWNsZVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBmYWlsZWQgPSB0cnVlXG4gICAgICBjYXVnaHRFcnJvciA9IGVycm9yXG4gICAgICBjb25zdCB0aW1lZE91dCA9IEJvb2xlYW4oLyoqIEB0eXBlIHtUZXN0VGltZW91dEVycm9yfSAqLyAoZXJyb3IpPy52ZWxvY2lvdXNUZXN0VGltZW91dClcbiAgICAgIGF0dGVtcHRUaW1lZE91dCA9IHRpbWVkT3V0XG5cbiAgICAgIGlmICh0aW1lZE91dCAmJiB0ZXN0TGlmZWN5Y2xlKSB7XG4gICAgICAgIGNvbnN0IGVtZXJnZW5jeUNsZWFudXBFcnJvcnMgPSBbXVxuXG4gICAgICAgIGlmIChwcm9maWxlQXR0ZW1wdCAmJiBwcm9maWxlcikgcHJvZmlsZXIuZmluaXNoQXR0ZW1wdChwcm9maWxlQXR0ZW1wdCwgXCJ0aW1lZC1vdXRcIilcbiAgICAgICAgY29uc3QgbGlmZWN5Y2xlT3V0Y29tZSA9IGF3YWl0IGF3YWl0U2V0dGxlZE9yR3JhY2UodGVzdExpZmVjeWNsZSwgZWZmZWN0aXZlVGltZW91dE1zID8/IDYwMDAwKVxuXG4gICAgICAgIGlmIChsaWZlY3ljbGVPdXRjb21lLnNldHRsZWQgJiYgbGlmZWN5Y2xlT3V0Y29tZS5zdGF0dXMgPT09IFwicmVqZWN0ZWRcIikge1xuICAgICAgICAgIGVtZXJnZW5jeUNsZWFudXBFcnJvcnMucHVzaChsaWZlY3ljbGVPdXRjb21lLnJlYXNvbilcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghbGlmZWN5Y2xlT3V0Y29tZS5zZXR0bGVkKSB7XG4gICAgICAgICAgdGVzdERhdGFiYXNlQWNjZXNzU2NvcGUucmV2b2tlZCA9IHRydWVcbiAgICAgICAgICB2b2lkIHRlc3RMaWZlY3ljbGUuY2F0Y2goKGNsZWFudXBFcnJvcikgPT4ge1xuICAgICAgICAgICAgaWYgKGlzVGVzdERhdGFiYXNlQWNjZXNzUmV2b2NhdGlvbihjbGVhbnVwRXJyb3IpKSByZXR1cm5cbiAgICAgICAgICAgIHRlc3RSdW5uZXIucmVjb3JkVGltZW91dENsZWFudXBGYWlsdXJlKGNsZWFudXBFcnJvciwgXCJ0ZXN0IGxpZmVjeWNsZVwiLCByZWNvcmRlZFRpbWVvdXRDbGVhbnVwRXJyb3JzKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgY29uc3QgcXVhcmFudGluZSA9IHRlc3RSdW5uZXIucXVhcmFudGluZUJyb3dzZXJEdW1teUNvbm5lY3Rpb25zKGJyb3dzZXJEdW1teUNvbm5lY3Rpb25SZWdpc3RyYXRpb25zKVxuICAgICAgICAgIGNvbnN0IHF1YXJhbnRpbmVPdXRjb21lID0gYXdhaXQgYXdhaXRTZXR0bGVkT3JHcmFjZShxdWFyYW50aW5lLCBlZmZlY3RpdmVUaW1lb3V0TXMgPz8gNjAwMDApXG4gICAgICAgICAgY29uc3QgdXNlc0Jyb3dzZXJUcmFuc2FjdGlvbnMgPSB0ZXN0QXJncy5kYXRhYmFzZUNsZWFuaW5nPy50cmFuc2FjdGlvbiA9PT0gdHJ1ZVxuICAgICAgICAgIGNvbnN0IHVzZXNCcm93c2VyVHJ1bmNhdGlvbiA9IHRlc3RBcmdzLmRhdGFiYXNlQ2xlYW5pbmc/LnRydW5jYXRlID8/ICF1c2VzQnJvd3NlclRyYW5zYWN0aW9uc1xuXG4gICAgICAgICAgYWJvcnRSZW1haW5pbmdUZXN0cyA9IHRlc3RSdW5uZXIuaXNCcm93c2VyVGVzdE1vZGUoKVxuICAgICAgICAgICAgJiYgdGVzdFJ1bm5lci5oYXNUYWcodGVzdEFyZ3MsIFwiZHVtbXlcIilcbiAgICAgICAgICAgICYmICh1c2VzQnJvd3NlclRyYW5zYWN0aW9ucyB8fCB1c2VzQnJvd3NlclRydW5jYXRpb24pXG5cbiAgICAgICAgICBpZiAocXVhcmFudGluZU91dGNvbWUuc2V0dGxlZCAmJiBxdWFyYW50aW5lT3V0Y29tZS5zdGF0dXMgPT09IFwicmVqZWN0ZWRcIikge1xuICAgICAgICAgICAgZW1lcmdlbmN5Q2xlYW51cEVycm9ycy5wdXNoKHF1YXJhbnRpbmVPdXRjb21lLnJlYXNvbilcbiAgICAgICAgICB9IGVsc2UgaWYgKCFxdWFyYW50aW5lT3V0Y29tZS5zZXR0bGVkKSB7XG4gICAgICAgICAgICB2b2lkIHF1YXJhbnRpbmUuY2F0Y2goKGNsZWFudXBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICB0ZXN0UnVubmVyLnJlY29yZFRpbWVvdXRDbGVhbnVwRmFpbHVyZShjbGVhbnVwRXJyb3IsIFwiYnJvd3NlciBkdW1teSBjb25uZWN0aW9uIHF1YXJhbnRpbmVcIiwgcmVjb3JkZWRUaW1lb3V0Q2xlYW51cEVycm9ycylcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBpZiAodGVzdFNoYXJlZENvbm5lY3Rpb25zQWN0aXZlKSB7XG4gICAgICAgICAgICB0ZXN0UnVubmVyLmNsZWFyVGVzdFNoYXJlZENvbm5lY3Rpb25zKHRlc3RTaGFyZWRDb25uZWN0aW9uUmVnaXN0cmF0aW9ucylcbiAgICAgICAgICAgIHRlc3RTaGFyZWRDb25uZWN0aW9uUmVnaXN0cmF0aW9ucyA9IFtdXG4gICAgICAgICAgICB0ZXN0U2hhcmVkQ29ubmVjdGlvbnNBY3RpdmUgPSBmYWxzZVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoY2xlYW51cEVycm9yKSB7XG4gICAgICAgICAgZW1lcmdlbmN5Q2xlYW51cEVycm9ycy5wdXNoKGNsZWFudXBFcnJvcilcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJyb2tlckNsZWFudXAgPSB0ZXN0UnVubmVyLnN0b3BTaGFyZWRUcmFuc2FjdGlvbkJyb2tlcihzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclJlZ2lzdHJhdGlvbiB8fCBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlclByZXBhcmF0aW9uKVxuICAgICAgICBjb25zdCBicm9rZXJDbGVhbnVwT3V0Y29tZSA9IGF3YWl0IGF3YWl0U2V0dGxlZE9yR3JhY2UoYnJva2VyQ2xlYW51cCwgZWZmZWN0aXZlVGltZW91dE1zID8/IDYwMDAwKVxuXG4gICAgICAgIGlmIChicm9rZXJDbGVhbnVwT3V0Y29tZS5zZXR0bGVkICYmIGJyb2tlckNsZWFudXBPdXRjb21lLnN0YXR1cyA9PT0gXCJyZWplY3RlZFwiKSB7XG4gICAgICAgICAgZW1lcmdlbmN5Q2xlYW51cEVycm9ycy5wdXNoKGJyb2tlckNsZWFudXBPdXRjb21lLnJlYXNvbilcbiAgICAgICAgfSBlbHNlIGlmICghYnJva2VyQ2xlYW51cE91dGNvbWUuc2V0dGxlZCkge1xuICAgICAgICAgIHZvaWQgYnJva2VyQ2xlYW51cC5jYXRjaCgoY2xlYW51cEVycm9yKSA9PiB7XG4gICAgICAgICAgICB0ZXN0UnVubmVyLnJlY29yZFRpbWVvdXRDbGVhbnVwRmFpbHVyZShjbGVhbnVwRXJyb3IsIFwic2hhcmVkIHRyYW5zYWN0aW9uIGJyb2tlclwiLCByZWNvcmRlZFRpbWVvdXRDbGVhbnVwRXJyb3JzKVxuICAgICAgICAgIH0pXG4gICAgICAgIH1cbiAgICAgICAgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJSZWdpc3RyYXRpb24gPSB1bmRlZmluZWRcbiAgICAgICAgc2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJQcmVwYXJhdGlvbiA9IHVuZGVmaW5lZFxuICAgICAgICBjb25zdCBlbWVyZ2VuY3lDbGVhbnVwID0gdGVzdFJ1bm5lci5jbGVhbnVwVHJhbnNhY3Rpb25hbFRlbmFudHModHJhbnNhY3Rpb25hbFRlbmFudFJlZ2lzdHJhdGlvbnMsIHtkaXNjYXJkOiB0cnVlfSlcbiAgICAgICAgY29uc3QgZW1lcmdlbmN5Q2xlYW51cE91dGNvbWUgPSBhd2FpdCBhd2FpdFNldHRsZWRPckdyYWNlKGVtZXJnZW5jeUNsZWFudXAsIGVmZmVjdGl2ZVRpbWVvdXRNcyA/PyA2MDAwMClcblxuICAgICAgICBpZiAoZW1lcmdlbmN5Q2xlYW51cE91dGNvbWUuc2V0dGxlZCAmJiBlbWVyZ2VuY3lDbGVhbnVwT3V0Y29tZS5zdGF0dXMgPT09IFwicmVqZWN0ZWRcIikge1xuICAgICAgICAgIGVtZXJnZW5jeUNsZWFudXBFcnJvcnMucHVzaChlbWVyZ2VuY3lDbGVhbnVwT3V0Y29tZS5yZWFzb24pXG4gICAgICAgIH0gZWxzZSBpZiAoIWVtZXJnZW5jeUNsZWFudXBPdXRjb21lLnNldHRsZWQpIHtcbiAgICAgICAgICB2b2lkIGVtZXJnZW5jeUNsZWFudXAuY2F0Y2goKGNsZWFudXBFcnJvcikgPT4ge1xuICAgICAgICAgICAgdGVzdFJ1bm5lci5yZWNvcmRUaW1lb3V0Q2xlYW51cEZhaWx1cmUoY2xlYW51cEVycm9yLCBcInRyYW5zYWN0aW9uYWwgdGVuYW50XCIsIHJlY29yZGVkVGltZW91dENsZWFudXBFcnJvcnMpXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlbWVyZ2VuY3lDbGVhbnVwRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjYXVnaHRFcnJvciA9IG5ldyBBZ2dyZWdhdGVFcnJvcihcbiAgICAgICAgICAgIFtjYXVnaHRFcnJvciwgLi4uZW1lcmdlbmN5Q2xlYW51cEVycm9yc10sXG4gICAgICAgICAgICBcIlRlc3QgdGltZW91dCBhbmQgZW1lcmdlbmN5IGNsZWFudXAgZmFpbGVkXCIsXG4gICAgICAgICAgICB7Y2F1c2U6IGNhdWdodEVycm9yfVxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoYnJvd3NlckR1bW15Q29ubmVjdGlvblJlZ2lzdHJhdGlvbnMuc29tZSgocmVnaXN0cmF0aW9uKSA9PiByZWdpc3RyYXRpb24ucXVhcmFudGluZWQpKSB7XG4gICAgICAgIHRlc3REYXRhYmFzZUFjY2Vzc1Njb3BlLnJldm9rZWQgPSB0cnVlXG4gICAgICAgIGFib3J0UmVtYWluaW5nVGVzdHMgPSB0cnVlXG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRlc3REYXRhYmFzZUFjY2Vzc1Njb3BlLnJldm9rZWQgPSB0cnVlXG5cbiAgICAgIGlmIChwcm9maWxlQXR0ZW1wdCAmJiBwcm9maWxlcikge1xuICAgICAgICBwcm9maWxlci5maW5pc2hBdHRlbXB0KHByb2ZpbGVBdHRlbXB0LCBmYWlsZWRcbiAgICAgICAgICA/IChhdHRlbXB0VGltZWRPdXQgPyBcInRpbWVkLW91dFwiIDogXCJmYWlsZWRcIilcbiAgICAgICAgICA6IFwicGFzc2VkXCIpXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGVzdFJ1bm5lci5yZWNvcmRBdHRlbXB0T3V0Y29tZSh0ZXN0LCBhdHRlbXB0TnVtYmVyLCB7XG4gICAgICBhYm9ydFJlbWFpbmluZ1Rlc3RzLFxuICAgICAgZXJyb3I6IGNhdWdodEVycm9yLFxuICAgICAgZmFpbGVkXG4gICAgfSlcblxuICAgIGlmIChmYWlsZWQpIHRocm93IGNhdWdodEVycm9yXG4gIH1cblxuICAvKipcbiAgICogUnVucyBiZWZvcmUtZWFjaCBob29rcyBpbiBpbmhlcml0ZWQgZGVjbGFyYXRpb24gb3JkZXIuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gSG9vayBhcmd1bWVudHMuXG4gICAqIEBwYXJhbSB7UGFja2FnZUhvb2tEZWNsYXJhdGlvbltdfSBhcmdzLmJlZm9yZUVhY2hlcyAtIFNldHVwIGhvb2tzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVsb2Npb3VzLXRlc3QtYXJndW1lbnRzLmpzXCIpLlRlc3RBcmdzfSBhcmdzLnRlc3RBcmdzIC0gU3RhYmxlIHRlc3QgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVsb2Npb3VzLXRlc3QtYXJndW1lbnRzLmpzXCIpLlRlc3REYXRhfSBhcmdzLnRlc3REYXRhIC0gVGVzdCByZWdpc3RyYXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGFsbCBzZXR1cCBob29rcyBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHJ1bkJlZm9yZUVhY2hlcyh7YmVmb3JlRWFjaGVzLCB0ZXN0QXJncywgdGVzdERhdGF9KSB7XG4gICAgZm9yIChjb25zdCBob29rIG9mIGJlZm9yZUVhY2hlcykge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSB0aGlzLnRlc3RSdW5uZXIuaG9va01ldGFkYXRhKGhvb2spXG5cbiAgICAgIGF3YWl0IHRoaXMudGVzdFJ1bm5lci5ydW5Qcm9maWxlU3Bhbih7XG4gICAgICAgIHBoYXNlOiBcImJlZm9yZUVhY2hcIixcbiAgICAgICAgZGVjbGFyYXRpb25JbmRleDogbWV0YWRhdGEuZGVjbGFyYXRpb25JbmRleCxcbiAgICAgICAgZGVjbGFyYXRpb25TY29wZUlkOiBtZXRhZGF0YS5kZWNsYXJhdGlvblNjb3BlSWQsXG4gICAgICAgIGZpbGVQYXRoOiBtZXRhZGF0YS5vd25lckZpbGVQYXRoXG4gICAgICB9LCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IGhvb2suY2FsbGJhY2soe2NvbmZpZ3VyYXRpb246IHRoaXMudGVzdFJ1bm5lci5nZXRDb25maWd1cmF0aW9uKCksIHRlc3RBcmdzLCB0ZXN0RGF0YX0pXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGV2ZXJ5IGFmdGVyLWVhY2ggaG9vayB3aGlsZSBwcmVzZXJ2aW5nIGFsbCBmYWlsdXJlcy5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBIb29rIGFyZ3VtZW50cy5cbiAgICogQHBhcmFtIHtQYWNrYWdlSG9va0RlY2xhcmF0aW9uW119IGFyZ3MuYWZ0ZXJFYWNoZXMgLSBDbGVhbnVwIGhvb2tzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVsb2Npb3VzLXRlc3QtYXJndW1lbnRzLmpzXCIpLlRlc3RBcmdzfSBhcmdzLnRlc3RBcmdzIC0gU3RhYmxlIHRlc3QgYXJndW1lbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVsb2Npb3VzLXRlc3QtYXJndW1lbnRzLmpzXCIpLlRlc3REYXRhfSBhcmdzLnRlc3REYXRhIC0gVGVzdCByZWdpc3RyYXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGV2ZXJ5IGNsZWFudXAgaG9vayBzZXR0bGVzLlxuICAgKi9cbiAgYXN5bmMgcnVuQWZ0ZXJFYWNoZXMoe2FmdGVyRWFjaGVzLCB0ZXN0QXJncywgdGVzdERhdGF9KSB7XG4gICAgLyoqIEB0eXBlIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPltdfSAqL1xuICAgIGNvbnN0IGVycm9ycyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IGhvb2sgb2YgYWZ0ZXJFYWNoZXMpIHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gdGhpcy50ZXN0UnVubmVyLmhvb2tNZXRhZGF0YShob29rKVxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnRlc3RSdW5uZXIucnVuUHJvZmlsZVNwYW4oe1xuICAgICAgICAgIHBoYXNlOiBcImFmdGVyRWFjaFwiLFxuICAgICAgICAgIGRlY2xhcmF0aW9uSW5kZXg6IG1ldGFkYXRhLmRlY2xhcmF0aW9uSW5kZXgsXG4gICAgICAgICAgZGVjbGFyYXRpb25TY29wZUlkOiBtZXRhZGF0YS5kZWNsYXJhdGlvblNjb3BlSWQsXG4gICAgICAgICAgZmlsZVBhdGg6IG1ldGFkYXRhLm93bmVyRmlsZVBhdGhcbiAgICAgICAgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IGhvb2suY2FsbGJhY2soe2NvbmZpZ3VyYXRpb246IHRoaXMudGVzdFJ1bm5lci5nZXRDb25maWd1cmF0aW9uKCksIHRlc3RBcmdzLCB0ZXN0RGF0YX0pXG4gICAgICAgIH0pXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBlcnJvcnMucHVzaChlcnJvcilcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA9PSAxKSB0aHJvdyBlcnJvcnNbMF1cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihlcnJvcnMsIFwiTXVsdGlwbGUgYWZ0ZXJFYWNoIGhvb2tzIGZhaWxlZFwiLCB7Y2F1c2U6IGVycm9yc1swXX0pXG4gICAgfVxuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type PackageTestDeclaration = import("@velocious/testing/runner").TestDeclaration;
|
|
2
|
+
/** @typedef {import("@velocious/testing/runner").TestDeclaration} PackageTestDeclaration */
|
|
3
|
+
/** Stops package traversal after framework-owned connection quarantine. */
|
|
4
|
+
export declare class AbortRemainingTestsError extends Error {
|
|
5
|
+
}
|
|
6
|
+
export default class VelociousRunnerReporter {
|
|
7
|
+
testRunner: import("./test-runner.js").default;
|
|
8
|
+
/** @type {WeakMap<PackageTestDeclaration, import("./test-runner.js").AttemptConsoleOutput[]>} */
|
|
9
|
+
attemptConsoleOutputs: WeakMap<PackageTestDeclaration, import("./test-runner.js").AttemptConsoleOutput[]>;
|
|
10
|
+
/** @type {PackageTestDeclaration | undefined} */
|
|
11
|
+
activeTest: PackageTestDeclaration | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Creates the legacy event and result projection adapter.
|
|
14
|
+
* @param {object} args - Constructor arguments.
|
|
15
|
+
* @param {import("./test-runner.js").default} args.testRunner - Owning Velocious runner.
|
|
16
|
+
*/
|
|
17
|
+
constructor({ testRunner, ...restArgs }: {
|
|
18
|
+
testRunner: import("./test-runner.js").default;
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Translates one awaited package runner event into the legacy contract.
|
|
22
|
+
* @param {import("@velocious/testing/runner").RunnerEvent} event - Structured package event.
|
|
23
|
+
* @returns {Promise<void>} - Resolves after legacy listeners finish.
|
|
24
|
+
*/
|
|
25
|
+
onEvent(event: import("@velocious/testing/runner").RunnerEvent): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Projects attempt failure/retry events while retaining the raw thrown value.
|
|
28
|
+
* @param {import("@velocious/testing/runner").RunnerEvent} event - Attempt event.
|
|
29
|
+
* @returns {Promise<void>} - Resolves after listeners finish.
|
|
30
|
+
*/
|
|
31
|
+
reportAttemptEvent(event: import("@velocious/testing/runner").RunnerEvent): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Projects final package result accounting and failures.
|
|
34
|
+
* @param {import("@velocious/testing/runner").RunnerEvent} event - Test result event.
|
|
35
|
+
* @returns {Promise<void>} - Resolves after listeners finish.
|
|
36
|
+
*/
|
|
37
|
+
reportTestEvent(event: import("@velocious/testing/runner").RunnerEvent): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Records and emits one final failed test result.
|
|
40
|
+
* @param {object} args - Final failure metadata.
|
|
41
|
+
* @param {import("./test-runner.js").AttemptConsoleOutput[]} args.attemptConsoleOutputs - Captured output across attempts.
|
|
42
|
+
* @param {string[]} args.descriptions - Parent description stack.
|
|
43
|
+
* @param {ReturnType<typeof JSON.parse>} args.error - Raw final failure.
|
|
44
|
+
* @param {string} args.leftPadding - Console indentation.
|
|
45
|
+
* @param {import("./test-runner.js").TestArgs} args.testArgs - Stable test arguments.
|
|
46
|
+
* @param {import("./test-runner.js").TestData} args.testData - Test registration.
|
|
47
|
+
* @param {string} args.testDescription - Test description.
|
|
48
|
+
* @returns {Promise<void>} - Resolves after the final-failure listener completes.
|
|
49
|
+
*/
|
|
50
|
+
reportFailedTest({ attemptConsoleOutputs, descriptions, error, leftPadding, testArgs, testData, testDescription }: {
|
|
51
|
+
attemptConsoleOutputs: import("./test-runner.js").AttemptConsoleOutput[];
|
|
52
|
+
descriptions: string[];
|
|
53
|
+
error: ReturnType<typeof JSON.parse>;
|
|
54
|
+
leftPadding: string;
|
|
55
|
+
testArgs: import("./test-runner.js").TestArgs;
|
|
56
|
+
testData: import("./test-runner.js").TestData;
|
|
57
|
+
testDescription: string;
|
|
58
|
+
}): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Emits one legacy event and awaits listeners in registration order.
|
|
61
|
+
* @param {string} eventName - Event name.
|
|
62
|
+
* @param {object} payload - Event payload.
|
|
63
|
+
* @returns {Promise<void>} - Resolves when all listeners complete.
|
|
64
|
+
*/
|
|
65
|
+
emitEvent(eventName: string, payload: object): Promise<void>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=velocious-runner-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"velocious-runner-reporter.d.ts","sourceRoot":"","sources":["../../../src/testing/velocious-runner-reporter.js"],"names":[],"mappings":"AAQI,YAA+D,sBAAsB,GAA3E,OAAO,2BAA2B,EAAE,eAAe,CAAwB;AAAzF,4FAA4F;AAE5F,2EAA2E;AAC3E,qBAAa,wBAAyB,SAAQ,KAAK;CAAG;AAEtD,MAAM,CAAC,OAAO,OAAO,uBAAuB;IAQnC,UAAU;IACf,iGAAiG;IAC5F,qBAAqB,EADf,OAAO,CAAC,sBAAsB,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;IAE7F,iDAAiD;IAC5C,UAAU,EADJ,sBAAsB,GAAG,SAAS;IAV/C;;;;OAIG;IACH,YAAY,EAAC,UAAU,EAAE,GAAG,QAAQ,EAAC,EAFlC;QAAiD,UAAU,EAAnD,OAAO,kBAAkB,EAAE,OAAO,CAC5C;KACoC,EAOpC;IAED;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAHR,OAAO,2BAA2B,EAAE,WAG5B,GAFN,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;OAIG;IACG,kBAAkB,CAAC,KAAK,EAHnB,OAAO,2BAA2B,EAAE,WAGjB,GAFjB,OAAO,CAAC,IAAI,CAAC,CA+FzB;IAED;;;;OAIG;IACG,eAAe,CAAC,KAAK,EAHhB,OAAO,2BAA2B,EAAE,WAGpB,GAFd,OAAO,CAAC,IAAI,CAAC,CA8CzB;IAED;;;;;;;;;;;OAWG;IACG,gBAAgB,CAAC,EAAC,qBAAqB,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAC,EATlH;QAAgE,qBAAqB,EAA7E,OAAO,kBAAkB,EAAE,oBAAoB,EAAE,CACzD;QAAuB,YAAY,EAA3B,MAAM,EAAE,CAChB;QAA4C,KAAK,EAAzC,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CACrC;QAAqB,WAAW,EAAxB,MAAM,CACd;QAAkD,QAAQ,EAAlD,OAAO,kBAAkB,EAAE,QAAQ,CAC3C;QAAkD,QAAQ,EAAlD,OAAO,kBAAkB,EAAE,QAAQ,CAC3C;QAAqB,eAAe,EAA5B,MAAM,CACd;KAEkH,GAFxG,OAAO,CAAC,IAAI,CAAC,CAmCzB;IAED;;;;;OAKG;IACG,SAAS,CAAC,SAAS,EAJd,MAIc,EAAE,OAAO,EAHvB,MAGuB,GAFrB,OAAO,CAAC,IAAI,CAAC,CAIzB;CACF"}
|