From 87d0cb96359bd76d7d3386072a5aee054d173356 Mon Sep 17 00:00:00 2001 From: Scott Norton Date: Tue, 10 Jun 2025 16:52:09 +0000 Subject: [PATCH 1/5] use minVersionForCollab in e2e tests --- .../src/test/blobs.spec.ts | 1 + .../src/test/compression.spec.ts | 20 ++- .../src/test/containerRuntime.spec.ts | 1 + .../src/test/offline/stashedOps.spec.ts | 1 + .../test-version-utils/src/compatUtils.ts | 159 +++++------------- 5 files changed, 62 insertions(+), 120 deletions(-) diff --git a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts index 35adcebee380..382d24f53c61 100644 --- a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts @@ -67,6 +67,7 @@ function makeTestContainerConfig( createBlobPayloadPending, }, registry, + minVersionForCollab: "2.40.0", }; } diff --git a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts index ca58ddbe68e6..d94266635493 100644 --- a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts @@ -16,6 +16,7 @@ import { CompressionAlgorithms, type IContainerRuntimeOptions, type IContainerRuntimeOptionsInternal, + type MinimumVersionForCollab, } from "@fluidframework/container-runtime/internal"; // TODO:AB#6558: This should be provided based on the compatibility configuration. // eslint-disable-next-line @typescript-eslint/no-restricted-imports @@ -57,11 +58,13 @@ const compressionSuite = (getProvider, apis?) => { async function setupContainers( runtimeOptions: IContainerRuntimeOptionsInternal = defaultRuntimeOptions, + minVersionForCollab: MinimumVersionForCollab | undefined = undefined, ) { const containerConfig: ITestContainerConfig = { registry: [["mapKey", SharedMap.getFactory()]], runtimeOptions, fluidDataObjectType: DataObjectFactoryType.Test, + minVersionForCollab, }; const localContainer = await provider.makeTestContainer(containerConfig); localDataObject = @@ -132,14 +135,17 @@ const compressionSuite = (getProvider, apis?) => { ) { this.skip(); } - await setupContainers({ - compressionOptions: { - minimumBatchSizeInBytes: option.compression ? 10 : Number.POSITIVE_INFINITY, - compressionAlgorithm: CompressionAlgorithms.lz4, + await setupContainers( + { + compressionOptions: { + minimumBatchSizeInBytes: option.compression ? 10 : Number.POSITIVE_INFINITY, + compressionAlgorithm: CompressionAlgorithms.lz4, + }, + chunkSizeInBytes: option.chunking ? 100 : Number.POSITIVE_INFINITY, + enableGroupedBatching: option.grouping, }, - chunkSizeInBytes: option.chunking ? 100 : Number.POSITIVE_INFINITY, - enableGroupedBatching: option.grouping, - }); + "2.0.0", // minVersionForCollab + ); const values = [ generateRandomStringOfSize(100), generateRandomStringOfSize(100), diff --git a/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts b/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts index e559458dc127..89c2fe4d7cf1 100644 --- a/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts @@ -123,6 +123,7 @@ describeCompat( enableGroupedBatching: compression, // Compression w/o grouping is not supported chunkSizeInBytes: chunking ? 200 : Infinity, }, + minVersionForCollab: "2.0.0", }; const container = await provider.makeTestContainer(options); entry = await getEntryPoint(container); diff --git a/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts b/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts index f311ca7444e5..4e374130de63 100644 --- a/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts @@ -1851,6 +1851,7 @@ describeCompat( state: "disabled", }, }, + enableRuntimeIdCompressor: "on", }, loaderProps: { configProvider: configProvider({ diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index 9fbbdbd9232f..5db936a147e0 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -6,13 +6,7 @@ import { mixinAttributor } from "@fluid-experimental/attributor"; import { TestDriverTypes } from "@fluid-internal/test-driver-definitions"; import { FluidTestDriverConfig, createFluidTestDriver } from "@fluid-private/test-drivers"; -import { - DefaultSummaryConfiguration, - CompressionAlgorithms, - disabledCompressionConfig, - ICompressionRuntimeOptions, - type IContainerRuntimeOptionsInternal, -} from "@fluidframework/container-runtime/internal"; +import type { MinimumVersionForCollab } from "@fluidframework/container-runtime/internal"; import { FluidObject, IFluidLoadable, IRequest } from "@fluidframework/core-interfaces"; import { IFluidHandleContext } from "@fluidframework/core-interfaces/internal"; import { assert, unreachableCase } from "@fluidframework/core-utils/internal"; @@ -52,98 +46,37 @@ import { getRequestedVersion } from "./versionUtils.js"; export const TestDataObjectType = "@fluid-example/test-dataStore"; /** - * This function modifies container runtime options according to a version of runtime used. - * If a version of runtime does not support some options, they are removed. - * If a version runtime supports some options, such options are enabled to increase a chance of - * hitting feature set controlled by such options, and thus increase chances of finding product bugs. + * Determines the minimumVersionForCollab that should be used for cross-client compatibility scenarios. + * We will use the lesser of the containerRuntimeVersion and containerRuntimeForLoadingVersion * - * @param version - a version of container runtime to be used in test - * @param optionsArg - input runtime options (optional) - * @returns - runtime options that should be used with a given version of container runtime - * @internal + * Note: The MinimumVersionForCollab returned will only be used if a minVersionForCollab was not provided + * in the ITestContainerConfig object. */ -function filterRuntimeOptionsForVersion( - version: string, - optionsArg: IContainerRuntimeOptionsInternal = { - summaryOptions: { - summaryConfigOverrides: { - ...DefaultSummaryConfiguration, - ...{ - initialSummarizerDelayMs: 0, - }, - }, - }, - }, - driverType: TestDriverTypes, -) { - let options = { ...optionsArg }; - - // No test fails with this option, it allows us to validate properly expectations and - // implementation of services - options.loadSequenceNumberVerification = "close"; - - const compressorDisabled: ICompressionRuntimeOptions = { - minimumBatchSizeInBytes: Number.POSITIVE_INFINITY, - compressionAlgorithm: CompressionAlgorithms.lz4, - }; - - // These is the "maximum" config. - const { - compressionOptions = options.enableGroupedBatching === false - ? disabledCompressionConfig - : { - minimumBatchSizeInBytes: 200, - compressionAlgorithm: CompressionAlgorithms.lz4, - }, - enableGroupedBatching = true, - enableRuntimeIdCompressor = "on", - // Some t9s tests timeout with small settings. This is likely due to too many ops going through. - // Reduce chunking cut-off for such tests. - chunkSizeInBytes = driverType === "local" ? 200 : 1000, - } = options; - - if (version.startsWith("1.")) { - options = { - // None of these features are supported by 1.3 - compressionOptions: disabledCompressionConfig, - enableGroupedBatching: false, - enableRuntimeIdCompressor: undefined, - // Enable chunking. - // We need to ensure that 1.x documents (that use chunking) can still be opened by 2.x. - // This options does nothing for 2.x builds as chunking is only enabled if compression is enabled. - chunkSizeInBytes, - ...options, - }; - } else if (version.startsWith("2.0.0-rc.1.")) { - options = { - compressionOptions: compressorDisabled, // Can't use compression, need https://github.com/microsoft/FluidFramework/pull/20111 fix - enableGroupedBatching, - enableRuntimeIdCompressor: undefined, // it was boolean in RC1, switched to enum in RC2 - chunkSizeInBytes: Number.POSITIVE_INFINITY, // disabled, need https://github.com/microsoft/FluidFramework/pull/20115 fix - ...options, - }; - } else if (version.startsWith("2.0.0-rc.2.")) { - options = { - compressionOptions: compressorDisabled, // Can't use compression, need https://github.com/microsoft/FluidFramework/pull/20111 fix - enableGroupedBatching, - // control over schema was generalized in RC3 - see https://github.com/microsoft/FluidFramework/pull/20174 - // IdCompressor settings moved around - can't enable them across versions without tripping on asserts - enableRuntimeIdCompressor: undefined, - chunkSizeInBytes: Number.POSITIVE_INFINITY, // disabled, need https://github.com/microsoft/FluidFramework/pull/20115 fix - ...options, - }; - } else { - // "2.0.0-rc.3." ++ - options = { - compressionOptions, - enableGroupedBatching, - chunkSizeInBytes, - enableRuntimeIdCompressor, - ...options, - }; +function getMinVersionForCollab( + containerRuntimeVersion: string, + containerRuntimeForLoadingVersion: string | undefined, +): MinimumVersionForCollab { + isMinimumVersionForCollab(containerRuntimeVersion); + if (containerRuntimeForLoadingVersion === undefined) { + // If `containerRuntimeForLoading` is not defined, then this is not a cross-client compat scenario. + // In this case, we can use the `containerRuntimeVersion` as the default minVersionForCollab. + return containerRuntimeVersion; } + isMinimumVersionForCollab(containerRuntimeForLoadingVersion); + // If `containerRuntimeForLoading` is defined, we will use the lower of the two versions to ensure + // compatibility between the two runtimes. + return semver.compare(containerRuntimeVersion, containerRuntimeForLoadingVersion) <= 0 + ? containerRuntimeVersion + : containerRuntimeForLoadingVersion; +} - return options; +/** + * Asserts the given version is valid semver and is type MinimumVersionForCollab. + */ +function isMinimumVersionForCollab( + version: string, +): asserts version is MinimumVersionForCollab { + assert(semver.valid(version) !== null, "version must be valid semver"); } /** @@ -246,12 +179,12 @@ export async function getVersionedTestObjectProviderFromApis( return new factoryCtor( TestDataObjectType, dataStoreFactory, - filterRuntimeOptionsForVersion( - apis.containerRuntime.version, - containerOptions?.runtimeOptions, - type, - ), - containerOptions?.minVersionForCollab, + containerOptions?.runtimeOptions, + containerOptions?.minVersionForCollab ?? + getMinVersionForCollab( + apis.containerRuntime.version, + apis.containerRuntimeForLoading?.version, + ), ); }; @@ -359,12 +292,12 @@ export async function getCompatVersionedTestObjectProviderFromApis( return new factoryCtor( TestDataObjectType, dataStoreFactory, - filterRuntimeOptionsForVersion( - minVersion, - containerOptions?.runtimeOptions, - driverConfig.type, - ), - containerOptions?.minVersionForCollab, + containerOptions?.runtimeOptions, + containerOptions?.minVersionForCollab ?? + getMinVersionForCollab( + apis.containerRuntime.version, + apis.containerRuntimeForLoading?.version, + ), [innerRequestHandler], ); }; @@ -384,12 +317,12 @@ export async function getCompatVersionedTestObjectProviderFromApis( return new factoryCtor( TestDataObjectType, dataStoreFactory, - filterRuntimeOptionsForVersion( - minVersion, - containerOptions?.runtimeOptions, - driverConfig.type, - ), - containerOptions?.minVersionForCollab, + containerOptions?.runtimeOptions, + containerOptions?.minVersionForCollab ?? + getMinVersionForCollab( + apis.containerRuntime.version, + apis.containerRuntimeForLoading.version, + ), [innerRequestHandler], ); }; From 2c138dcaed65179f02bb0704ef890abab04b98ce Mon Sep 17 00:00:00 2001 From: Scott Norton Date: Wed, 11 Jun 2025 19:28:21 +0000 Subject: [PATCH 2/5] pr feedback --- .../test-version-utils/src/compatUtils.ts | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index 5db936a147e0..63d251bcb522 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -46,28 +46,39 @@ import { getRequestedVersion } from "./versionUtils.js"; export const TestDataObjectType = "@fluid-example/test-dataStore"; /** - * Determines the minimumVersionForCollab that should be used for cross-client compatibility scenarios. - * We will use the lesser of the containerRuntimeVersion and containerRuntimeForLoadingVersion + * Determines the MinimumVersionForCollab that should be used for cross-client compatibility tests. + * + * In cross-client compat tests, a different version of the runtime is being used to create and load + * containers. The MinimumVersionForCollab returned will be the lesser of the two versions: + * - runtimeVersion: The version of the runtime that is being used to create the container. + * - runtimeVersionForLoading: The version of the runtime that is being used to load the container. + * Additionally, runtimeVersionForLoading is only defined in cross-client compat tests, so if it's undefined + * we will just use runtimeVersion. * * Note: The MinimumVersionForCollab returned will only be used if a minVersionForCollab was not provided * in the ITestContainerConfig object. + * + * For example, if we are running a cross-client compat test with the following versions: + * - runtimeVersion: "2.42.0" + * - runtimeVersionForLoading: "1.4.0" + * We will return "1.4.0" since it's the lower of the two versions. */ function getMinVersionForCollab( - containerRuntimeVersion: string, - containerRuntimeForLoadingVersion: string | undefined, + runtimeVersion: string, + runtimeVersionForLoading: string | undefined, ): MinimumVersionForCollab { - isMinimumVersionForCollab(containerRuntimeVersion); - if (containerRuntimeForLoadingVersion === undefined) { + isMinimumVersionForCollab(runtimeVersion); + if (runtimeVersionForLoading === undefined) { // If `containerRuntimeForLoading` is not defined, then this is not a cross-client compat scenario. - // In this case, we can use the `containerRuntimeVersion` as the default minVersionForCollab. - return containerRuntimeVersion; + // In this case, we can use the `runtimeVersion` as the default minVersionForCollab. + return runtimeVersion; } - isMinimumVersionForCollab(containerRuntimeForLoadingVersion); + isMinimumVersionForCollab(runtimeVersionForLoading); // If `containerRuntimeForLoading` is defined, we will use the lower of the two versions to ensure // compatibility between the two runtimes. - return semver.compare(containerRuntimeVersion, containerRuntimeForLoadingVersion) <= 0 - ? containerRuntimeVersion - : containerRuntimeForLoadingVersion; + return semver.compare(runtimeVersion, runtimeVersionForLoading) <= 0 + ? runtimeVersion + : runtimeVersionForLoading; } /** From 24355ed37c3d3a0aa16b21319a71125198e06dba Mon Sep 17 00:00:00 2001 From: Scott Norton Date: Mon, 16 Jun 2025 20:54:14 +0000 Subject: [PATCH 3/5] add comments for test changes --- packages/test/test-end-to-end-tests/src/test/blobs.spec.ts | 2 ++ .../test/test-end-to-end-tests/src/test/compression.spec.ts | 2 ++ .../test-end-to-end-tests/src/test/containerRuntime.spec.ts | 2 ++ .../test-end-to-end-tests/src/test/offline/stashedOps.spec.ts | 2 +- 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts index 382d24f53c61..320e737e4ee2 100644 --- a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts @@ -67,6 +67,8 @@ function makeTestContainerConfig( createBlobPayloadPending, }, registry, + // We set minVersionForCollab to 2.40.0 so we can test createBlobPayloadPending with older clients + // in cross-client compat tests. minVersionForCollab: "2.40.0", }; } diff --git a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts index d94266635493..d37e98b26157 100644 --- a/packages/test/test-end-to-end-tests/src/test/compression.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/compression.spec.ts @@ -144,6 +144,8 @@ const compressionSuite = (getProvider, apis?) => { chunkSizeInBytes: option.chunking ? 100 : Number.POSITIVE_INFINITY, enableGroupedBatching: option.grouping, }, + // We set minVersionForCollab to 2.0.0 so we can test grouping and batching features with older clients. + // in cross-client compat tests. "2.0.0", // minVersionForCollab ); const values = [ diff --git a/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts b/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts index 89c2fe4d7cf1..7700b6526a57 100644 --- a/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/containerRuntime.spec.ts @@ -123,6 +123,8 @@ describeCompat( enableGroupedBatching: compression, // Compression w/o grouping is not supported chunkSizeInBytes: chunking ? 200 : Infinity, }, + // We set minVersionForCollab to 2.0.0 so we can test schema control with older clients + // in cross-client compat tests. minVersionForCollab: "2.0.0", }; const container = await provider.makeTestContainer(options); diff --git a/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts b/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts index 4e374130de63..278fb7a26097 100644 --- a/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/offline/stashedOps.spec.ts @@ -1851,7 +1851,7 @@ describeCompat( state: "disabled", }, }, - enableRuntimeIdCompressor: "on", + enableRuntimeIdCompressor: "on", // id compressor is not enabled by default }, loaderProps: { configProvider: configProvider({ From 52bbadbec51c41db9cfb6fddf1d63d7fc003b6df Mon Sep 17 00:00:00 2001 From: Scott Norton Date: Fri, 20 Jun 2025 13:41:10 +0000 Subject: [PATCH 4/5] rename assertValidMinVersionForCollab --- packages/test/test-version-utils/src/compatUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index ae9b3ef4f252..c2e5bc144b27 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -71,13 +71,13 @@ function getMinVersionForCollab( runtimeVersion: string, runtimeVersionForLoading: string | undefined, ): MinimumVersionForCollab { - isMinimumVersionForCollab(runtimeVersion); + assertValidMinVersionForCollab(runtimeVersion); if (runtimeVersionForLoading === undefined) { // If `containerRuntimeForLoading` is not defined, then this is not a cross-client compat scenario. // In this case, we can use the `runtimeVersion` as the default minVersionForCollab. return runtimeVersion; } - isMinimumVersionForCollab(runtimeVersionForLoading); + assertValidMinVersionForCollab(runtimeVersionForLoading); // If `containerRuntimeForLoading` is defined, we will use the lower of the two versions to ensure // compatibility between the two runtimes. return semver.compare(runtimeVersion, runtimeVersionForLoading) <= 0 @@ -88,7 +88,7 @@ function getMinVersionForCollab( /** * Asserts the given version is valid semver and is type MinimumVersionForCollab. */ -function isMinimumVersionForCollab( +function assertValidMinVersionForCollab( version: string, ): asserts version is MinimumVersionForCollab { assert(semver.valid(version) !== null, "version must be valid semver"); From 8921d2474627101b1c64d2c9b54a9e3e474bd187 Mon Sep 17 00:00:00 2001 From: Scott Norton Date: Fri, 20 Jun 2025 17:42:28 +0000 Subject: [PATCH 5/5] change assertValidMinVersionForCollab to throw error --- packages/test/test-version-utils/src/compatUtils.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index c2e5bc144b27..4f8791845cf2 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -91,7 +91,9 @@ function getMinVersionForCollab( function assertValidMinVersionForCollab( version: string, ): asserts version is MinimumVersionForCollab { - assert(semver.valid(version) !== null, "version must be valid semver"); + if (semver.valid(version) === null) { + throw new Error(`Runtime version must be valid semver: ${version}`); + } } /**