diff --git a/packages/test/test-version-utils/src/compatUtils.ts b/packages/test/test-version-utils/src/compatUtils.ts index b87564924762..4f8791845cf2 100644 --- a/packages/test/test-version-utils/src/compatUtils.ts +++ b/packages/test/test-version-utils/src/compatUtils.ts @@ -10,13 +10,7 @@ import { type RouterliciousEndpoint, } 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"; @@ -56,98 +50,50 @@ 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 tests. * - * @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 + * 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 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( + runtimeVersion: string, + runtimeVersionForLoading: string | undefined, +): MinimumVersionForCollab { + 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; } + 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 + ? runtimeVersion + : runtimeVersionForLoading; +} - return options; +/** + * Asserts the given version is valid semver and is type MinimumVersionForCollab. + */ +function assertValidMinVersionForCollab( + version: string, +): asserts version is MinimumVersionForCollab { + if (semver.valid(version) === null) { + throw new Error(`Runtime version must be valid semver: ${version}`); + } } /** @@ -250,12 +196,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, + ), ); }; @@ -363,12 +309,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], ); }; @@ -388,12 +334,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], ); };