From f3e2823e5313b9c7cded84ebdac93a2a68a8efd6 Mon Sep 17 00:00:00 2001 From: Jatin Garg <48029724+jatgarg@users.noreply.github.com> Date: Wed, 30 Mar 2022 14:17:43 -0700 Subject: [PATCH] Add stress test for testing new fluid binary wire format (#9391) --- .../odsp-driver/src/compactSnapshotParser.ts | 18 +++++++++--------- .../test/test-drivers/src/odspDriverApi.ts | 2 +- .../test-service-load/src/optionsMatrix.ts | 12 ++++++++++++ packages/test/test-service-load/src/runner.ts | 9 ++++++++- .../test-service-load/src/testConfigFile.ts | 6 ++++-- packages/test/test-service-load/src/utils.ts | 11 ++++++++++- .../test/test-service-load/testConfig.json | 14 ++++++++++++++ 7 files changed, 58 insertions(+), 14 deletions(-) diff --git a/packages/drivers/odsp-driver/src/compactSnapshotParser.ts b/packages/drivers/odsp-driver/src/compactSnapshotParser.ts index 5f2ab0433508..1a96ac24d2d9 100644 --- a/packages/drivers/odsp-driver/src/compactSnapshotParser.ts +++ b/packages/drivers/odsp-driver/src/compactSnapshotParser.ts @@ -14,6 +14,7 @@ import { assertNumberInstance, getAndValidateNodeProps, NodeCore, + NodeTypes, TreeBuilder, } from "./zipItDataRepresentationUtils"; @@ -28,7 +29,8 @@ interface ISnapshotSection { * Recreates blobs section of the tree. * @param node - tree node to read blob section from */ -function readBlobSection(node: NodeCore) { +function readBlobSection(node: NodeTypes) { + assertNodeCoreInstance(node, "TreeBlobs should be of type NodeCore"); const blobs: Map = new Map(); for (let count = 0; count < node.length; ++count) { const blob = node.getNode(count); @@ -44,7 +46,8 @@ function readBlobSection(node: NodeCore) { * Recreates ops section of the tree. * @param node - tree node to read ops section from */ -function readOpsSection(node: NodeCore) { +function readOpsSection(node: NodeTypes) { + assertNodeCoreInstance(node, "Deltas should be of type NodeCore"); const ops: ISequencedDocumentMessage[] = []; const records = getAndValidateNodeProps(node, ["firstSequenceNumber", "deltas"]); assertNumberInstance(records.firstSequenceNumber, "Seq number should be a number"); @@ -93,7 +96,8 @@ function readTreeSection(node: NodeCore) { * Recreates snapshot tree out of tree representation. * @param node - tree node to de-serialize from */ -function readSnapshotSection(node: NodeCore): ISnapshotSection { +function readSnapshotSection(node: NodeTypes): ISnapshotSection { + assertNodeCoreInstance(node, "Snapshot should be of type NodeCore"); const records = getAndValidateNodeProps(node, ["id", "sequenceNumber", "treeNodes"]); @@ -120,7 +124,7 @@ export function parseCompactSnapshotResponse(buffer: ReadBuffer): ISnapshotConte const root = builder.getNode(0); const records = getAndValidateNodeProps(root, - ["mrv", "cv", "snapshot", "blobs", "deltas"]); + ["mrv", "cv", "snapshot", "blobs", "deltas"], false); assertBlobCoreInstance(records.mrv, "minReadVersion should be of BlobCore type"); assertBlobCoreInstance(records.cv, "createVersion should be of BlobCore type"); @@ -129,13 +133,9 @@ export function parseCompactSnapshotResponse(buffer: ReadBuffer): ISnapshotConte assert(records.cv.toString() >= snapshotMinReadVersion, 0x210 /* "Snapshot should be created with minReadVersion or above" */); - assertNodeCoreInstance(records.snapshot, "Snapshot should be of type NodeCore"); - assertNodeCoreInstance(records.blobs, "TreeBlobs should be of type NodeCore"); - assertNodeCoreInstance(records.deltas, "Deltas should be of type NodeCore"); - return { ...readSnapshotSection(records.snapshot), blobs: readBlobSection(records.blobs), - ops: readOpsSection(records.deltas), + ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [], }; } diff --git a/packages/test/test-drivers/src/odspDriverApi.ts b/packages/test/test-drivers/src/odspDriverApi.ts index bfb5a3c6819c..145fbad75352 100644 --- a/packages/test/test-drivers/src/odspDriverApi.ts +++ b/packages/test/test-drivers/src/odspDriverApi.ts @@ -62,7 +62,7 @@ export const generateOdspHostStoragePolicy = (seed: number) => { sessionOptions: [undefined, ...generatePairwiseOptions(odspSessionOptions, seed)], enableRedeemFallback: booleanCases, cacheCreateNewSummary: booleanCases, - fetchBinarySnapshotFormat: [false], + fetchBinarySnapshotFormat: [undefined], isolateSocketCache: [true], enableShareLinkWithCreate: [false], }; diff --git a/packages/test/test-service-load/src/optionsMatrix.ts b/packages/test/test-service-load/src/optionsMatrix.ts index 945e4928d042..79b9f742e782 100644 --- a/packages/test/test-service-load/src/optionsMatrix.ts +++ b/packages/test/test-service-load/src/optionsMatrix.ts @@ -15,6 +15,7 @@ import { numberCases, } from "@fluidframework/test-pairwise-generator"; import { ILoaderOptions } from "@fluidframework/container-loader"; +import { ConfigTypes } from "@fluidframework/telemetry-utils"; const loaderOptionsMatrix: OptionsMatrix = { cache: booleanCases, @@ -87,3 +88,14 @@ export function generateRuntimeOptions( {...overrides, gcOptions: undefined, summaryOptions: undefined}), seed); } + +export function generateConfigurations( + seed: number, overrides: OptionsMatrix> | undefined, +): Record[] { + if (overrides === undefined) { + return [{}]; + } + return generatePairwiseOptions>( + overrides, + seed); +} diff --git a/packages/test/test-service-load/src/runner.ts b/packages/test/test-service-load/src/runner.ts index 04e509a019e9..d3d2b85897c4 100644 --- a/packages/test/test-service-load/src/runner.ts +++ b/packages/test/test-service-load/src/runner.ts @@ -17,7 +17,7 @@ import { ITelemetryLogger } from "@fluidframework/common-definitions"; import { ILoadTest, IRunConfig } from "./loadTestDataStore"; import { createCodeLoader, createTestDriver, getProfile, loggerP, safeExit } from "./utils"; import { FaultInjectionDocumentServiceFactory } from "./faultInjectionDriver"; -import { generateLoaderOptions, generateRuntimeOptions } from "./optionsMatrix"; +import { generateConfigurations, generateLoaderOptions, generateRuntimeOptions } from "./optionsMatrix"; function printStatus(runConfig: IRunConfig, message: string) { if (runConfig.verbose) { @@ -139,6 +139,8 @@ async function runnerProcess( const containerOptions = generateRuntimeOptions( seed, runConfig.testConfig?.optionOverrides?.[driver]?.container); + const configurations = generateConfigurations( + seed, runConfig.testConfig?.optionOverrides?.[driver]?.configurations); const testDriver: ITestDriver = await createTestDriver(driver, seed, runConfig.runId); const baseLogger = await loggerP; const logger = ChildLogger.create(baseLogger, undefined, @@ -180,6 +182,11 @@ async function runnerProcess( codeLoader: createCodeLoader(containerOptions[runConfig.runId % containerOptions.length]), logger, options: loaderOptions[runConfig.runId % containerOptions.length], + configProvider: { + getRawConfig(name) { + return configurations[runConfig.runId % configurations.length][name]; + }, + }, }); const container: IContainer = await loader.resolve({ url, headers }); diff --git a/packages/test/test-service-load/src/testConfigFile.ts b/packages/test/test-service-load/src/testConfigFile.ts index afc89f0bd065..0c2c3e097850 100644 --- a/packages/test/test-service-load/src/testConfigFile.ts +++ b/packages/test/test-service-load/src/testConfigFile.ts @@ -5,6 +5,7 @@ import { ILoaderOptions } from "@fluidframework/container-definitions"; import { IContainerRuntimeOptions } from "@fluidframework/container-runtime"; +import { ConfigTypes } from "@fluidframework/telemetry-utils"; import { TestDriverTypes } from "@fluidframework/test-driver-definitions"; import { OptionsMatrix } from "@fluidframework/test-pairwise-generator"; @@ -43,6 +44,7 @@ export interface ILoadTestConfig { } export interface OptionOverride{ - loader?: Partial>, - container?: Partial> + loader?: Partial>; + container?: Partial>; + configurations?: OptionsMatrix>; } diff --git a/packages/test/test-service-load/src/utils.ts b/packages/test/test-service-load/src/utils.ts index 0590c28e2e8e..13bf1ecbf800 100644 --- a/packages/test/test-service-load/src/utils.ts +++ b/packages/test/test-service-load/src/utils.ts @@ -19,7 +19,7 @@ import { ITelemetryBufferedLogger, ITestDriver, TestDriverTypes } from "@fluidfr import { createFluidTestDriver, generateOdspHostStoragePolicy, OdspTestDriver } from "@fluidframework/test-drivers"; import { LocalCodeLoader } from "@fluidframework/test-utils"; import { createFluidExport, ILoadTest } from "./loadTestDataStore"; -import { generateLoaderOptions, generateRuntimeOptions } from "./optionsMatrix"; +import { generateConfigurations, generateLoaderOptions, generateRuntimeOptions } from "./optionsMatrix"; import { pkgName, pkgVersion } from "./packageVersion"; import { ILoadTestConfig, ITestConfig } from "./testConfigFile"; @@ -126,6 +126,10 @@ export async function initialize(testDriver: ITestDriver, seed: number, testConf const containerOptions = random.pick( randEng, generateRuntimeOptions(seed, testConfig.optionOverrides?.[testDriver.type]?.container)); + const configurations = random.pick( + randEng, + generateConfigurations(seed, testConfig?.optionOverrides?.[testDriver.type]?.configurations)); + // Construct the loader const loader = new Loader({ urlResolver: testDriver.createUrlResolver(), @@ -140,6 +144,11 @@ export async function initialize(testDriver: ITestDriver, seed: number, testConf }), options: loaderOptions, detachedBlobStorage: new MockDetachedBlobStorage(), + configProvider: { + getRawConfig(name) { + return configurations[name]; + }, + }, }); const container: IContainer = await loader.createDetachedContainer(codeDetails); diff --git a/packages/test/test-service-load/testConfig.json b/packages/test/test-service-load/testConfig.json index 793312846868..cf9c58885445 100644 --- a/packages/test/test-service-load/testConfig.json +++ b/packages/test/test-service-load/testConfig.json @@ -86,6 +86,20 @@ "totalBlobCount": 300, "blobSize": 10240, "detachedBlobCount": 10 + }, + "binarySnapshotFormat": { + "opRatePerMin": 60, + "progressIntervalMs": 5000, + "numClients": 4, + "totalSendCount": 150, + "readWriteCycleMs": 10000, + "optionOverrides":{ + "odsp":{ + "configurations":{ + "Fluid.Driver.Odsp.binaryFormatSnapshot": [true] + } + } + } } } }