@fluidframework/test-utils 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.1.0.148229
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/TestConfigs.d.ts.map +1 -1
- package/dist/TestConfigs.js +0 -2
- package/dist/TestConfigs.js.map +1 -1
- package/dist/TestSummaryUtils.d.ts +14 -3
- package/dist/TestSummaryUtils.d.ts.map +1 -1
- package/dist/TestSummaryUtils.js +24 -16
- package/dist/TestSummaryUtils.js.map +1 -1
- package/dist/containerUtils.d.ts +10 -19
- package/dist/containerUtils.d.ts.map +1 -1
- package/dist/containerUtils.js +12 -25
- package/dist/containerUtils.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/loaderContainerTracker.d.ts +3 -5
- package/dist/loaderContainerTracker.d.ts.map +1 -1
- package/dist/loaderContainerTracker.js +6 -9
- 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/testObjectProvider.d.ts +4 -1
- package/dist/testObjectProvider.d.ts.map +1 -1
- package/dist/testObjectProvider.js +39 -11
- package/dist/testObjectProvider.js.map +1 -1
- package/dist/timeoutUtils.d.ts +0 -2
- package/dist/timeoutUtils.d.ts.map +1 -1
- package/dist/timeoutUtils.js +1 -7
- package/dist/timeoutUtils.js.map +1 -1
- package/package.json +62 -63
- package/src/TestConfigs.ts +0 -2
- package/src/TestSummaryUtils.ts +23 -30
- package/src/containerUtils.ts +12 -25
- package/src/index.ts +2 -7
- package/src/loaderContainerTracker.ts +11 -21
- package/src/packageVersion.ts +1 -1
- package/src/testObjectProvider.ts +55 -12
- package/src/timeoutUtils.ts +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/test-utils",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.4.1.0.148229",
|
|
4
4
|
"description": "Utilities for Fluid tests",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -14,31 +14,6 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"module": "lib/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
|
-
"scripts": {
|
|
18
|
-
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
19
|
-
"build:compile": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
20
|
-
"build:compile:min": "npm run build:compile",
|
|
21
|
-
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
22
|
-
"build:full": "npm run build",
|
|
23
|
-
"build:full:compile": "npm run build:compile",
|
|
24
|
-
"build:genver": "gen-version",
|
|
25
|
-
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
26
|
-
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
27
|
-
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
28
|
-
"eslint": "eslint --format stylish src",
|
|
29
|
-
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
30
|
-
"format": "npm run prettier:fix",
|
|
31
|
-
"lint": "npm run prettier && npm run eslint",
|
|
32
|
-
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
33
|
-
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
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",
|
|
38
|
-
"tsc": "tsc",
|
|
39
|
-
"typetests:gen": "flub generate typetests --generate --dir .",
|
|
40
|
-
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
41
|
-
},
|
|
42
17
|
"nyc": {
|
|
43
18
|
"all": true,
|
|
44
19
|
"cache-dir": "nyc/.cache",
|
|
@@ -60,64 +35,88 @@
|
|
|
60
35
|
"temp-directory": "nyc/.nyc_output"
|
|
61
36
|
},
|
|
62
37
|
"dependencies": {
|
|
63
|
-
"@fluidframework/aqueduct": "
|
|
38
|
+
"@fluidframework/aqueduct": "2.0.0-dev.4.1.0.148229",
|
|
64
39
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
65
|
-
"@fluidframework/common-utils": "^1.
|
|
66
|
-
"@fluidframework/container-definitions": "
|
|
67
|
-
"@fluidframework/container-loader": "
|
|
68
|
-
"@fluidframework/container-runtime": "
|
|
69
|
-
"@fluidframework/container-runtime-definitions": "
|
|
70
|
-
"@fluidframework/core-interfaces": "
|
|
71
|
-
"@fluidframework/datastore": "
|
|
72
|
-
"@fluidframework/datastore-definitions": "
|
|
73
|
-
"@fluidframework/driver-definitions": "
|
|
74
|
-
"@fluidframework/driver-utils": "
|
|
75
|
-
"@fluidframework/local-driver": "
|
|
76
|
-
"@fluidframework/map": "
|
|
77
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
40
|
+
"@fluidframework/common-utils": "^1.1.1",
|
|
41
|
+
"@fluidframework/container-definitions": "2.0.0-dev.4.1.0.148229",
|
|
42
|
+
"@fluidframework/container-loader": "2.0.0-dev.4.1.0.148229",
|
|
43
|
+
"@fluidframework/container-runtime": "2.0.0-dev.4.1.0.148229",
|
|
44
|
+
"@fluidframework/container-runtime-definitions": "2.0.0-dev.4.1.0.148229",
|
|
45
|
+
"@fluidframework/core-interfaces": "2.0.0-dev.4.1.0.148229",
|
|
46
|
+
"@fluidframework/datastore": "2.0.0-dev.4.1.0.148229",
|
|
47
|
+
"@fluidframework/datastore-definitions": "2.0.0-dev.4.1.0.148229",
|
|
48
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.4.1.0.148229",
|
|
49
|
+
"@fluidframework/driver-utils": "2.0.0-dev.4.1.0.148229",
|
|
50
|
+
"@fluidframework/local-driver": "2.0.0-dev.4.1.0.148229",
|
|
51
|
+
"@fluidframework/map": "2.0.0-dev.4.1.0.148229",
|
|
78
52
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
79
|
-
"@fluidframework/request-handler": "
|
|
80
|
-
"@fluidframework/routerlicious-driver": "
|
|
81
|
-
"@fluidframework/runtime-definitions": "
|
|
82
|
-
"@fluidframework/runtime-utils": "
|
|
83
|
-
"@fluidframework/telemetry-utils": "
|
|
84
|
-
"@fluidframework/test-driver-definitions": "
|
|
85
|
-
"@fluidframework/test-runtime-utils": "
|
|
53
|
+
"@fluidframework/request-handler": "2.0.0-dev.4.1.0.148229",
|
|
54
|
+
"@fluidframework/routerlicious-driver": "2.0.0-dev.4.1.0.148229",
|
|
55
|
+
"@fluidframework/runtime-definitions": "2.0.0-dev.4.1.0.148229",
|
|
56
|
+
"@fluidframework/runtime-utils": "2.0.0-dev.4.1.0.148229",
|
|
57
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.4.1.0.148229",
|
|
58
|
+
"@fluidframework/test-driver-definitions": "2.0.0-dev.4.1.0.148229",
|
|
59
|
+
"@fluidframework/test-runtime-utils": "2.0.0-dev.4.1.0.148229",
|
|
86
60
|
"best-random": "^1.0.0",
|
|
87
61
|
"debug": "^4.1.1",
|
|
88
62
|
"uuid": "^8.3.1"
|
|
89
63
|
},
|
|
90
64
|
"devDependencies": {
|
|
91
|
-
"@fluid-tools/build-cli": "^0.
|
|
65
|
+
"@fluid-tools/build-cli": "^0.13.1",
|
|
92
66
|
"@fluidframework/build-common": "^1.1.0",
|
|
93
|
-
"@fluidframework/build-tools": "^0.
|
|
67
|
+
"@fluidframework/build-tools": "^0.13.1",
|
|
94
68
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
95
|
-
"@fluidframework/test-
|
|
96
|
-
"@
|
|
97
|
-
"@
|
|
69
|
+
"@fluidframework/mocha-test-setup": "2.0.0-dev.4.1.0.148229",
|
|
70
|
+
"@fluidframework/test-utils-previous": "npm:@fluidframework/test-utils@2.0.0-internal.4.0.0",
|
|
71
|
+
"@microsoft/api-extractor": "^7.34.4",
|
|
98
72
|
"@types/debug": "^4.1.5",
|
|
99
73
|
"@types/diff": "^3.5.1",
|
|
100
74
|
"@types/mocha": "^9.1.1",
|
|
101
|
-
"@types/node": "^14.18.
|
|
75
|
+
"@types/node": "^14.18.38",
|
|
102
76
|
"@types/random-js": "^1.0.31",
|
|
103
77
|
"@types/uuid": "^8.3.0",
|
|
104
|
-
"concurrently": "^6.
|
|
78
|
+
"concurrently": "^7.6.0",
|
|
105
79
|
"copyfiles": "^2.4.1",
|
|
106
|
-
"cross-env": "^7.0.
|
|
80
|
+
"cross-env": "^7.0.3",
|
|
107
81
|
"diff": "^3.5.0",
|
|
108
82
|
"eslint": "~8.6.0",
|
|
109
|
-
"mocha": "^10.
|
|
110
|
-
"
|
|
83
|
+
"mocha": "^10.2.0",
|
|
84
|
+
"mocha-json-output-reporter": "^2.0.1",
|
|
85
|
+
"mocha-multi-reporters": "^1.5.1",
|
|
86
|
+
"moment": "^2.21.0",
|
|
87
|
+
"nyc": "^15.1.0",
|
|
111
88
|
"prettier": "~2.6.2",
|
|
112
89
|
"random-js": "^1.0.8",
|
|
113
|
-
"rimraf": "^
|
|
90
|
+
"rimraf": "^4.4.0",
|
|
114
91
|
"typescript": "~4.5.5"
|
|
115
92
|
},
|
|
116
93
|
"typeValidation": {
|
|
117
|
-
"version": "2.0.0-internal.3.1.0",
|
|
118
|
-
"previousVersionStyle": "~previousMinor",
|
|
119
|
-
"baselineRange": ">=2.0.0-internal.3.0.0 <2.0.0-internal.3.1.0",
|
|
120
|
-
"baselineVersion": "2.0.0-internal.3.0.0",
|
|
121
94
|
"broken": {}
|
|
95
|
+
},
|
|
96
|
+
"scripts": {
|
|
97
|
+
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
98
|
+
"build:compile": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
99
|
+
"build:compile:min": "npm run build:compile",
|
|
100
|
+
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
101
|
+
"build:full": "npm run build",
|
|
102
|
+
"build:full:compile": "npm run build:compile",
|
|
103
|
+
"build:genver": "gen-version",
|
|
104
|
+
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
105
|
+
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
106
|
+
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
107
|
+
"eslint": "eslint --format stylish src",
|
|
108
|
+
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
109
|
+
"format": "npm run prettier:fix",
|
|
110
|
+
"lint": "npm run prettier && npm run eslint",
|
|
111
|
+
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
112
|
+
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
113
|
+
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
114
|
+
"test": "npm run test:mocha",
|
|
115
|
+
"test:mocha": "mocha --unhandled-rejections=strict --recursive dist/test/*.spec.js --exit --project src/test/tsconfig.json -r node_modules/@fluidframework/mocha-test-setup",
|
|
116
|
+
"test:mocha:multireport": "cross-env FLUID_TEST_MULTIREPORT=1 npm run test:mocha",
|
|
117
|
+
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
118
|
+
"tsc": "tsc",
|
|
119
|
+
"typetests:gen": "fluid-type-test-generator",
|
|
120
|
+
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
122
121
|
}
|
|
123
|
-
}
|
|
122
|
+
}
|
package/src/TestConfigs.ts
CHANGED
|
@@ -8,8 +8,6 @@ import { ConfigTypes, IConfigProviderBase } from "@fluidframework/telemetry-util
|
|
|
8
8
|
export const mockConfigProvider = (
|
|
9
9
|
settings: Record<string, ConfigTypes> = {},
|
|
10
10
|
): IConfigProviderBase => {
|
|
11
|
-
settings["Fluid.GarbageCollection.TrackGCState"] = "true";
|
|
12
|
-
settings["Fluid.GarbageCollection.WriteDataAtRoot"] = "true";
|
|
13
11
|
return {
|
|
14
12
|
getRawConfig: (name: string): ConfigTypes => settings[name],
|
|
15
13
|
};
|
package/src/TestSummaryUtils.ts
CHANGED
|
@@ -29,10 +29,11 @@ import { timeoutAwait } from "./timeoutUtils";
|
|
|
29
29
|
const summarizerClientType = "summarizer";
|
|
30
30
|
|
|
31
31
|
async function createSummarizerCore(
|
|
32
|
-
|
|
32
|
+
container: IContainer,
|
|
33
33
|
loader: IHostLoader,
|
|
34
34
|
summaryVersion?: string,
|
|
35
35
|
) {
|
|
36
|
+
const absoluteUrl = await container.getAbsoluteUrl("");
|
|
36
37
|
if (absoluteUrl === undefined) {
|
|
37
38
|
throw new Error("URL could not be resolved");
|
|
38
39
|
}
|
|
@@ -52,10 +53,12 @@ async function createSummarizerCore(
|
|
|
52
53
|
const summarizerContainer = await loader.resolve(request);
|
|
53
54
|
await waitForContainerConnection(summarizerContainer);
|
|
54
55
|
|
|
55
|
-
const fluidObject
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
const fluidObject: FluidObject<ISummarizer> | undefined = summarizerContainer.getEntryPoint
|
|
57
|
+
? await summarizerContainer.getEntryPoint?.()
|
|
58
|
+
: await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, {
|
|
59
|
+
url: "_summarizer",
|
|
60
|
+
});
|
|
61
|
+
if (fluidObject?.ISummarizer === undefined) {
|
|
59
62
|
throw new Error("Fluid object does not implement ISummarizer");
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -74,6 +77,11 @@ const defaultSummaryOptions: ISummaryRuntimeOptions = {
|
|
|
74
77
|
},
|
|
75
78
|
};
|
|
76
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Creates a summarizer client from the given container and data store factory, and returns the summarizer client's
|
|
82
|
+
* IContainer and ISummarizer.
|
|
83
|
+
* The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.
|
|
84
|
+
*/
|
|
77
85
|
export async function createSummarizerFromFactory(
|
|
78
86
|
provider: ITestObjectProvider,
|
|
79
87
|
container: IContainer,
|
|
@@ -81,7 +89,8 @@ export async function createSummarizerFromFactory(
|
|
|
81
89
|
summaryVersion?: string,
|
|
82
90
|
containerRuntimeFactoryType = ContainerRuntimeFactoryWithDefaultDataStore,
|
|
83
91
|
registryEntries?: NamedFluidDataStoreRegistryEntries,
|
|
84
|
-
|
|
92
|
+
logger?: ITelemetryBaseLogger,
|
|
93
|
+
): Promise<{ container: IContainer; summarizer: ISummarizer }> {
|
|
85
94
|
const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>
|
|
86
95
|
runtime.IFluidHandleContext.resolveHandle(request);
|
|
87
96
|
const runtimeFactory = new containerRuntimeFactoryType(
|
|
@@ -94,11 +103,15 @@ export async function createSummarizerFromFactory(
|
|
|
94
103
|
|
|
95
104
|
const loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], {
|
|
96
105
|
configProvider: mockConfigProvider(),
|
|
106
|
+
logger,
|
|
97
107
|
});
|
|
98
|
-
|
|
99
|
-
return (await createSummarizerCore(absoluteUrl, loader, summaryVersion)).summarizer;
|
|
108
|
+
return createSummarizerCore(container, loader, summaryVersion);
|
|
100
109
|
}
|
|
101
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Creates a summarizer client from the given container and returns the summarizer client's IContainer and ISummarizer.
|
|
113
|
+
* The ISummarizer can be used to generate on-demand summaries. The IContainer can be used to fetch data stores, etc.
|
|
114
|
+
*/
|
|
102
115
|
export async function createSummarizer(
|
|
103
116
|
provider: ITestObjectProvider,
|
|
104
117
|
container: IContainer,
|
|
@@ -106,27 +119,6 @@ export async function createSummarizer(
|
|
|
106
119
|
gcOptions?: IGCRuntimeOptions,
|
|
107
120
|
configProvider: IConfigProviderBase = mockConfigProvider(),
|
|
108
121
|
logger?: ITelemetryBaseLogger,
|
|
109
|
-
): Promise<ISummarizer> {
|
|
110
|
-
const absoluteUrl = await container.getAbsoluteUrl("");
|
|
111
|
-
return (
|
|
112
|
-
await createSummarizerWithContainer(
|
|
113
|
-
provider,
|
|
114
|
-
absoluteUrl,
|
|
115
|
-
summaryVersion,
|
|
116
|
-
gcOptions,
|
|
117
|
-
configProvider,
|
|
118
|
-
logger,
|
|
119
|
-
)
|
|
120
|
-
).summarizer;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export async function createSummarizerWithContainer(
|
|
124
|
-
provider: ITestObjectProvider,
|
|
125
|
-
absoluteUrl: string | undefined,
|
|
126
|
-
summaryVersion?: string,
|
|
127
|
-
gcOptions?: IGCRuntimeOptions,
|
|
128
|
-
configProvider: IConfigProviderBase = mockConfigProvider(),
|
|
129
|
-
logger?: ITelemetryBaseLogger,
|
|
130
122
|
): Promise<{ container: IContainer; summarizer: ISummarizer }> {
|
|
131
123
|
const testContainerConfig: ITestContainerConfig = {
|
|
132
124
|
runtimeOptions: {
|
|
@@ -136,8 +128,9 @@ export async function createSummarizerWithContainer(
|
|
|
136
128
|
loaderProps: { configProvider, logger },
|
|
137
129
|
};
|
|
138
130
|
const loader = provider.makeTestLoader(testContainerConfig);
|
|
139
|
-
return createSummarizerCore(
|
|
131
|
+
return createSummarizerCore(container, loader, summaryVersion);
|
|
140
132
|
}
|
|
133
|
+
|
|
141
134
|
/**
|
|
142
135
|
* Summarizes on demand and returns the summary tree, the version number and the reference sequence number of the
|
|
143
136
|
* submitted summary.
|
package/src/containerUtils.ts
CHANGED
|
@@ -4,23 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { IContainer } from "@fluidframework/container-definitions";
|
|
7
|
-
import { ConnectionState
|
|
7
|
+
import { ConnectionState } from "@fluidframework/container-loader";
|
|
8
8
|
import { PromiseExecutor, timeoutPromise, TimeoutWithError } from "./timeoutUtils";
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Waits for the specified container to emit a 'connected' event.
|
|
12
|
-
*
|
|
13
|
-
* @deprecated Use waitForContainerConnection instead.
|
|
14
|
-
* Note that an upcoming release will change the default parameters on that function to:
|
|
15
|
-
* - failOnContainerClose = true
|
|
16
|
-
* - timeoutOptions.durationMs = 1s
|
|
17
|
-
*/
|
|
18
|
-
export async function ensureContainerConnected(container: Container): Promise<void> {
|
|
19
|
-
if (!container.connected) {
|
|
20
|
-
return timeoutPromise((resolve) => container.once("connected", () => resolve()));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
10
|
/**
|
|
25
11
|
* Utility function to wait for the specified Container to be in Connected state.
|
|
26
12
|
* If the Container is already connected, the Promise returns immediately; otherwise it resolves when the Container emits
|
|
@@ -30,20 +16,21 @@ export async function ensureContainerConnected(container: Container): Promise<vo
|
|
|
30
16
|
* @param container - The container to wait for.
|
|
31
17
|
* @param failOnContainerClose - If true, the returned Promise will be rejected if the container emits a 'closed' event
|
|
32
18
|
* before a 'connected' event.
|
|
33
|
-
* Defaults to
|
|
19
|
+
* Defaults to true.
|
|
34
20
|
* @param timeoutOptions - Options related to the behavior of the timeout.
|
|
35
|
-
* If
|
|
36
|
-
* 'connected' (or 'closed, if
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* timeoutOptions.durationMs
|
|
21
|
+
* If provided, the returned Promise will reject if the container hasn't emitted relevant events in timeoutOptions.durationMs.
|
|
22
|
+
* If not provided, the Promise will wait indefinitely for the Container to emit its 'connected' (or 'closed', if
|
|
23
|
+
* failOnContainerClose === true) event.
|
|
24
|
+
*
|
|
25
|
+
* @returns A Promise that either:
|
|
26
|
+
* - Resolves when the specified container emits a 'connected' event (or immediately if the Container is already connected).
|
|
27
|
+
* - Rejects if failOnContainerClose === true and the container emits a 'closed' event before a 'connected' event.
|
|
28
|
+
* - Rejects after timeoutOptions.durationMs if timeoutOptions !== undefined and the container does not emit relevant
|
|
29
|
+
* events, within that timeframe.
|
|
43
30
|
*/
|
|
44
31
|
export async function waitForContainerConnection(
|
|
45
32
|
container: IContainer,
|
|
46
|
-
failOnContainerClose: boolean =
|
|
33
|
+
failOnContainerClose: boolean = true,
|
|
47
34
|
timeoutOptions?: TimeoutWithError,
|
|
48
35
|
): Promise<void> {
|
|
49
36
|
if (container.connectionState !== ConnectionState.Connected) {
|
package/src/index.ts
CHANGED
|
@@ -29,12 +29,7 @@ export {
|
|
|
29
29
|
ITestObjectProvider,
|
|
30
30
|
TestObjectProvider,
|
|
31
31
|
} from "./testObjectProvider";
|
|
32
|
-
export {
|
|
33
|
-
createSummarizer,
|
|
34
|
-
createSummarizerFromFactory,
|
|
35
|
-
createSummarizerWithContainer,
|
|
36
|
-
summarizeNow,
|
|
37
|
-
} from "./TestSummaryUtils";
|
|
32
|
+
export { createSummarizer, createSummarizerFromFactory, summarizeNow } from "./TestSummaryUtils";
|
|
38
33
|
export {
|
|
39
34
|
defaultTimeoutDurationMs,
|
|
40
35
|
timeoutAwait,
|
|
@@ -42,4 +37,4 @@ export {
|
|
|
42
37
|
TimeoutWithError,
|
|
43
38
|
TimeoutWithValue,
|
|
44
39
|
} from "./timeoutUtils";
|
|
45
|
-
export {
|
|
40
|
+
export { waitForContainerConnection } from "./containerUtils";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { assert } from "@fluidframework/common-utils";
|
|
6
6
|
import { IContainer, IDeltaQueue, IHostLoader } from "@fluidframework/container-definitions";
|
|
7
|
-
import {
|
|
7
|
+
import { ConnectionState } from "@fluidframework/container-loader";
|
|
8
8
|
import { canBeCoalescedByService } from "@fluidframework/driver-utils";
|
|
9
9
|
import {
|
|
10
10
|
IDocumentMessage,
|
|
@@ -123,7 +123,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
123
123
|
// Received the no op back, update the record if we are tracking
|
|
124
124
|
if (
|
|
125
125
|
canBeCoalescedByService(message) &&
|
|
126
|
-
message.clientId ===
|
|
126
|
+
message.clientId === container.clientId &&
|
|
127
127
|
record.trailingNoOps !== 0 &&
|
|
128
128
|
record.startTrailingNoOps <= message.clientSequenceNumber
|
|
129
129
|
) {
|
|
@@ -162,21 +162,16 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
162
162
|
// REVIEW: do we need to unpatch the loaders?
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
/**
|
|
166
|
-
* Ensure all tracked containers are synchronized
|
|
167
|
-
*/
|
|
168
|
-
public async ensureSynchronized(...containers: IContainer[]): Promise<void> {
|
|
169
|
-
await this.processSynchronized(undefined, ...containers);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
165
|
/**
|
|
173
166
|
* Ensure all tracked containers are synchronized with a time limit
|
|
167
|
+
*
|
|
168
|
+
* @deprecated - this method is equivalent to @see {@link LoaderContainerTracker.ensureSynchronized}, please configure the test timeout instead
|
|
174
169
|
*/
|
|
175
170
|
public async ensureSynchronizedWithTimeout?(
|
|
176
171
|
timeoutDuration: number | undefined,
|
|
177
172
|
...containers: IContainer[]
|
|
178
173
|
) {
|
|
179
|
-
await this.
|
|
174
|
+
await this.ensureSynchronized(...containers);
|
|
180
175
|
}
|
|
181
176
|
|
|
182
177
|
/**
|
|
@@ -198,10 +193,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
198
193
|
*
|
|
199
194
|
* - Trailing NoOp is tracked and don't count as pending ops.
|
|
200
195
|
*/
|
|
201
|
-
|
|
202
|
-
timeoutDuration: number | undefined,
|
|
203
|
-
...containers: IContainer[]
|
|
204
|
-
) {
|
|
196
|
+
public async ensureSynchronized(...containers: IContainer[]): Promise<void> {
|
|
205
197
|
const resumed = this.resumeProcessing(...containers);
|
|
206
198
|
|
|
207
199
|
let waitingSequenceNumberSynchronized = false;
|
|
@@ -287,9 +279,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
287
279
|
// All the clientId we track should be a superset of the quorum, otherwise, we are missing
|
|
288
280
|
// leave messages
|
|
289
281
|
const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);
|
|
290
|
-
const openedClientId = openedDocuments.map(
|
|
291
|
-
(container) => (container as Container).clientId,
|
|
292
|
-
);
|
|
282
|
+
const openedClientId = openedDocuments.map((container) => container.clientId);
|
|
293
283
|
|
|
294
284
|
const pendingClients: [IContainer, Set<string>][] = [];
|
|
295
285
|
containersToApply.forEach((container) => {
|
|
@@ -375,7 +365,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
375
365
|
*/
|
|
376
366
|
private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {
|
|
377
367
|
const unconnectedClients = Array.from(this.containers.keys()).filter(
|
|
378
|
-
(c) => !c.closed &&
|
|
368
|
+
(c) => !c.closed && c.connectionState !== ConnectionState.Connected,
|
|
379
369
|
);
|
|
380
370
|
return Promise.all(
|
|
381
371
|
pendingClients.map(async ([container, pendingClientId]) => {
|
|
@@ -546,7 +536,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
546
536
|
const inHandler = (message: ISequencedDocumentMessage) => {
|
|
547
537
|
if (
|
|
548
538
|
!canBeCoalescedByService(message) &&
|
|
549
|
-
message.clientId ===
|
|
539
|
+
message.clientId === container.clientId &&
|
|
550
540
|
inflightTracker.get(container) === message.clientSequenceNumber
|
|
551
541
|
) {
|
|
552
542
|
inflightTracker.delete(container);
|
|
@@ -600,7 +590,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
600
590
|
return `${e.message}: ${e.stack}`;
|
|
601
591
|
}
|
|
602
592
|
};
|
|
603
|
-
debugOp(`${index}: ADD: clientId: ${
|
|
593
|
+
debugOp(`${index}: ADD: clientId: ${container.clientId}`);
|
|
604
594
|
container.deltaManager.outbound.on("op", (messages) => {
|
|
605
595
|
for (const msg of messages) {
|
|
606
596
|
debugOp(
|
|
@@ -614,7 +604,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
614
604
|
const getInboundHandler = (type: string) => {
|
|
615
605
|
return (msg: ISequencedDocumentMessage) => {
|
|
616
606
|
const clientSeq =
|
|
617
|
-
msg.clientId ===
|
|
607
|
+
msg.clientId === container.clientId
|
|
618
608
|
? `cli: ${msg.clientSequenceNumber.toString().padStart(3)}`
|
|
619
609
|
: " ";
|
|
620
610
|
debugOp(
|
package/src/packageVersion.ts
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
IContainer,
|
|
8
|
+
IHostLoader,
|
|
9
|
+
IFluidCodeDetails,
|
|
10
|
+
LoaderHeader,
|
|
11
|
+
} from "@fluidframework/container-definitions";
|
|
7
12
|
import {
|
|
8
13
|
ITelemetryGenericEvent,
|
|
9
14
|
ITelemetryBaseLogger,
|
|
@@ -154,10 +159,18 @@ function getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {
|
|
|
154
159
|
* any expected events that have not occurred.
|
|
155
160
|
*/
|
|
156
161
|
export class EventAndErrorTrackingLogger extends TelemetryLogger {
|
|
157
|
-
/**
|
|
158
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Even if these error events are logged, tests should still be allowed to pass
|
|
164
|
+
* Additionally, if downgrade is true, then log as generic (e.g. to avoid polluting the e2e test logs)
|
|
165
|
+
*/
|
|
166
|
+
private readonly allowedErrors: { eventName: string; downgrade?: true }[] = [
|
|
159
167
|
// This log was removed in current version as unnecessary, but it's still present in previous versions
|
|
160
|
-
|
|
168
|
+
{
|
|
169
|
+
eventName: "fluid:telemetry:Container:NoRealStorageInDetachedContainer",
|
|
170
|
+
downgrade: true,
|
|
171
|
+
},
|
|
172
|
+
// This log's category changes depending on the op latency. test results shouldn't be affected but if we see lots we'd like an alert from the logs.
|
|
173
|
+
{ eventName: "fluid:telemetry:OpPerf:OpRoundtripTime" },
|
|
161
174
|
];
|
|
162
175
|
|
|
163
176
|
constructor(private readonly baseLogger: ITelemetryBaseLogger) {
|
|
@@ -207,10 +220,15 @@ export class EventAndErrorTrackingLogger extends TelemetryLogger {
|
|
|
207
220
|
}
|
|
208
221
|
}
|
|
209
222
|
if (event.category === "error") {
|
|
210
|
-
if
|
|
211
|
-
|
|
212
|
-
|
|
223
|
+
// Check to see if this error is allowed and if its category should be downgraded
|
|
224
|
+
const allowedError = this.allowedErrors.find(
|
|
225
|
+
({ eventName }) => eventName === event.eventName,
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
if (allowedError === undefined) {
|
|
213
229
|
this.unexpectedErrors.push(event);
|
|
230
|
+
} else if (allowedError.downgrade) {
|
|
231
|
+
event.category = "generic";
|
|
214
232
|
}
|
|
215
233
|
}
|
|
216
234
|
|
|
@@ -364,10 +382,37 @@ export class TestObjectProvider implements ITestObjectProvider {
|
|
|
364
382
|
requestHeader?: IRequestHeader,
|
|
365
383
|
): Promise<IContainer> {
|
|
366
384
|
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
367
|
-
|
|
385
|
+
|
|
386
|
+
// Once ADO#3889 is done to switch default connection mode to "read" on load, we don't need
|
|
387
|
+
// to load "delayed" across the board. Remove the following code.
|
|
388
|
+
const delayConnection =
|
|
389
|
+
requestHeader === undefined || requestHeader[LoaderHeader.reconnect] !== false;
|
|
390
|
+
const headers: IRequestHeader = delayConnection
|
|
391
|
+
? {
|
|
392
|
+
[LoaderHeader.loadMode]: { deltaConnection: "delayed" },
|
|
393
|
+
...requestHeader,
|
|
394
|
+
}
|
|
395
|
+
: requestHeader;
|
|
396
|
+
|
|
397
|
+
const container = await loader.resolve({
|
|
368
398
|
url: await this.driver.createContainerUrl(this.documentId),
|
|
369
|
-
headers
|
|
399
|
+
headers,
|
|
370
400
|
});
|
|
401
|
+
|
|
402
|
+
// Once ADO#3889 is done to switch default connection mode to "read" on load, we don't need
|
|
403
|
+
// to load "delayed" across the board. Remove the following code.
|
|
404
|
+
if (delayConnection) {
|
|
405
|
+
// Older version may not have connect, use resume instead.
|
|
406
|
+
const maybeContainer = container as Partial<IContainer>;
|
|
407
|
+
if (maybeContainer.connect !== undefined) {
|
|
408
|
+
container.connect();
|
|
409
|
+
} else {
|
|
410
|
+
// back compat
|
|
411
|
+
(container as any).resume();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return container;
|
|
371
416
|
}
|
|
372
417
|
|
|
373
418
|
/**
|
|
@@ -442,9 +487,7 @@ export class TestObjectProvider implements ITestObjectProvider {
|
|
|
442
487
|
}
|
|
443
488
|
|
|
444
489
|
public async ensureSynchronized(timeoutDuration?: number): Promise<void> {
|
|
445
|
-
return this._loaderContainerTracker.
|
|
446
|
-
? this._loaderContainerTracker.ensureSynchronizedWithTimeout(timeoutDuration)
|
|
447
|
-
: this._loaderContainerTracker.ensureSynchronized();
|
|
490
|
+
return this._loaderContainerTracker.ensureSynchronized();
|
|
448
491
|
}
|
|
449
492
|
|
|
450
493
|
public async waitContainerToCatchUp(container: IContainer) {
|
package/src/timeoutUtils.ts
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Container } from "@fluidframework/container-loader";
|
|
7
6
|
import { assert, Deferred } from "@fluidframework/common-utils";
|
|
8
7
|
|
|
9
8
|
// @deprecated this value is no longer used
|
|
@@ -133,12 +132,6 @@ export async function timeoutAwait<T = void>(
|
|
|
133
132
|
return Promise.race([promise, timeoutPromise<T>(() => {}, timeoutOptions)]);
|
|
134
133
|
}
|
|
135
134
|
|
|
136
|
-
export async function ensureContainerConnected(container: Container): Promise<void> {
|
|
137
|
-
if (!container.connected) {
|
|
138
|
-
return timeoutPromise((resolve) => container.once("connected", () => resolve()));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
135
|
// Create a promise based on the timeout options
|
|
143
136
|
async function getTimeoutPromise<T = void>(
|
|
144
137
|
executor: (
|