@fluidframework/test-utils 2.0.0-internal.1.0.0.82159 → 2.0.0-internal.1.0.0.83139

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.
@@ -0,0 +1,29 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { IDocumentService, IDocumentServiceFactory, IDocumentStorageService, ISummaryContext } from "@fluidframework/driver-definitions";
6
+ import { ISummaryTree } from "@fluidframework/protocol-definitions";
7
+ /**
8
+ * Wraps the given IDocumentStorageService to override the `uploadSummaryWithContext` method. It calls the
9
+ * `uploadSummaryCb` whenever a summary is uploaded by the client. The summary context can be updated in the
10
+ * callback before it is uploaded to the server.
11
+ */
12
+ export declare function wrapDocumentStorageService(innerDocStorageService: IDocumentStorageService, uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext): IDocumentStorageService;
13
+ /**
14
+ * Wraps the given IDocumentService to override the `connectToStorage` method. The intent is to plumb the
15
+ * `uploadSummaryCb` to the IDocumentStorageService so that it is called whenever a summary is uploaded by
16
+ * the client.
17
+ * The document storage service that is created in `connectToStorage` is wrapped by calling `wrapDocumentStorageService`
18
+ * to pass in the `uploadSummaryCb`.
19
+ */
20
+ export declare function wrapDocumentService(innerDocService: IDocumentService, uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext): IDocumentService;
21
+ /**
22
+ * Wraps the given IDocumentServiceFactory to override the `createDocumentService` method. The intent is to plumb
23
+ * the `uploadSummaryCb` all the way to the IDocumentStorageService so that it is called whenever a summary is
24
+ * uploaded by the client.
25
+ * The document service that is created in `createDocumentService` is wrapped by calling `wrapDocumentService` to
26
+ * pass in the `uploadSummaryCb`.
27
+ */
28
+ export declare function wrapDocumentServiceFactory(innerDocServiceFactory: IDocumentServiceFactory, uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext): IDocumentServiceFactory;
29
+ //# sourceMappingURL=DriverWrappers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DriverWrappers.d.ts","sourceRoot":"","sources":["../src/DriverWrappers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EAEvB,eAAe,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,0BAA0B,CACtC,sBAAsB,EAAE,uBAAuB,EAC/C,eAAe,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,KAAK,eAAe,2BAW5F;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAC/B,eAAe,EAAE,gBAAgB,EACjC,eAAe,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,KAAK,eAAe,oBAQ5F;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACtC,sBAAsB,EAAE,uBAAuB,EAC/C,eAAe,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,KAAK,eAAe,2BAa5F"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.wrapDocumentServiceFactory = exports.wrapDocumentService = exports.wrapDocumentStorageService = void 0;
8
+ /**
9
+ * Wraps the given IDocumentStorageService to override the `uploadSummaryWithContext` method. It calls the
10
+ * `uploadSummaryCb` whenever a summary is uploaded by the client. The summary context can be updated in the
11
+ * callback before it is uploaded to the server.
12
+ */
13
+ function wrapDocumentStorageService(innerDocStorageService, uploadSummaryCb) {
14
+ const outerDocStorageService = Object.create(innerDocStorageService);
15
+ outerDocStorageService.uploadSummaryWithContext = async (summary, context) => {
16
+ const newContext = uploadSummaryCb(summary, context);
17
+ return innerDocStorageService.uploadSummaryWithContext(summary, newContext);
18
+ };
19
+ return outerDocStorageService;
20
+ }
21
+ exports.wrapDocumentStorageService = wrapDocumentStorageService;
22
+ /**
23
+ * Wraps the given IDocumentService to override the `connectToStorage` method. The intent is to plumb the
24
+ * `uploadSummaryCb` to the IDocumentStorageService so that it is called whenever a summary is uploaded by
25
+ * the client.
26
+ * The document storage service that is created in `connectToStorage` is wrapped by calling `wrapDocumentStorageService`
27
+ * to pass in the `uploadSummaryCb`.
28
+ */
29
+ function wrapDocumentService(innerDocService, uploadSummaryCb) {
30
+ const outerDocService = Object.create(innerDocService);
31
+ outerDocService.connectToStorage = async () => {
32
+ const storageService = await innerDocService.connectToStorage();
33
+ return wrapDocumentStorageService(storageService, uploadSummaryCb);
34
+ };
35
+ return outerDocService;
36
+ }
37
+ exports.wrapDocumentService = wrapDocumentService;
38
+ /**
39
+ * Wraps the given IDocumentServiceFactory to override the `createDocumentService` method. The intent is to plumb
40
+ * the `uploadSummaryCb` all the way to the IDocumentStorageService so that it is called whenever a summary is
41
+ * uploaded by the client.
42
+ * The document service that is created in `createDocumentService` is wrapped by calling `wrapDocumentService` to
43
+ * pass in the `uploadSummaryCb`.
44
+ */
45
+ function wrapDocumentServiceFactory(innerDocServiceFactory, uploadSummaryCb) {
46
+ const outerDocServiceFactory = Object.create(innerDocServiceFactory);
47
+ outerDocServiceFactory.createDocumentService = async (resolvedUrl, logger, clientIsSummarizer) => {
48
+ const documentService = await innerDocServiceFactory.createDocumentService(resolvedUrl, logger, clientIsSummarizer);
49
+ return wrapDocumentService(documentService, uploadSummaryCb);
50
+ };
51
+ return outerDocServiceFactory;
52
+ }
53
+ exports.wrapDocumentServiceFactory = wrapDocumentServiceFactory;
54
+ //# sourceMappingURL=DriverWrappers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DriverWrappers.js","sourceRoot":"","sources":["../src/DriverWrappers.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAYH;;;;GAIG;AACH,SAAgB,0BAA0B,CACtC,sBAA+C,EAC/C,eAAyF;IAEzF,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAA4B,CAAC;IAChG,sBAAsB,CAAC,wBAAwB,GAAG,KAAK,EACnD,OAAqB,EACrB,OAAwB,EACT,EAAE;QACjB,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,sBAAsB,CAAC,wBAAwB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAChF,CAAC,CAAC;IACF,OAAO,sBAAsB,CAAC;AAClC,CAAC;AAbD,gEAaC;AAED;;;;;;GAMG;AACH,SAAgB,mBAAmB,CAC/B,eAAiC,EACjC,eAAyF;IAEzF,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAqB,CAAC;IAC3E,eAAe,CAAC,gBAAgB,GAAG,KAAK,IAAsC,EAAE;QAC5E,MAAM,cAAc,GAAG,MAAM,eAAe,CAAC,gBAAgB,EAAE,CAAC;QAChE,OAAO,0BAA0B,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IACvE,CAAC,CAAC;IACF,OAAO,eAAe,CAAC;AAC3B,CAAC;AAVD,kDAUC;AAED;;;;;;GAMG;AACH,SAAgB,0BAA0B,CACtC,sBAA+C,EAC/C,eAAyF;IAEzF,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAA4B,CAAC;IAChG,sBAAsB,CAAC,qBAAqB,GAAG,KAAK,EAChD,WAAyB,EACzB,MAA6B,EAC7B,kBAA4B,EACH,EAAE;QAC3B,MAAM,eAAe,GAAG,MAAM,sBAAsB,CAAC,qBAAqB,CACtE,WAAW,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;QAC7C,OAAO,mBAAmB,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;IACjE,CAAC,CAAC;IACF,OAAO,sBAAsB,CAAC;AAClC,CAAC;AAfD,gEAeC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport {\n IDocumentService,\n IDocumentServiceFactory,\n IDocumentStorageService,\n IResolvedUrl,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport { ISummaryTree } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Wraps the given IDocumentStorageService to override the `uploadSummaryWithContext` method. It calls the\n * `uploadSummaryCb` whenever a summary is uploaded by the client. The summary context can be updated in the\n * callback before it is uploaded to the server.\n */\nexport function wrapDocumentStorageService(\n innerDocStorageService: IDocumentStorageService,\n uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,\n) {\n const outerDocStorageService = Object.create(innerDocStorageService) as IDocumentStorageService;\n outerDocStorageService.uploadSummaryWithContext = async (\n summary: ISummaryTree,\n context: ISummaryContext,\n ): Promise<string> => {\n const newContext = uploadSummaryCb(summary, context);\n return innerDocStorageService.uploadSummaryWithContext(summary, newContext);\n };\n return outerDocStorageService;\n}\n\n/**\n * Wraps the given IDocumentService to override the `connectToStorage` method. The intent is to plumb the\n * `uploadSummaryCb` to the IDocumentStorageService so that it is called whenever a summary is uploaded by\n * the client.\n * The document storage service that is created in `connectToStorage` is wrapped by calling `wrapDocumentStorageService`\n * to pass in the `uploadSummaryCb`.\n */\nexport function wrapDocumentService(\n innerDocService: IDocumentService,\n uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,\n) {\n const outerDocService = Object.create(innerDocService) as IDocumentService;\n outerDocService.connectToStorage = async (): Promise<IDocumentStorageService> => {\n const storageService = await innerDocService.connectToStorage();\n return wrapDocumentStorageService(storageService, uploadSummaryCb);\n };\n return outerDocService;\n}\n\n/**\n * Wraps the given IDocumentServiceFactory to override the `createDocumentService` method. The intent is to plumb\n * the `uploadSummaryCb` all the way to the IDocumentStorageService so that it is called whenever a summary is\n * uploaded by the client.\n * The document service that is created in `createDocumentService` is wrapped by calling `wrapDocumentService` to\n * pass in the `uploadSummaryCb`.\n */\nexport function wrapDocumentServiceFactory(\n innerDocServiceFactory: IDocumentServiceFactory,\n uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,\n) {\n const outerDocServiceFactory = Object.create(innerDocServiceFactory) as IDocumentServiceFactory;\n outerDocServiceFactory.createDocumentService = async (\n resolvedUrl: IResolvedUrl,\n logger?: ITelemetryBaseLogger,\n clientIsSummarizer?: boolean,\n ): Promise<IDocumentService> => {\n const documentService = await innerDocServiceFactory.createDocumentService(\n resolvedUrl, logger, clientIsSummarizer);\n return wrapDocumentService(documentService, uploadSummaryCb);\n };\n return outerDocServiceFactory;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { ConfigTypes, IConfigProviderBase } from "@fluidframework/telemetry-utils";
6
+ export declare const mockConfigProvider: (settings?: Record<string, ConfigTypes>) => IConfigProviderBase;
7
+ //# sourceMappingURL=TestConfigs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestConfigs.d.ts","sourceRoot":"","sources":["../src/TestConfigs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEnF,eAAO,MAAM,kBAAkB,cAAe,OAAO,MAAM,EAAE,WAAW,CAAC,KAAQ,mBAO/E,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.mockConfigProvider = void 0;
8
+ exports.mockConfigProvider = ((settings = {}) => {
9
+ settings["Fluid.ContainerRuntime.UseDataStoreAliasing"] = "true";
10
+ settings["Fluid.GarbageCollection.TrackGCState"] = "true";
11
+ settings["Fluid.GarbageCollection.WriteDataAtRoot"] = "true";
12
+ return {
13
+ getRawConfig: (name) => settings[name],
14
+ };
15
+ });
16
+ //# sourceMappingURL=TestConfigs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestConfigs.js","sourceRoot":"","sources":["../src/TestConfigs.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIU,QAAA,kBAAkB,GAAG,CAAC,CAAC,WAAwC,EAAE,EAAuB,EAAE;IACnG,QAAQ,CAAC,6CAA6C,CAAC,GAAG,MAAM,CAAC;IACjE,QAAQ,CAAC,sCAAsC,CAAC,GAAG,MAAM,CAAC;IAC1D,QAAQ,CAAC,yCAAyC,CAAC,GAAG,MAAM,CAAC;IAC7D,OAAO;QACH,YAAY,EAAE,CAAC,IAAY,EAAe,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;KAC9D,CAAC;AACN,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ConfigTypes, IConfigProviderBase } from \"@fluidframework/telemetry-utils\";\n\nexport const mockConfigProvider = ((settings: Record<string, ConfigTypes> = {}): IConfigProviderBase => {\n settings[\"Fluid.ContainerRuntime.UseDataStoreAliasing\"] = \"true\";\n settings[\"Fluid.GarbageCollection.TrackGCState\"] = \"true\";\n settings[\"Fluid.GarbageCollection.WriteDataAtRoot\"] = \"true\";\n return {\n getRawConfig: (name: string): ConfigTypes => settings[name],\n };\n});\n"]}
@@ -0,0 +1,17 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { ContainerRuntimeFactoryWithDefaultDataStore } from "@fluidframework/aqueduct";
6
+ import { IContainer } from "@fluidframework/container-definitions";
7
+ import { IGCRuntimeOptions, ISummarizer } from "@fluidframework/container-runtime";
8
+ import { IFluidDataStoreFactory } from "@fluidframework/runtime-definitions";
9
+ import { ITestObjectProvider } from "./testObjectProvider";
10
+ export declare function createSummarizerFromFactory(provider: ITestObjectProvider, container: IContainer, dataStoreFactory: IFluidDataStoreFactory, summaryVersion?: string, containerRuntimeFactoryType?: typeof ContainerRuntimeFactoryWithDefaultDataStore): Promise<ISummarizer>;
11
+ export declare function createSummarizer(provider: ITestObjectProvider, container: IContainer, summaryVersion?: string, gcOptions?: IGCRuntimeOptions): Promise<ISummarizer>;
12
+ export declare function summarizeNow(summarizer: ISummarizer, reason?: string): Promise<{
13
+ summaryTree: import("@fluidframework/protocol-definitions").ISummaryTree;
14
+ summaryVersion: string;
15
+ }>;
16
+ export declare function waitForContainerConnection(container: IContainer): Promise<void>;
17
+ //# sourceMappingURL=TestSummaryUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestSummaryUtils.d.ts","sourceRoot":"","sources":["../src/TestSummaryUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,2CAA2C,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAA6B,MAAM,uCAAuC,CAAC;AAE9F,OAAO,EACH,iBAAiB,EACjB,WAAW,EAEd,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEH,sBAAsB,EACzB,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EAAwB,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AA6CjF,wBAAsB,2BAA2B,CAC7C,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,gBAAgB,EAAE,sBAAsB,EACxC,cAAc,CAAC,EAAE,MAAM,EACvB,2BAA2B,qDAA8C,GAC1E,OAAO,CAAC,WAAW,CAAC,CAmBtB;AAED,wBAAsB,gBAAgB,CAClC,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,UAAU,EACrB,cAAc,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,iBAAiB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAWtB;AAED,wBAAsB,YAAY,CAAC,UAAU,EAAE,WAAW,EAAE,MAAM,GAAE,MAA0B;;;GAqB7F;AAED,wBAAsB,0BAA0B,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrF"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.waitForContainerConnection = exports.summarizeNow = exports.createSummarizer = exports.createSummarizerFromFactory = void 0;
8
+ const aqueduct_1 = require("@fluidframework/aqueduct");
9
+ const common_utils_1 = require("@fluidframework/common-utils");
10
+ const container_definitions_1 = require("@fluidframework/container-definitions");
11
+ const container_loader_1 = require("@fluidframework/container-loader");
12
+ const driver_definitions_1 = require("@fluidframework/driver-definitions");
13
+ const runtime_utils_1 = require("@fluidframework/runtime-utils");
14
+ const TestConfigs_1 = require("./TestConfigs");
15
+ const summarizerClientType = "summarizer";
16
+ async function createSummarizerCore(container, loader, summaryVersion) {
17
+ const absoluteUrl = await container.getAbsoluteUrl("");
18
+ if (absoluteUrl === undefined) {
19
+ throw new Error("URL could not be resolved");
20
+ }
21
+ const request = {
22
+ headers: {
23
+ [container_definitions_1.LoaderHeader.cache]: false,
24
+ [container_definitions_1.LoaderHeader.clientDetails]: {
25
+ capabilities: { interactive: false },
26
+ type: summarizerClientType,
27
+ },
28
+ [driver_definitions_1.DriverHeader.summarizingClient]: true,
29
+ [container_definitions_1.LoaderHeader.reconnect]: false,
30
+ [container_definitions_1.LoaderHeader.version]: summaryVersion,
31
+ },
32
+ url: absoluteUrl,
33
+ };
34
+ const summarizerContainer = await loader.resolve(request);
35
+ await waitForContainerConnection(summarizerContainer);
36
+ const fluidObject = await (0, runtime_utils_1.requestFluidObject)(summarizerContainer, { url: "_summarizer" });
37
+ if (fluidObject.ISummarizer === undefined) {
38
+ throw new Error("Fluid object does not implement ISummarizer");
39
+ }
40
+ return fluidObject.ISummarizer;
41
+ }
42
+ const defaultSummaryOptions = {
43
+ summaryConfigOverrides: {
44
+ state: "disableHeuristics",
45
+ maxAckWaitTime: 10000,
46
+ maxOpsSinceLastSummary: 7000,
47
+ initialSummarizerDelayMs: 0,
48
+ summarizerClientElection: false,
49
+ },
50
+ };
51
+ async function createSummarizerFromFactory(provider, container, dataStoreFactory, summaryVersion, containerRuntimeFactoryType = aqueduct_1.ContainerRuntimeFactoryWithDefaultDataStore) {
52
+ const innerRequestHandler = async (request, runtime) => runtime.IFluidHandleContext.resolveHandle(request);
53
+ const runtimeFactory = new containerRuntimeFactoryType(dataStoreFactory, [
54
+ [dataStoreFactory.type, Promise.resolve(dataStoreFactory)],
55
+ ], undefined, [innerRequestHandler], { summaryOptions: defaultSummaryOptions });
56
+ const loader = provider.createLoader([[provider.defaultCodeDetails, runtimeFactory]], { configProvider: (0, TestConfigs_1.mockConfigProvider)() });
57
+ return createSummarizerCore(container, loader, summaryVersion);
58
+ }
59
+ exports.createSummarizerFromFactory = createSummarizerFromFactory;
60
+ async function createSummarizer(provider, container, summaryVersion, gcOptions) {
61
+ const testContainerConfig = {
62
+ runtimeOptions: {
63
+ summaryOptions: defaultSummaryOptions,
64
+ gcOptions,
65
+ },
66
+ loaderProps: { configProvider: (0, TestConfigs_1.mockConfigProvider)() },
67
+ };
68
+ const loader = provider.makeTestLoader(testContainerConfig);
69
+ return createSummarizerCore(container, loader, summaryVersion);
70
+ }
71
+ exports.createSummarizer = createSummarizer;
72
+ async function summarizeNow(summarizer, reason = "end-to-end test") {
73
+ const result = summarizer.summarizeOnDemand({ reason });
74
+ const submitResult = await result.summarySubmitted;
75
+ (0, common_utils_1.assert)(submitResult.success, "on-demand summary should submit");
76
+ (0, common_utils_1.assert)(submitResult.data.stage === "submit", "on-demand summary submitted data stage should be submit");
77
+ (0, common_utils_1.assert)(submitResult.data.summaryTree !== undefined, "summary tree should exist");
78
+ const broadcastResult = await result.summaryOpBroadcasted;
79
+ (0, common_utils_1.assert)(broadcastResult.success, "summary op should be broadcast");
80
+ const ackNackResult = await result.receivedSummaryAckOrNack;
81
+ (0, common_utils_1.assert)(ackNackResult.success, "summary op should be acked");
82
+ await new Promise((resolve) => process.nextTick(resolve));
83
+ return {
84
+ summaryTree: submitResult.data.summaryTree,
85
+ summaryVersion: ackNackResult.data.summaryAckOp.contents.handle,
86
+ };
87
+ }
88
+ exports.summarizeNow = summarizeNow;
89
+ async function waitForContainerConnection(container) {
90
+ if (container.connectionState !== container_loader_1.ConnectionState.Connected) {
91
+ return new Promise((resolve) => container.once("connected", () => resolve()));
92
+ }
93
+ }
94
+ exports.waitForContainerConnection = waitForContainerConnection;
95
+ //# sourceMappingURL=TestSummaryUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestSummaryUtils.js","sourceRoot":"","sources":["../src/TestSummaryUtils.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 { ContainerRuntimeFactoryWithDefaultDataStore } from \"@fluidframework/aqueduct\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IHostLoader, LoaderHeader } from \"@fluidframework/container-definitions\";\nimport { ConnectionState } from \"@fluidframework/container-loader\";\nimport {\n IGCRuntimeOptions,\n ISummarizer,\n ISummaryRuntimeOptions,\n} from \"@fluidframework/container-runtime\";\nimport { FluidObject, IRequest } from \"@fluidframework/core-interfaces\";\nimport { DriverHeader } from \"@fluidframework/driver-definitions\";\nimport {\n IContainerRuntimeBase,\n IFluidDataStoreFactory,\n} from \"@fluidframework/runtime-definitions\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { ITestContainerConfig, ITestObjectProvider } from \"./testObjectProvider\";\nimport { mockConfigProvider } from \"./TestConfigs\";\n\nconst summarizerClientType = \"summarizer\";\n\nasync function createSummarizerCore(container: IContainer, loader: IHostLoader, summaryVersion?: string) {\n const absoluteUrl = await container.getAbsoluteUrl(\"\");\n if (absoluteUrl === undefined) {\n throw new Error(\"URL could not be resolved\");\n }\n\n const request: IRequest = {\n headers: {\n [LoaderHeader.cache]: false,\n [LoaderHeader.clientDetails]: {\n capabilities: { interactive: false },\n type: summarizerClientType,\n },\n [DriverHeader.summarizingClient]: true,\n [LoaderHeader.reconnect]: false,\n [LoaderHeader.version]: summaryVersion,\n },\n url: absoluteUrl,\n };\n const summarizerContainer = await loader.resolve(request);\n await waitForContainerConnection(summarizerContainer);\n\n const fluidObject =\n await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, { url: \"_summarizer\" });\n if (fluidObject.ISummarizer === undefined) {\n throw new Error(\"Fluid object does not implement ISummarizer\");\n }\n return fluidObject.ISummarizer;\n}\n\nconst defaultSummaryOptions: ISummaryRuntimeOptions = {\n summaryConfigOverrides: {\n state: \"disableHeuristics\",\n maxAckWaitTime: 10000,\n maxOpsSinceLastSummary: 7000,\n initialSummarizerDelayMs: 0,\n summarizerClientElection: false,\n },\n};\n\nexport async function createSummarizerFromFactory(\n provider: ITestObjectProvider,\n container: IContainer,\n dataStoreFactory: IFluidDataStoreFactory,\n summaryVersion?: string,\n containerRuntimeFactoryType = ContainerRuntimeFactoryWithDefaultDataStore,\n): Promise<ISummarizer> {\n const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>\n runtime.IFluidHandleContext.resolveHandle(request);\n const runtimeFactory = new containerRuntimeFactoryType(\n dataStoreFactory,\n [\n [dataStoreFactory.type, Promise.resolve(dataStoreFactory)],\n ],\n undefined,\n [innerRequestHandler],\n { summaryOptions: defaultSummaryOptions },\n );\n\n const loader = provider.createLoader(\n [[provider.defaultCodeDetails, runtimeFactory]],\n { configProvider: mockConfigProvider() },\n );\n\n return createSummarizerCore(container, loader, summaryVersion);\n}\n\nexport async function createSummarizer(\n provider: ITestObjectProvider,\n container: IContainer,\n summaryVersion?: string,\n gcOptions?: IGCRuntimeOptions,\n): Promise<ISummarizer> {\n const testContainerConfig: ITestContainerConfig = {\n runtimeOptions: {\n summaryOptions: defaultSummaryOptions,\n gcOptions,\n },\n loaderProps: { configProvider: mockConfigProvider() },\n };\n\n const loader = provider.makeTestLoader(testContainerConfig);\n return createSummarizerCore(container, loader, summaryVersion);\n}\n\nexport async function summarizeNow(summarizer: ISummarizer, reason: string = \"end-to-end test\") {\n const result = summarizer.summarizeOnDemand({ reason });\n\n const submitResult = await result.summarySubmitted;\n assert(submitResult.success, \"on-demand summary should submit\");\n assert(submitResult.data.stage === \"submit\",\n \"on-demand summary submitted data stage should be submit\");\n assert(submitResult.data.summaryTree !== undefined, \"summary tree should exist\");\n\n const broadcastResult = await result.summaryOpBroadcasted;\n assert(broadcastResult.success, \"summary op should be broadcast\");\n\n const ackNackResult = await result.receivedSummaryAckOrNack;\n assert(ackNackResult.success, \"summary op should be acked\");\n\n await new Promise((resolve) => process.nextTick(resolve));\n\n return {\n summaryTree: submitResult.data.summaryTree,\n summaryVersion: ackNackResult.data.summaryAckOp.contents.handle,\n };\n}\n\nexport async function waitForContainerConnection(container: IContainer): Promise<void> {\n if (container.connectionState !== ConnectionState.Connected) {\n return new Promise((resolve) => container.once(\"connected\", () => resolve()));\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -11,4 +11,7 @@ export * from "./retry";
11
11
  export * from "./testContainerRuntimeFactory";
12
12
  export * from "./testFluidObject";
13
13
  export * from "./timeoutUtils";
14
+ export * from "./DriverWrappers";
15
+ export * from "./TestSummaryUtils";
16
+ export * from "./TestConfigs";
14
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,SAAS,CAAC;AACxB,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -23,4 +23,7 @@ __exportStar(require("./retry"), exports);
23
23
  __exportStar(require("./testContainerRuntimeFactory"), exports);
24
24
  __exportStar(require("./testFluidObject"), exports);
25
25
  __exportStar(require("./timeoutUtils"), exports);
26
+ __exportStar(require("./DriverWrappers"), exports);
27
+ __exportStar(require("./TestSummaryUtils"), exports);
28
+ __exportStar(require("./TestConfigs"), exports);
26
29
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,uDAAqC;AACrC,2DAAyC;AACzC,gDAA8B;AAC9B,oDAAkC;AAClC,0CAAwB;AACxB,gEAA8C;AAC9C,oDAAkC;AAClC,iDAA+B","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./interfaces\";\nexport * from \"./testObjectProvider\";\nexport * from \"./loaderContainerTracker\";\nexport * from \"./localLoader\";\nexport * from \"./localCodeLoader\";\nexport * from \"./retry\";\nexport * from \"./testContainerRuntimeFactory\";\nexport * from \"./testFluidObject\";\nexport * from \"./timeoutUtils\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,uDAAqC;AACrC,2DAAyC;AACzC,gDAA8B;AAC9B,oDAAkC;AAClC,0CAAwB;AACxB,gEAA8C;AAC9C,oDAAkC;AAClC,iDAA+B;AAC/B,mDAAiC;AACjC,qDAAmC;AACnC,gDAA8B","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport * from \"./interfaces\";\nexport * from \"./testObjectProvider\";\nexport * from \"./loaderContainerTracker\";\nexport * from \"./localLoader\";\nexport * from \"./localCodeLoader\";\nexport * from \"./retry\";\nexport * from \"./testContainerRuntimeFactory\";\nexport * from \"./testFluidObject\";\nexport * from \"./timeoutUtils\";\nexport * from \"./DriverWrappers\";\nexport * from \"./TestSummaryUtils\";\nexport * from \"./TestConfigs\";\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/test-utils";
8
- export declare const pkgVersion = "2.0.0-internal.1.0.0.82159";
8
+ export declare const pkgVersion = "2.0.0-internal.1.0.0.83139";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/test-utils";
11
- exports.pkgVersion = "2.0.0-internal.1.0.0.82159";
11
+ exports.pkgVersion = "2.0.0-internal.1.0.0.83139";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,4BAA4B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"2.0.0-internal.1.0.0.82159\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,4BAA4B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"2.0.0-internal.1.0.0.83139\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/test-utils",
3
- "version": "2.0.0-internal.1.0.0.82159",
3
+ "version": "2.0.0-internal.1.0.0.83139",
4
4
  "description": "Utilities for Fluid tests",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -55,28 +55,28 @@
55
55
  "temp-directory": "nyc/.nyc_output"
56
56
  },
57
57
  "dependencies": {
58
- "@fluidframework/aqueduct": "2.0.0-internal.1.0.0.82159",
58
+ "@fluidframework/aqueduct": "2.0.0-internal.1.0.0.83139",
59
59
  "@fluidframework/common-definitions": "^0.20.1",
60
60
  "@fluidframework/common-utils": "^0.32.1",
61
- "@fluidframework/container-definitions": "2.0.0-internal.1.0.0.82159",
62
- "@fluidframework/container-loader": "2.0.0-internal.1.0.0.82159",
63
- "@fluidframework/container-runtime": "2.0.0-internal.1.0.0.82159",
64
- "@fluidframework/container-runtime-definitions": "2.0.0-internal.1.0.0.82159",
65
- "@fluidframework/core-interfaces": "2.0.0-internal.1.0.0.82159",
66
- "@fluidframework/datastore": "2.0.0-internal.1.0.0.82159",
67
- "@fluidframework/datastore-definitions": "2.0.0-internal.1.0.0.82159",
68
- "@fluidframework/driver-definitions": "2.0.0-internal.1.0.0.82159",
69
- "@fluidframework/driver-utils": "2.0.0-internal.1.0.0.82159",
70
- "@fluidframework/local-driver": "2.0.0-internal.1.0.0.82159",
71
- "@fluidframework/map": "2.0.0-internal.1.0.0.82159",
61
+ "@fluidframework/container-definitions": "2.0.0-internal.1.0.0.83139",
62
+ "@fluidframework/container-loader": "2.0.0-internal.1.0.0.83139",
63
+ "@fluidframework/container-runtime": "2.0.0-internal.1.0.0.83139",
64
+ "@fluidframework/container-runtime-definitions": "2.0.0-internal.1.0.0.83139",
65
+ "@fluidframework/core-interfaces": "2.0.0-internal.1.0.0.83139",
66
+ "@fluidframework/datastore": "2.0.0-internal.1.0.0.83139",
67
+ "@fluidframework/datastore-definitions": "2.0.0-internal.1.0.0.83139",
68
+ "@fluidframework/driver-definitions": "2.0.0-internal.1.0.0.83139",
69
+ "@fluidframework/driver-utils": "2.0.0-internal.1.0.0.83139",
70
+ "@fluidframework/local-driver": "2.0.0-internal.1.0.0.83139",
71
+ "@fluidframework/map": "2.0.0-internal.1.0.0.83139",
72
72
  "@fluidframework/protocol-definitions": "^0.1029.1000-0",
73
- "@fluidframework/request-handler": "2.0.0-internal.1.0.0.82159",
74
- "@fluidframework/routerlicious-driver": "2.0.0-internal.1.0.0.82159",
75
- "@fluidframework/runtime-definitions": "2.0.0-internal.1.0.0.82159",
76
- "@fluidframework/runtime-utils": "2.0.0-internal.1.0.0.82159",
77
- "@fluidframework/telemetry-utils": "2.0.0-internal.1.0.0.82159",
78
- "@fluidframework/test-driver-definitions": "2.0.0-internal.1.0.0.82159",
79
- "@fluidframework/test-runtime-utils": "2.0.0-internal.1.0.0.82159",
73
+ "@fluidframework/request-handler": "2.0.0-internal.1.0.0.83139",
74
+ "@fluidframework/routerlicious-driver": "2.0.0-internal.1.0.0.83139",
75
+ "@fluidframework/runtime-definitions": "2.0.0-internal.1.0.0.83139",
76
+ "@fluidframework/runtime-utils": "2.0.0-internal.1.0.0.83139",
77
+ "@fluidframework/telemetry-utils": "2.0.0-internal.1.0.0.83139",
78
+ "@fluidframework/test-driver-definitions": "2.0.0-internal.1.0.0.83139",
79
+ "@fluidframework/test-runtime-utils": "2.0.0-internal.1.0.0.83139",
80
80
  "best-random": "^1.0.0",
81
81
  "debug": "^4.1.1",
82
82
  "uuid": "^8.3.1"
@@ -0,0 +1,77 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
7
+ import {
8
+ IDocumentService,
9
+ IDocumentServiceFactory,
10
+ IDocumentStorageService,
11
+ IResolvedUrl,
12
+ ISummaryContext,
13
+ } from "@fluidframework/driver-definitions";
14
+ import { ISummaryTree } from "@fluidframework/protocol-definitions";
15
+
16
+ /**
17
+ * Wraps the given IDocumentStorageService to override the `uploadSummaryWithContext` method. It calls the
18
+ * `uploadSummaryCb` whenever a summary is uploaded by the client. The summary context can be updated in the
19
+ * callback before it is uploaded to the server.
20
+ */
21
+ export function wrapDocumentStorageService(
22
+ innerDocStorageService: IDocumentStorageService,
23
+ uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,
24
+ ) {
25
+ const outerDocStorageService = Object.create(innerDocStorageService) as IDocumentStorageService;
26
+ outerDocStorageService.uploadSummaryWithContext = async (
27
+ summary: ISummaryTree,
28
+ context: ISummaryContext,
29
+ ): Promise<string> => {
30
+ const newContext = uploadSummaryCb(summary, context);
31
+ return innerDocStorageService.uploadSummaryWithContext(summary, newContext);
32
+ };
33
+ return outerDocStorageService;
34
+ }
35
+
36
+ /**
37
+ * Wraps the given IDocumentService to override the `connectToStorage` method. The intent is to plumb the
38
+ * `uploadSummaryCb` to the IDocumentStorageService so that it is called whenever a summary is uploaded by
39
+ * the client.
40
+ * The document storage service that is created in `connectToStorage` is wrapped by calling `wrapDocumentStorageService`
41
+ * to pass in the `uploadSummaryCb`.
42
+ */
43
+ export function wrapDocumentService(
44
+ innerDocService: IDocumentService,
45
+ uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,
46
+ ) {
47
+ const outerDocService = Object.create(innerDocService) as IDocumentService;
48
+ outerDocService.connectToStorage = async (): Promise<IDocumentStorageService> => {
49
+ const storageService = await innerDocService.connectToStorage();
50
+ return wrapDocumentStorageService(storageService, uploadSummaryCb);
51
+ };
52
+ return outerDocService;
53
+ }
54
+
55
+ /**
56
+ * Wraps the given IDocumentServiceFactory to override the `createDocumentService` method. The intent is to plumb
57
+ * the `uploadSummaryCb` all the way to the IDocumentStorageService so that it is called whenever a summary is
58
+ * uploaded by the client.
59
+ * The document service that is created in `createDocumentService` is wrapped by calling `wrapDocumentService` to
60
+ * pass in the `uploadSummaryCb`.
61
+ */
62
+ export function wrapDocumentServiceFactory(
63
+ innerDocServiceFactory: IDocumentServiceFactory,
64
+ uploadSummaryCb: (summaryTree: ISummaryTree, context: ISummaryContext) => ISummaryContext,
65
+ ) {
66
+ const outerDocServiceFactory = Object.create(innerDocServiceFactory) as IDocumentServiceFactory;
67
+ outerDocServiceFactory.createDocumentService = async (
68
+ resolvedUrl: IResolvedUrl,
69
+ logger?: ITelemetryBaseLogger,
70
+ clientIsSummarizer?: boolean,
71
+ ): Promise<IDocumentService> => {
72
+ const documentService = await innerDocServiceFactory.createDocumentService(
73
+ resolvedUrl, logger, clientIsSummarizer);
74
+ return wrapDocumentService(documentService, uploadSummaryCb);
75
+ };
76
+ return outerDocServiceFactory;
77
+ }
@@ -0,0 +1,15 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ConfigTypes, IConfigProviderBase } from "@fluidframework/telemetry-utils";
7
+
8
+ export const mockConfigProvider = ((settings: Record<string, ConfigTypes> = {}): IConfigProviderBase => {
9
+ settings["Fluid.ContainerRuntime.UseDataStoreAliasing"] = "true";
10
+ settings["Fluid.GarbageCollection.TrackGCState"] = "true";
11
+ settings["Fluid.GarbageCollection.WriteDataAtRoot"] = "true";
12
+ return {
13
+ getRawConfig: (name: string): ConfigTypes => settings[name],
14
+ };
15
+ });
@@ -0,0 +1,139 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ContainerRuntimeFactoryWithDefaultDataStore } from "@fluidframework/aqueduct";
7
+ import { assert } from "@fluidframework/common-utils";
8
+ import { IContainer, IHostLoader, LoaderHeader } from "@fluidframework/container-definitions";
9
+ import { ConnectionState } from "@fluidframework/container-loader";
10
+ import {
11
+ IGCRuntimeOptions,
12
+ ISummarizer,
13
+ ISummaryRuntimeOptions,
14
+ } from "@fluidframework/container-runtime";
15
+ import { FluidObject, IRequest } from "@fluidframework/core-interfaces";
16
+ import { DriverHeader } from "@fluidframework/driver-definitions";
17
+ import {
18
+ IContainerRuntimeBase,
19
+ IFluidDataStoreFactory,
20
+ } from "@fluidframework/runtime-definitions";
21
+ import { requestFluidObject } from "@fluidframework/runtime-utils";
22
+ import { ITestContainerConfig, ITestObjectProvider } from "./testObjectProvider";
23
+ import { mockConfigProvider } from "./TestConfigs";
24
+
25
+ const summarizerClientType = "summarizer";
26
+
27
+ async function createSummarizerCore(container: IContainer, loader: IHostLoader, summaryVersion?: string) {
28
+ const absoluteUrl = await container.getAbsoluteUrl("");
29
+ if (absoluteUrl === undefined) {
30
+ throw new Error("URL could not be resolved");
31
+ }
32
+
33
+ const request: IRequest = {
34
+ headers: {
35
+ [LoaderHeader.cache]: false,
36
+ [LoaderHeader.clientDetails]: {
37
+ capabilities: { interactive: false },
38
+ type: summarizerClientType,
39
+ },
40
+ [DriverHeader.summarizingClient]: true,
41
+ [LoaderHeader.reconnect]: false,
42
+ [LoaderHeader.version]: summaryVersion,
43
+ },
44
+ url: absoluteUrl,
45
+ };
46
+ const summarizerContainer = await loader.resolve(request);
47
+ await waitForContainerConnection(summarizerContainer);
48
+
49
+ const fluidObject =
50
+ await requestFluidObject<FluidObject<ISummarizer>>(summarizerContainer, { url: "_summarizer" });
51
+ if (fluidObject.ISummarizer === undefined) {
52
+ throw new Error("Fluid object does not implement ISummarizer");
53
+ }
54
+ return fluidObject.ISummarizer;
55
+ }
56
+
57
+ const defaultSummaryOptions: ISummaryRuntimeOptions = {
58
+ summaryConfigOverrides: {
59
+ state: "disableHeuristics",
60
+ maxAckWaitTime: 10000,
61
+ maxOpsSinceLastSummary: 7000,
62
+ initialSummarizerDelayMs: 0,
63
+ summarizerClientElection: false,
64
+ },
65
+ };
66
+
67
+ export async function createSummarizerFromFactory(
68
+ provider: ITestObjectProvider,
69
+ container: IContainer,
70
+ dataStoreFactory: IFluidDataStoreFactory,
71
+ summaryVersion?: string,
72
+ containerRuntimeFactoryType = ContainerRuntimeFactoryWithDefaultDataStore,
73
+ ): Promise<ISummarizer> {
74
+ const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>
75
+ runtime.IFluidHandleContext.resolveHandle(request);
76
+ const runtimeFactory = new containerRuntimeFactoryType(
77
+ dataStoreFactory,
78
+ [
79
+ [dataStoreFactory.type, Promise.resolve(dataStoreFactory)],
80
+ ],
81
+ undefined,
82
+ [innerRequestHandler],
83
+ { summaryOptions: defaultSummaryOptions },
84
+ );
85
+
86
+ const loader = provider.createLoader(
87
+ [[provider.defaultCodeDetails, runtimeFactory]],
88
+ { configProvider: mockConfigProvider() },
89
+ );
90
+
91
+ return createSummarizerCore(container, loader, summaryVersion);
92
+ }
93
+
94
+ export async function createSummarizer(
95
+ provider: ITestObjectProvider,
96
+ container: IContainer,
97
+ summaryVersion?: string,
98
+ gcOptions?: IGCRuntimeOptions,
99
+ ): Promise<ISummarizer> {
100
+ const testContainerConfig: ITestContainerConfig = {
101
+ runtimeOptions: {
102
+ summaryOptions: defaultSummaryOptions,
103
+ gcOptions,
104
+ },
105
+ loaderProps: { configProvider: mockConfigProvider() },
106
+ };
107
+
108
+ const loader = provider.makeTestLoader(testContainerConfig);
109
+ return createSummarizerCore(container, loader, summaryVersion);
110
+ }
111
+
112
+ export async function summarizeNow(summarizer: ISummarizer, reason: string = "end-to-end test") {
113
+ const result = summarizer.summarizeOnDemand({ reason });
114
+
115
+ const submitResult = await result.summarySubmitted;
116
+ assert(submitResult.success, "on-demand summary should submit");
117
+ assert(submitResult.data.stage === "submit",
118
+ "on-demand summary submitted data stage should be submit");
119
+ assert(submitResult.data.summaryTree !== undefined, "summary tree should exist");
120
+
121
+ const broadcastResult = await result.summaryOpBroadcasted;
122
+ assert(broadcastResult.success, "summary op should be broadcast");
123
+
124
+ const ackNackResult = await result.receivedSummaryAckOrNack;
125
+ assert(ackNackResult.success, "summary op should be acked");
126
+
127
+ await new Promise((resolve) => process.nextTick(resolve));
128
+
129
+ return {
130
+ summaryTree: submitResult.data.summaryTree,
131
+ summaryVersion: ackNackResult.data.summaryAckOp.contents.handle,
132
+ };
133
+ }
134
+
135
+ export async function waitForContainerConnection(container: IContainer): Promise<void> {
136
+ if (container.connectionState !== ConnectionState.Connected) {
137
+ return new Promise((resolve) => container.once("connected", () => resolve()));
138
+ }
139
+ }
package/src/index.ts CHANGED
@@ -12,3 +12,6 @@ export * from "./retry";
12
12
  export * from "./testContainerRuntimeFactory";
13
13
  export * from "./testFluidObject";
14
14
  export * from "./timeoutUtils";
15
+ export * from "./DriverWrappers";
16
+ export * from "./TestSummaryUtils";
17
+ export * from "./TestConfigs";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/test-utils";
9
- export const pkgVersion = "2.0.0-internal.1.0.0.82159";
9
+ export const pkgVersion = "2.0.0-internal.1.0.0.83139";