@fluidframework/test-utils 2.0.0-internal.2.4.0 → 2.0.0-internal.3.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/dist/TestSummaryUtils.js +4 -4
- package/dist/TestSummaryUtils.js.map +1 -1
- package/dist/loaderContainerTracker.d.ts +0 -4
- package/dist/loaderContainerTracker.d.ts.map +1 -1
- package/dist/loaderContainerTracker.js +2 -11
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/testContainerRuntimeFactory.d.ts +2 -2
- package/dist/testObjectProvider.d.ts.map +1 -1
- package/dist/testObjectProvider.js +3 -5
- package/dist/testObjectProvider.js.map +1 -1
- package/dist/timeoutUtils.d.ts +12 -0
- package/dist/timeoutUtils.d.ts.map +1 -1
- package/dist/timeoutUtils.js +127 -12
- package/dist/timeoutUtils.js.map +1 -1
- package/package.json +28 -23
- package/src/TestSummaryUtils.ts +4 -4
- package/src/loaderContainerTracker.ts +0 -11
- package/src/packageVersion.ts +1 -1
- package/src/testObjectProvider.ts +14 -15
- package/src/timeoutUtils.ts +157 -14
- package/tsconfig.json +5 -2
package/dist/timeoutUtils.d.ts
CHANGED
|
@@ -2,18 +2,30 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import { Container } from "@fluidframework/container-loader";
|
|
5
6
|
export declare const defaultTimeoutDurationMs = 250;
|
|
6
7
|
export interface TimeoutWithError {
|
|
8
|
+
/**
|
|
9
|
+
* Timeout duration in milliseconds, if it is great than 0 and not Infinity
|
|
10
|
+
* If it is undefined, then it will use test timeout if we are in side the test function
|
|
11
|
+
* Otherwise, there is no timeout
|
|
12
|
+
*/
|
|
7
13
|
durationMs?: number;
|
|
8
14
|
reject?: true;
|
|
9
15
|
errorMsg?: string;
|
|
10
16
|
}
|
|
11
17
|
export interface TimeoutWithValue<T = void> {
|
|
18
|
+
/**
|
|
19
|
+
* Timeout duration in milliseconds, if it is great than 0 and not Infinity
|
|
20
|
+
* If it is undefined, then it will use test timeout if we are in side the test function
|
|
21
|
+
* Otherwise, there is no timeout
|
|
22
|
+
*/
|
|
12
23
|
durationMs?: number;
|
|
13
24
|
reject: false;
|
|
14
25
|
value: T;
|
|
15
26
|
}
|
|
16
27
|
export declare type PromiseExecutor<T = void> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;
|
|
17
28
|
export declare function timeoutAwait<T = void>(promise: PromiseLike<T>, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
|
|
29
|
+
export declare function ensureContainerConnected(container: Container): Promise<void>;
|
|
18
30
|
export declare function timeoutPromise<T = void>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
|
|
19
31
|
//# sourceMappingURL=timeoutUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAI7D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AA2F5C,MAAM,WAAW,gBAAgB;IAC7B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACZ;AAED,oBAAY,eAAe,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC;AAE/H,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EACvC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG9D;AAED,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlF;AAqCD,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,EAChG,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GAC5D,OAAO,CAAC,CAAC,CAAC,CAyBZ"}
|
package/dist/timeoutUtils.js
CHANGED
|
@@ -4,25 +4,111 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
|
|
7
|
+
exports.timeoutPromise = exports.ensureContainerConnected = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
|
|
8
|
+
const common_utils_1 = require("@fluidframework/common-utils");
|
|
9
|
+
// @deprecated this value is no longer used
|
|
8
10
|
exports.defaultTimeoutDurationMs = 250;
|
|
11
|
+
// TestTimeout class manage tracking of test timeout. It create a timer when timeout is in effect,
|
|
12
|
+
// and provide a promise that will be reject before the test timeout happen with a `timeBuffer` of 15 ms.
|
|
13
|
+
// Once rejected, a new TestTimeout object will be create for the timeout.
|
|
14
|
+
const timeBuffer = 15; // leave 15 ms leeway for finish processing
|
|
15
|
+
class TestTimeout {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.timeout = 0;
|
|
18
|
+
this.rejected = false;
|
|
19
|
+
this.deferred = new common_utils_1.Deferred();
|
|
20
|
+
// Ignore rejection for timeout promise if no one is waiting for it.
|
|
21
|
+
this.deferred.promise.catch(() => { });
|
|
22
|
+
}
|
|
23
|
+
static reset(runnable) {
|
|
24
|
+
TestTimeout.clear();
|
|
25
|
+
TestTimeout.instance.resetTimer(runnable);
|
|
26
|
+
}
|
|
27
|
+
static clear() {
|
|
28
|
+
if (TestTimeout.instance.rejected) {
|
|
29
|
+
TestTimeout.instance = new TestTimeout();
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
TestTimeout.instance.clearTimer();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
static getInstance() {
|
|
36
|
+
return TestTimeout.instance;
|
|
37
|
+
}
|
|
38
|
+
async getPromise() {
|
|
39
|
+
return this.deferred.promise;
|
|
40
|
+
}
|
|
41
|
+
getTimeout() {
|
|
42
|
+
return this.timeout;
|
|
43
|
+
}
|
|
44
|
+
resetTimer(runnable) {
|
|
45
|
+
(0, common_utils_1.assert)(!this.timer, "clearTimer should have been called before reset");
|
|
46
|
+
(0, common_utils_1.assert)(!this.deferred.isCompleted, "can't reset a completed TestTimeout");
|
|
47
|
+
// Check the test timeout setting
|
|
48
|
+
const timeout = runnable.timeout();
|
|
49
|
+
if (!(Number.isFinite(timeout) && timeout > 0)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// subtract a buffer
|
|
53
|
+
this.timeout = Math.max(timeout - timeBuffer, 1);
|
|
54
|
+
// Set up timer to reject near the test timeout.
|
|
55
|
+
this.timer = setTimeout(() => {
|
|
56
|
+
this.deferred.reject(this);
|
|
57
|
+
this.rejected = true;
|
|
58
|
+
}, this.timeout);
|
|
59
|
+
}
|
|
60
|
+
clearTimer() {
|
|
61
|
+
if (this.timer) {
|
|
62
|
+
clearTimeout(this.timer);
|
|
63
|
+
this.timer = undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
TestTimeout.instance = new TestTimeout();
|
|
68
|
+
// only register if we are running with mocha-test-setup loaded
|
|
69
|
+
if (globalThis.getMochaModule !== undefined) {
|
|
70
|
+
// patching resetTimeout and clearTimeout on the runnable object
|
|
71
|
+
// so we can track when test timeout are enforced
|
|
72
|
+
const mochaModule = globalThis.getMochaModule();
|
|
73
|
+
const runnablePrototype = mochaModule.Runnable.prototype;
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
75
|
+
const oldResetTimeoutFunc = runnablePrototype.resetTimeout;
|
|
76
|
+
runnablePrototype.resetTimeout = function () {
|
|
77
|
+
oldResetTimeoutFunc.call(this);
|
|
78
|
+
TestTimeout.reset(this);
|
|
79
|
+
};
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
81
|
+
const oldClearTimeoutFunc = runnablePrototype.clearTimeout;
|
|
82
|
+
runnablePrototype.clearTimeout = function () {
|
|
83
|
+
TestTimeout.clear();
|
|
84
|
+
oldClearTimeoutFunc.call(this);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
9
87
|
async function timeoutAwait(promise, timeoutOptions = {}) {
|
|
10
88
|
return Promise.race([promise, timeoutPromise(() => { }, timeoutOptions)]);
|
|
11
89
|
}
|
|
12
90
|
exports.timeoutAwait = timeoutAwait;
|
|
13
|
-
async function
|
|
91
|
+
async function ensureContainerConnected(container) {
|
|
92
|
+
if (!container.connected) {
|
|
93
|
+
return timeoutPromise((resolve) => container.once("connected", () => resolve()));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.ensureContainerConnected = ensureContainerConnected;
|
|
97
|
+
// Create a promise based on the timeout options
|
|
98
|
+
async function getTimeoutPromise(executor, timeoutOptions, err) {
|
|
14
99
|
var _a;
|
|
15
|
-
const timeout = timeoutOptions.durationMs !==
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// create the timeout error outside the async task, so its callstack includes
|
|
20
|
-
// the original call site, this makes it easier to debug
|
|
21
|
-
const err = timeoutOptions.reject === false
|
|
22
|
-
? undefined
|
|
23
|
-
: new Error(`${(_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "Timed out"}(${timeout}ms)`);
|
|
100
|
+
const timeout = (_a = timeoutOptions.durationMs) !== null && _a !== void 0 ? _a : 0;
|
|
101
|
+
if (timeout <= 0 || !Number.isFinite(timeout)) {
|
|
102
|
+
return new Promise(executor);
|
|
103
|
+
}
|
|
24
104
|
return new Promise((resolve, reject) => {
|
|
25
|
-
const
|
|
105
|
+
const timeoutRejections = () => {
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
107
|
+
const errorObject = err;
|
|
108
|
+
errorObject.message = `${errorObject.message} (${timeout}ms)`;
|
|
109
|
+
reject(err);
|
|
110
|
+
};
|
|
111
|
+
const timer = setTimeout(() => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : timeoutRejections(), timeout);
|
|
26
112
|
executor((value) => {
|
|
27
113
|
clearTimeout(timer);
|
|
28
114
|
resolve(value);
|
|
@@ -32,5 +118,34 @@ async function timeoutPromise(executor, timeoutOptions = {}) {
|
|
|
32
118
|
});
|
|
33
119
|
});
|
|
34
120
|
}
|
|
121
|
+
// Create a promise based on test timeout and the timeout options
|
|
122
|
+
async function timeoutPromise(executor, timeoutOptions = {}) {
|
|
123
|
+
var _a;
|
|
124
|
+
// create the timeout error outside the async task, so its callstack includes
|
|
125
|
+
// the original call site, this makes it easier to debug
|
|
126
|
+
const err = timeoutOptions.reject === false
|
|
127
|
+
? undefined
|
|
128
|
+
: new Error((_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "Timed out");
|
|
129
|
+
const executorPromise = getTimeoutPromise(executor, timeoutOptions, err);
|
|
130
|
+
const currentTestTimeout = TestTimeout.getInstance();
|
|
131
|
+
if (currentTestTimeout === undefined) {
|
|
132
|
+
return executorPromise;
|
|
133
|
+
}
|
|
134
|
+
return Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {
|
|
135
|
+
var _a;
|
|
136
|
+
if (e === currentTestTimeout) {
|
|
137
|
+
if (timeoutOptions.reject !== false) {
|
|
138
|
+
// If the rejection is because of the timeout then
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
140
|
+
const errorObject = err;
|
|
141
|
+
errorObject.message =
|
|
142
|
+
`${(_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "Test timed out"} (${currentTestTimeout.getTimeout()}ms)`;
|
|
143
|
+
throw errorObject;
|
|
144
|
+
}
|
|
145
|
+
return timeoutOptions.value;
|
|
146
|
+
}
|
|
147
|
+
throw e;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
35
150
|
exports.timeoutPromise = timeoutPromise;
|
|
36
151
|
//# sourceMappingURL=timeoutUtils.js.map
|
package/dist/timeoutUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEU,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAerC,KAAK,UAAU,YAAY,CAC9B,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAG,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AALD,oCAKC;AAEM,KAAK,UAAU,cAAc,CAChC,QAAgG,EAChG,iBAAyD,EAAE;;IAE3D,MAAM,OAAO,GACT,cAAc,CAAC,UAAU,KAAK,SAAS;WACpC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC;WAC1C,cAAc,CAAC,UAAU,GAAG,CAAC;QAC5B,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,gCAAwB,CAAC;IAC/D,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,MAAA,cAAc,CAAC,QAAQ,mCAAI,WAAW,IAAI,OAAO,KAAK,CAAC,CAAC;IAC3E,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,KAAK,GAAG,UAAU,CACpB,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EACnF,OAAO,CAAC,CAAC;QAEb,QAAQ,CACJ,CAAC,KAAK,EAAE,EAAE;YACN,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACP,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC;AA7BD,wCA6BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const defaultTimeoutDurationMs = 250;\n\nexport interface TimeoutWithError {\n durationMs?: number;\n reject?: true;\n errorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n durationMs?: number;\n reject: false;\n value: T;\n}\n\nexport type PromiseExecutor<T = void> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;\n\nexport async function timeoutAwait<T = void>(\n promise: PromiseLike<T>,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n return Promise.race([promise, timeoutPromise<T>(() => { }, timeoutOptions)]);\n}\n\nexport async function timeoutPromise<T = void>(\n executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n const timeout =\n timeoutOptions.durationMs !== undefined\n && Number.isFinite(timeoutOptions.durationMs)\n && timeoutOptions.durationMs > 0\n ? timeoutOptions.durationMs : defaultTimeoutDurationMs;\n // create the timeout error outside the async task, so its callstack includes\n // the original call site, this makes it easier to debug\n const err = timeoutOptions.reject === false\n ? undefined\n : new Error(`${timeoutOptions.errorMsg ?? \"Timed out\"}(${timeout}ms)`);\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),\n timeout);\n\n executor(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (reason) => {\n clearTimeout(timer);\n reject(reason);\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Container } from \"@fluidframework/container-loader\";\nimport { assert, Deferred } from \"@fluidframework/common-utils\";\n\n// @deprecated this value is no longer used\nexport const defaultTimeoutDurationMs = 250;\n\n// TestTimeout class manage tracking of test timeout. It create a timer when timeout is in effect,\n// and provide a promise that will be reject before the test timeout happen with a `timeBuffer` of 15 ms.\n// Once rejected, a new TestTimeout object will be create for the timeout.\n\nconst timeBuffer = 15; // leave 15 ms leeway for finish processing\n\nclass TestTimeout {\n private timeout: number = 0;\n private timer: NodeJS.Timeout | undefined;\n private readonly deferred: Deferred<void>;\n private rejected = false;\n\n private static instance: TestTimeout = new TestTimeout();\n public static reset(runnable: Mocha.Runnable) {\n TestTimeout.clear();\n TestTimeout.instance.resetTimer(runnable);\n }\n\n public static clear() {\n if (TestTimeout.instance.rejected) {\n TestTimeout.instance = new TestTimeout();\n } else {\n TestTimeout.instance.clearTimer();\n }\n }\n\n public static getInstance() {\n return TestTimeout.instance;\n }\n\n public async getPromise() {\n return this.deferred.promise;\n }\n\n public getTimeout() {\n return this.timeout;\n }\n\n private constructor() {\n this.deferred = new Deferred();\n // Ignore rejection for timeout promise if no one is waiting for it.\n this.deferred.promise.catch(() => { });\n }\n\n private resetTimer(runnable: Mocha.Runnable) {\n assert(!this.timer, \"clearTimer should have been called before reset\");\n assert(!this.deferred.isCompleted, \"can't reset a completed TestTimeout\");\n\n // Check the test timeout setting\n const timeout = runnable.timeout();\n if (!(Number.isFinite(timeout) && timeout > 0)) { return; }\n\n // subtract a buffer\n this.timeout = Math.max(timeout - timeBuffer, 1);\n\n // Set up timer to reject near the test timeout.\n this.timer = setTimeout(() => {\n this.deferred.reject(this);\n this.rejected = true;\n }, this.timeout);\n }\n private clearTimer() {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n}\n\n// only register if we are running with mocha-test-setup loaded\nif (globalThis.getMochaModule !== undefined) {\n // patching resetTimeout and clearTimeout on the runnable object\n // so we can track when test timeout are enforced\n const mochaModule = globalThis.getMochaModule() as typeof Mocha;\n const runnablePrototype = mochaModule.Runnable.prototype;\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const oldResetTimeoutFunc = runnablePrototype.resetTimeout;\n runnablePrototype.resetTimeout = function(this: Mocha.Runnable) {\n oldResetTimeoutFunc.call(this);\n TestTimeout.reset(this);\n };\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const oldClearTimeoutFunc = runnablePrototype.clearTimeout;\n runnablePrototype.clearTimeout = function(this: Mocha.Runnable) {\n TestTimeout.clear();\n oldClearTimeoutFunc.call(this);\n };\n}\n\nexport interface TimeoutWithError {\n /**\n * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n * If it is undefined, then it will use test timeout if we are in side the test function\n * Otherwise, there is no timeout\n */\n durationMs?: number;\n reject?: true;\n errorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n /**\n * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n * If it is undefined, then it will use test timeout if we are in side the test function\n * Otherwise, there is no timeout\n */\n durationMs?: number;\n reject: false;\n value: T;\n}\n\nexport type PromiseExecutor<T = void> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;\n\nexport async function timeoutAwait<T = void>(\n promise: PromiseLike<T>,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n return Promise.race([promise, timeoutPromise<T>(() => { }, timeoutOptions)]);\n}\n\nexport async function ensureContainerConnected(container: Container): Promise<void> {\n if (!container.connected) {\n return timeoutPromise((resolve) => container.once(\"connected\", () => resolve()));\n }\n}\n\n// Create a promise based on the timeout options\nasync function getTimeoutPromise<T = void>(\n executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T>,\n err: Error | undefined,\n) {\n const timeout = timeoutOptions.durationMs ?? 0;\n if (timeout <= 0 || !Number.isFinite(timeout)) {\n return new Promise(executor);\n }\n\n return new Promise<T>((resolve, reject) => {\n const timeoutRejections = () => {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const errorObject = err!;\n errorObject.message = `${errorObject.message} (${timeout}ms)`;\n reject(err);\n };\n const timer = setTimeout(\n () => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : timeoutRejections(),\n timeout);\n\n executor(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (reason) => {\n clearTimeout(timer);\n reject(reason);\n });\n });\n}\n\n// Create a promise based on test timeout and the timeout options\nexport async function timeoutPromise<T = void>(\n executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n // create the timeout error outside the async task, so its callstack includes\n // the original call site, this makes it easier to debug\n const err = timeoutOptions.reject === false\n ? undefined\n : new Error(timeoutOptions.errorMsg ?? \"Timed out\");\n const executorPromise = getTimeoutPromise(executor, timeoutOptions, err);\n\n const currentTestTimeout = TestTimeout.getInstance();\n if (currentTestTimeout === undefined) { return executorPromise; }\n\n return Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {\n if (e === currentTestTimeout) {\n if (timeoutOptions.reject !== false) {\n // If the rejection is because of the timeout then\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const errorObject = err!;\n errorObject.message =\n `${timeoutOptions.errorMsg ?? \"Test timed out\"} (${currentTestTimeout.getTimeout()}ms)`;\n throw errorObject;\n }\n return timeoutOptions.value;\n }\n throw e;\n }) as Promise<T>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/test-utils",
|
|
3
|
-
"version": "2.0.0-internal.
|
|
3
|
+
"version": "2.0.0-internal.3.0.0",
|
|
4
4
|
"description": "Utilities for Fluid tests",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"lint:fix": "npm run eslint:fix",
|
|
33
33
|
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
34
34
|
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
35
|
+
"test": "npm run test:mocha",
|
|
36
|
+
"test:mocha": "mocha --unhandled-rejections=strict --recursive dist/test/*.spec.js --exit --project src/test/tsconfig.json -r node_modules/@fluidframework/mocha-test-setup",
|
|
37
|
+
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
35
38
|
"tsc": "tsc",
|
|
36
39
|
"typetests:gen": "flub generate typetests --generate --dir .",
|
|
37
40
|
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
@@ -57,28 +60,29 @@
|
|
|
57
60
|
"temp-directory": "nyc/.nyc_output"
|
|
58
61
|
},
|
|
59
62
|
"dependencies": {
|
|
60
|
-
"@fluidframework/aqueduct": ">=2.0.0-internal.
|
|
63
|
+
"@fluidframework/aqueduct": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
61
64
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
62
65
|
"@fluidframework/common-utils": "^1.0.0",
|
|
63
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.
|
|
64
|
-
"@fluidframework/container-loader": ">=2.0.0-internal.
|
|
65
|
-
"@fluidframework/container-runtime": ">=2.0.0-internal.
|
|
66
|
-
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.
|
|
67
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.
|
|
68
|
-
"@fluidframework/datastore": ">=2.0.0-internal.
|
|
69
|
-
"@fluidframework/datastore-definitions": ">=2.0.0-internal.
|
|
70
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.
|
|
71
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.
|
|
72
|
-
"@fluidframework/local-driver": ">=2.0.0-internal.
|
|
73
|
-
"@fluidframework/map": ">=2.0.0-internal.
|
|
66
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
67
|
+
"@fluidframework/container-loader": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
68
|
+
"@fluidframework/container-runtime": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
69
|
+
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
70
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
71
|
+
"@fluidframework/datastore": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
72
|
+
"@fluidframework/datastore-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
73
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
74
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
75
|
+
"@fluidframework/local-driver": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
76
|
+
"@fluidframework/map": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
77
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
74
78
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
75
|
-
"@fluidframework/request-handler": ">=2.0.0-internal.
|
|
76
|
-
"@fluidframework/routerlicious-driver": ">=2.0.0-internal.
|
|
77
|
-
"@fluidframework/runtime-definitions": ">=2.0.0-internal.
|
|
78
|
-
"@fluidframework/runtime-utils": ">=2.0.0-internal.
|
|
79
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.
|
|
80
|
-
"@fluidframework/test-driver-definitions": ">=2.0.0-internal.
|
|
81
|
-
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.
|
|
79
|
+
"@fluidframework/request-handler": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
80
|
+
"@fluidframework/routerlicious-driver": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
81
|
+
"@fluidframework/runtime-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
82
|
+
"@fluidframework/runtime-utils": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
83
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
84
|
+
"@fluidframework/test-driver-definitions": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
85
|
+
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.3.0.0 <2.0.0-internal.4.0.0",
|
|
82
86
|
"best-random": "^1.0.0",
|
|
83
87
|
"debug": "^4.1.1",
|
|
84
88
|
"uuid": "^8.3.1"
|
|
@@ -98,6 +102,7 @@
|
|
|
98
102
|
"@types/uuid": "^8.3.0",
|
|
99
103
|
"concurrently": "^6.2.0",
|
|
100
104
|
"copyfiles": "^2.4.1",
|
|
105
|
+
"cross-env": "^7.0.2",
|
|
101
106
|
"diff": "^3.5.0",
|
|
102
107
|
"eslint": "~8.6.0",
|
|
103
108
|
"mocha": "^10.0.0",
|
|
@@ -108,9 +113,9 @@
|
|
|
108
113
|
"typescript": "~4.5.5"
|
|
109
114
|
},
|
|
110
115
|
"typeValidation": {
|
|
111
|
-
"version": "2.0.0-internal.
|
|
112
|
-
"baselineRange": ">=2.0.0-internal.2.
|
|
113
|
-
"baselineVersion": "2.0.0-internal.2.
|
|
116
|
+
"version": "2.0.0-internal.3.0.0",
|
|
117
|
+
"baselineRange": ">=2.0.0-internal.2.0.0 <2.0.0-internal.3.0.0",
|
|
118
|
+
"baselineVersion": "2.0.0-internal.2.1.1",
|
|
114
119
|
"broken": {}
|
|
115
120
|
}
|
|
116
121
|
}
|
package/src/TestSummaryUtils.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
|
|
|
24
24
|
import { ITestContainerConfig, ITestObjectProvider } from "./testObjectProvider";
|
|
25
25
|
import { mockConfigProvider } from "./TestConfigs";
|
|
26
26
|
import { waitForContainerConnection } from "./containerUtils";
|
|
27
|
+
import { timeoutAwait } from "./timeoutUtils";
|
|
27
28
|
|
|
28
29
|
const summarizerClientType = "summarizer";
|
|
29
30
|
|
|
@@ -65,7 +66,6 @@ const defaultSummaryOptions: ISummaryRuntimeOptions = {
|
|
|
65
66
|
maxAckWaitTime: 10000,
|
|
66
67
|
maxOpsSinceLastSummary: 7000,
|
|
67
68
|
initialSummarizerDelayMs: 0,
|
|
68
|
-
summarizerClientElection: false,
|
|
69
69
|
},
|
|
70
70
|
};
|
|
71
71
|
|
|
@@ -142,16 +142,16 @@ export async function createSummarizerWithContainer(
|
|
|
142
142
|
export async function summarizeNow(summarizer: ISummarizer, reason: string = "end-to-end test") {
|
|
143
143
|
const result = summarizer.summarizeOnDemand({ reason });
|
|
144
144
|
|
|
145
|
-
const submitResult = await result.summarySubmitted;
|
|
145
|
+
const submitResult = await timeoutAwait(result.summarySubmitted);
|
|
146
146
|
assert(submitResult.success, "on-demand summary should submit");
|
|
147
147
|
assert(submitResult.data.stage === "submit",
|
|
148
148
|
"on-demand summary submitted data stage should be submit");
|
|
149
149
|
assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
|
|
150
150
|
|
|
151
|
-
const broadcastResult = await result.summaryOpBroadcasted;
|
|
151
|
+
const broadcastResult = await timeoutAwait(result.summaryOpBroadcasted);
|
|
152
152
|
assert(broadcastResult.success, "summary op should be broadcast");
|
|
153
153
|
|
|
154
|
-
const ackNackResult = await result.receivedSummaryAckOrNack;
|
|
154
|
+
const ackNackResult = await timeoutAwait(result.receivedSummaryAckOrNack);
|
|
155
155
|
assert(ackNackResult.success, "summary op should be acked");
|
|
156
156
|
|
|
157
157
|
await new Promise((resolve) => process.nextTick(resolve));
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
|
|
6
|
-
|
|
7
5
|
import { assert } from "@fluidframework/common-utils";
|
|
8
6
|
import { IContainer, IDeltaQueue, IHostLoader } from "@fluidframework/container-definitions";
|
|
9
7
|
import { Container } from "@fluidframework/container-loader";
|
|
@@ -16,9 +14,6 @@ import { timeoutAwait, timeoutPromise } from "./timeoutUtils";
|
|
|
16
14
|
const debugOp = debug.extend("ops");
|
|
17
15
|
const debugWait = debug.extend("wait");
|
|
18
16
|
|
|
19
|
-
// set the maximum timeout value as 5 mins
|
|
20
|
-
const defaultMaxTimeout = 5 * 6000;
|
|
21
|
-
|
|
22
17
|
interface ContainerRecord {
|
|
23
18
|
// A short number for debug output
|
|
24
19
|
index: number;
|
|
@@ -187,7 +182,6 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
187
182
|
* - Trailing NoOp is tracked and don't count as pending ops.
|
|
188
183
|
*/
|
|
189
184
|
private async processSynchronized(timeoutDuration: number | undefined, ...containers: IContainer[]) {
|
|
190
|
-
const start = Date.now();
|
|
191
185
|
const resumed = this.resumeProcessing(...containers);
|
|
192
186
|
|
|
193
187
|
let waitingSequenceNumberSynchronized = false;
|
|
@@ -214,14 +208,12 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
214
208
|
waitingSequenceNumberSynchronized = true;
|
|
215
209
|
debugWait("Waiting for sequence number synchronized");
|
|
216
210
|
await timeoutAwait(this.waitForAnyInboundOps(containersToApply), {
|
|
217
|
-
durationMs: timeoutDuration ? timeoutDuration - (Date.now() - start) : defaultMaxTimeout,
|
|
218
211
|
errorMsg: "Timeout on waiting for sequence number synchronized",
|
|
219
212
|
});
|
|
220
213
|
}
|
|
221
214
|
} else {
|
|
222
215
|
waitingSequenceNumberSynchronized = false;
|
|
223
216
|
await timeoutAwait(this.waitForPendingClients(pendingClients), {
|
|
224
|
-
durationMs: timeoutDuration ? timeoutDuration - (Date.now() - start) : defaultMaxTimeout,
|
|
225
217
|
errorMsg: "Timeout on waiting for pending join or leave op",
|
|
226
218
|
});
|
|
227
219
|
}
|
|
@@ -230,12 +222,10 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
230
222
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
231
223
|
debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);
|
|
232
224
|
waitingSequenceNumberSynchronized = false;
|
|
233
|
-
const remainedDuration = timeoutDuration ? timeoutDuration - (Date.now() - start) : defaultMaxTimeout;
|
|
234
225
|
await Promise.all(dirtyContainers.map(async (c) => Promise.race(
|
|
235
226
|
[timeoutPromise(
|
|
236
227
|
(resolve) => c.once("saved", () => resolve()),
|
|
237
228
|
{
|
|
238
|
-
durationMs: remainedDuration,
|
|
239
229
|
errorMsg: "Timeout on waiting a container to be saved",
|
|
240
230
|
},
|
|
241
231
|
),
|
|
@@ -252,7 +242,6 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
252
242
|
// don't call pause if resumed is empty and pause everything, which is not what we want
|
|
253
243
|
if (resumed.length !== 0) {
|
|
254
244
|
await timeoutAwait(this.pauseProcessing(...resumed), {
|
|
255
|
-
durationMs: timeoutDuration ? timeoutDuration - (Date.now() - start) : defaultMaxTimeout,
|
|
256
245
|
errorMsg: "Timeout on waiting for pausing all resumed containers",
|
|
257
246
|
});
|
|
258
247
|
}
|
package/src/packageVersion.ts
CHANGED
|
@@ -149,7 +149,7 @@ export class EventAndErrorTrackingLogger extends TelemetryLogger {
|
|
|
149
149
|
private readonly expectedEvents: ({ index: number; event: ITelemetryGenericEvent | undefined; } | undefined)[] = [];
|
|
150
150
|
private readonly unexpectedErrors: ITelemetryBaseEvent[] = [];
|
|
151
151
|
|
|
152
|
-
public registerExpectedEvent(...
|
|
152
|
+
public registerExpectedEvent(...orderedExpectedEvents: ITelemetryGenericEvent[]) {
|
|
153
153
|
if (this.expectedEvents.length !== 0) {
|
|
154
154
|
// we don't have to error here. just no reason not to. given the events must be
|
|
155
155
|
// ordered it could be tricky to figure out problems around multiple registrations.
|
|
@@ -157,7 +157,7 @@ export class EventAndErrorTrackingLogger extends TelemetryLogger {
|
|
|
157
157
|
"Expected events already registered.\n"
|
|
158
158
|
+ "Call reportAndClearTrackedEvents to clear them before registering more");
|
|
159
159
|
}
|
|
160
|
-
this.expectedEvents.push(...
|
|
160
|
+
this.expectedEvents.push(...orderedExpectedEvents.map((event, index) => ({ index, event })));
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
send(event: ITelemetryBaseEvent): void {
|
|
@@ -232,14 +232,14 @@ export class TestObjectProvider implements ITestObjectProvider {
|
|
|
232
232
|
if (this._logger === undefined) {
|
|
233
233
|
this._logger = new EventAndErrorTrackingLogger(
|
|
234
234
|
ChildLogger.create(getTestLogger?.(), undefined,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
235
|
+
{
|
|
236
|
+
all: {
|
|
237
|
+
driverType: this.driver.type,
|
|
238
|
+
driverEndpointName: this.driver.endpointName,
|
|
239
|
+
driverTenantName: this.driver.tenantName,
|
|
240
|
+
driverUserIndex: this.driver.userIndex,
|
|
241
|
+
},
|
|
242
|
+
}));
|
|
243
243
|
}
|
|
244
244
|
return this._logger;
|
|
245
245
|
}
|
|
@@ -293,7 +293,7 @@ export class TestObjectProvider implements ITestObjectProvider {
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
const loader = new this.LoaderConstructor({
|
|
296
|
-
...
|
|
296
|
+
...loaderProps,
|
|
297
297
|
logger: multiSinkLogger,
|
|
298
298
|
codeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),
|
|
299
299
|
urlResolver: loaderProps?.urlResolver ?? this.urlResolver,
|
|
@@ -407,10 +407,9 @@ export class TestObjectProvider implements ITestObjectProvider {
|
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
public async ensureSynchronized(timeoutDuration?: number): Promise<void> {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
: this._loaderContainerTracker.ensureSynchronizedWithTimeout?.(timeoutDuration);
|
|
410
|
+
return this._loaderContainerTracker.ensureSynchronizedWithTimeout
|
|
411
|
+
? this._loaderContainerTracker.ensureSynchronizedWithTimeout(timeoutDuration)
|
|
412
|
+
: this._loaderContainerTracker.ensureSynchronized();
|
|
414
413
|
}
|
|
415
414
|
|
|
416
415
|
public async waitContainerToCatchUp(container: IContainer) {
|