/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import { EventEmitter, TypedEventEmitter } from "@fluid-internal/client-utils"; import { AttachState, IAudience, IAudienceEvents, ISelf } from "@fluidframework/container-definitions"; import { ILoader, IAudienceOwner } from "@fluidframework/container-definitions/internal"; import type { IContainerRuntimeEvents } from "@fluidframework/container-runtime-definitions/internal"; import { FluidObject, IFluidHandle, IRequest, IResponse, type ITelemetryBaseLogger } from "@fluidframework/core-interfaces"; import { IFluidHandleContext, type IFluidHandleInternal } from "@fluidframework/core-interfaces/internal"; import { IChannelServices, IChannelStorageService, IDeltaConnection, IDeltaHandler, IChannel, IFluidDataStoreRuntime, IChannelFactory, type IDeltaManagerErased } from "@fluidframework/datastore-definitions/internal"; import type { IClient } from "@fluidframework/driver-definitions"; import { IQuorumClients, ISequencedClient, ISummaryTree } from "@fluidframework/driver-definitions"; import { ITreeEntry, ISequencedDocumentMessage, type ISnapshotTree } from "@fluidframework/driver-definitions/internal"; import type { IIdCompressor } from "@fluidframework/id-compressor"; import { type IdCreationRange } from "@fluidframework/id-compressor/internal"; import { ISummaryTreeWithStats, IGarbageCollectionData, FlushMode, IFluidDataStoreChannel, VisibilityState, type ITelemetryContext, type IRuntimeMessageCollection, type OldestSupportedClientVersion } from "@fluidframework/runtime-definitions/internal"; import { MockDeltaManager } from "./mockDeltas.js"; /** * Mock implementation of IDeltaConnection for testing * @legacy @beta */ export declare class MockDeltaConnection implements IDeltaConnection { private readonly submitFn; private readonly dirtyFn; get connected(): boolean; private _connected; handler: IDeltaHandler | undefined; constructor(submitFn: (messageContent: any, localOpMetadata: unknown) => number, dirtyFn: () => void); attach(handler: IDeltaHandler): void; submit(messageContent: any, localOpMetadata: unknown): number; dirty(): void; setConnectionState(connected: boolean): void; processMessages(messageCollection: IRuntimeMessageCollection): void; reSubmit(content: any, localOpMetadata: unknown, squash: boolean): void; applyStashedOp(content: any): unknown; rollback?(message: any, localOpMetadata: unknown): void; } /** * @legacy @beta */ export interface IMockContainerRuntimePendingMessage { content: any; referenceSequenceNumber: number; clientSequenceNumber: number; localOpMetadata: unknown; } export interface IMockContainerRuntimeIdAllocationMessage { type: "idAllocation"; contents: IdCreationRange; } /** * Options for the container runtime mock. * @legacy @beta */ export interface IMockContainerRuntimeOptions { /** * Configures the flush mode for the runtime. In Immediate flush mode the runtime will immediately * send all operations to the driver layer, while in TurnBased the operations will be buffered * and then sent them as a single batch when `flush()` is called on the runtime. * * By default, flush mode is Immediate. */ readonly flushMode?: FlushMode; /** * If configured, it will simulate group batching by forcing all ops within a batch to have * the same sequence number. * * By default, the value is `false` */ readonly enableGroupedBatching?: boolean; } /** * @legacy @beta */ export interface IInternalMockRuntimeMessage { content: any; localOpMetadata?: unknown; referenceSequenceNumber?: number; } /** * Mock implementation of IContainerRuntime for testing basic submitting and processing of messages. * If test specific logic is required, extend this class and add the logic there. For an example, take a look * at MockContainerRuntimeForReconnection. * @legacy @beta */ export declare class MockContainerRuntime extends TypedEventEmitter { #private; protected readonly dataStoreRuntime: MockFluidDataStoreRuntime; protected readonly factory: MockContainerRuntimeFactory; protected readonly overrides?: { minimumSequenceNumber?: number | undefined; } | undefined; clientId: string; readonly deltaManager: MockDeltaManager; /** * @deprecated use the associated datastore to create the delta connection */ protected readonly deltaConnections: MockDeltaConnection[]; protected readonly pendingMessages: IMockContainerRuntimePendingMessage[]; protected readonly outbox: IInternalMockRuntimeMessage[]; private readonly idAllocationOutbox; /** * The runtime options this instance is using. See {@link IMockContainerRuntimeOptions}. */ protected readonly runtimeOptions: Required; constructor(dataStoreRuntime: MockFluidDataStoreRuntime, factory: MockContainerRuntimeFactory, mockContainerRuntimeOptions?: IMockContainerRuntimeOptions, overrides?: { minimumSequenceNumber?: number | undefined; } | undefined); /** * Creates a {@link MockDeltaConnection} for this container runtime. * * @deprecated use the associated datastore to create the delta connection */ createDeltaConnection(): MockDeltaConnection; private finalizeIdRange; runWithManualFlush(act: () => void | Promise): Promise; submit(messageContent: any, localOpMetadata?: unknown): number; /** * If the message is an idAllocation message, it will finalize the id range and return true. * Otherwise, it will return false. */ protected maybeProcessIdAllocationMessage(message: ISequencedDocumentMessage): boolean; private isAllocationMessage; dirty(): void; get isDirty(): boolean; /** * If flush mode is set to FlushMode.TurnBased, it will send all messages queued since the last time * this method (or `flushSomeMessages`) was called. Otherwise, calling the method does nothing. */ flush(): void; /** * If flush mode is set to FlushMode.TurnBased, it will send the specified number of messages from the outbox * queued since the last time this (or `flush`) was called. Otherwise, calling the method does nothing. * This can be useful when simulating staging mode, and we only want to flush certain messages. */ flushSomeMessages(numMessages: number): void; /** * If flush mode is set to FlushMode.TurnBased, it will rebase the current batch by resubmitting them * to the data stores. Otherwise, calling the method does nothing. * * The method requires `runtimeOptions.enableGroupedBatching` to be enabled. */ rebase(): void; protected reSubmitMessages(messagesToResubmit: { content: any; localOpMetadata?: unknown; }[]): void; /** * Rolls back all pending messages. * @remarks * This only works when the FlushMode is not immediate as immediate * flush mode send the ops to the mock runtime factory for processing/sequencing, and so those * ops are no longer local, so not available for rollback. */ rollback?(): void; private generateIdAllocationOp; private submitInternal; process(message: ISequencedDocumentMessage): void; protected addPendingMessage(content: any, localOpMetadata: unknown, clientSequenceNumber: number): void; protected processInternal(message: ISequencedDocumentMessage): [boolean, unknown]; resolveHandle(handle: IFluidHandle): Promise; } /** * Factory to create MockContainerRuntime for testing basic submitting and processing of messages. * This also acts as a very basic server that stores the messages from all the MockContainerRuntimes and * processes them when asked. * If test specific logic is required, extend this class and add the logic there. For an example, take a look * at MockContainerRuntimeFactoryForReconnection. * @legacy @beta */ export declare class MockContainerRuntimeFactory { sequenceNumber: number; minSeq: Map; readonly quorum: MockQuorumClients; /** * The MockContainerRuntimes we produce will push messages into this queue as they are submitted. * This is playing the role of the orderer, establishing a single universal order for the messages generated. * They are held in this queue until we explicitly choose to process them, at which time they are "broadcast" to * each of the runtimes. */ protected messages: ISequencedDocumentMessage[]; protected readonly runtimes: Set; /** * The container runtime options which will be provided to the all runtimes * created by this factory and also drive the way the ops are processed. * * See {@link IMockContainerRuntimeOptions} */ protected readonly runtimeOptions: Required; constructor(mockContainerRuntimeOptions?: IMockContainerRuntimeOptions); get outstandingMessageCount(): number; /** * Gets the minimum sequence number for all connected clients. */ getMinSeq(): number; createContainerRuntime(dataStoreRuntime: MockFluidDataStoreRuntime): MockContainerRuntime; removeContainerRuntime(containerRuntime: MockContainerRuntime): void; pushMessage(msg: Partial): void; protected lastProcessedMessage: ISequencedDocumentMessage | undefined; protected getFirstMessageToProcess(): ISequencedDocumentMessage; private processFirstMessage; /** * Process one of the queued messages. Throws if no messages are queued. */ processOneMessage(): void; /** * Process a given number of queued messages. Throws if there are fewer messages queued than requested. * @param count - the number of messages to process */ processSomeMessages(count: number): void; /** * Process all remaining messages in the queue. */ processAllMessages(): void; } /** * @legacy @beta */ export declare class MockQuorumClients implements IQuorumClients, EventEmitter { private readonly members; private readonly eventEmitter; constructor(...members: [string, Partial][]); addMember(id: string, client: Partial): void; removeMember(id: string): void; getMembers(): Map; getMember(clientId: string): ISequencedClient | undefined; disposed: boolean; dispose(): void; addListener(event: string | number, listener: (...args: any[]) => void): this; on(event: string | number, listener: (...args: any[]) => void): this; once(event: string | number, listener: (...args: any[]) => void): this; prependListener(event: string | number, listener: (...args: any[]) => void): this; prependOnceListener(event: string | number, listener: (...args: any[]) => void): this; removeListener(event: string | number, listener: (...args: any[]) => void): this; off(event: string | number, listener: (...args: any[]) => void): this; removeAllListeners(event?: string | number | undefined): this; setMaxListeners(n: number): this; getMaxListeners(): number; listeners(event: string | number): ReturnType; rawListeners(event: string | number): ReturnType; emit(event: string | number, ...args: any[]): boolean; eventNames(): (string | number)[]; listenerCount(type: string | number): number; } /** * @legacy @beta */ export declare class MockAudience extends TypedEventEmitter implements IAudienceOwner { private readonly audienceMembers; private _currentClientId; constructor(); addMember(clientId: string, member: IClient): void; removeMember(clientId: string): boolean; getMembers(): Map; getMember(clientId: string): IClient | undefined; getSelf(): ISelf | undefined; setCurrentClientId(clientId: string): void; } /** * Mock implementation of IRuntime for testing that does nothing * @legacy @beta * @sealed */ export declare class MockFluidDataStoreRuntime extends EventEmitter implements IFluidDataStoreRuntime, IFluidDataStoreChannel, IFluidHandleContext { constructor(overrides?: { clientId?: string; entryPoint?: IFluidHandle; id?: string; logger?: ITelemetryBaseLogger; idCompressor?: IIdCompressor; attachState?: AttachState; registry?: readonly IChannelFactory[]; minVersionForCollab?: OldestSupportedClientVersion; inStagingMode?: boolean; isDirty?: boolean; }); private readonly; readonly isReadOnly: () => boolean; readonly entryPoint: IFluidHandleInternal; /** * @see IFluidDataStoreRuntimeInternalConfig.minVersionForCollab */ readonly minVersionForCollab: OldestSupportedClientVersion; get IFluidHandleContext(): IFluidHandleContext; get rootRoutingContext(): IFluidHandleContext; get channelsRoutingContext(): IFluidHandleContext; get objectsRoutingContext(): IFluidHandleContext; readonly inStagingMode: boolean; readonly isDirty: boolean; readonly documentId: string; readonly id: string; readonly existing: boolean; options: Record; clientId: string; readonly path = ""; readonly connected = true; deltaManagerInternal: MockDeltaManager; get deltaManager(): IDeltaManagerErased; readonly loader: ILoader; readonly logger: ITelemetryBaseLogger; quorum: MockQuorumClients; private readonly audience; containerRuntime?: MockContainerRuntime; idCompressor: IIdCompressor | undefined; private readonly deltaConnections; private readonly registry?; createDeltaConnection(): MockDeltaConnection; get absolutePath(): string; /** * Whether the data store is local (not attached). * * @deprecated Use `attachState` instead * * @privateRemarks Also remove the setter when this is removed. setters don't get their own doc tags. */ get local(): boolean; set local(local: boolean); private _disposed; get disposed(): boolean; dispose(): void; getChannel(id: string): Promise; createChannel(id: string | undefined, type: string): IChannel; /** * @remarks This is for internal use only. */ ILayerCompatDetails?: unknown; addChannel(channel: IChannel): void; get isAttached(): boolean; private _attachState; get attachState(): AttachState; get visibilityState(): VisibilityState; bindChannel(channel: IChannel): void; attachGraph(): void; makeVisibleAndAttachGraph(): void; bind(handle: IFluidHandle): void; getQuorum(): IQuorumClients; getAudience(): IAudience; save(message: string): void; close(): Promise; uploadBlob(blob: ArrayBufferLike): Promise>; getBlob(blobId: string): Promise; private submitMessageInternal; private setChannelDirty; submitSignal: IFluidDataStoreRuntime["submitSignal"]; processMessages(messageCollection: IRuntimeMessageCollection): void; processSignal(message: any, local: boolean): void; updateMinSequenceNumber(value: number): void; setConnectionState(connected: boolean, clientId?: string): void; notifyReadOnlyState(readonly: boolean): void; resolveHandle(request: IRequest): Promise; request(request: IRequest): Promise; summarize(fullTree?: boolean, trackState?: boolean): Promise; getGCData(): Promise; updateUsedRoutes(usedRoutes: string[]): void; getAttachSnapshot(): ITreeEntry[]; getAttachSummary(): ISummaryTreeWithStats; getAttachGCData(telemetryContext?: ITelemetryContext | undefined): IGarbageCollectionData; setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void; waitAttached(): Promise; requestDataStore(request: IRequest): Promise; reSubmit(content: any, localOpMetadata: unknown, squash: boolean): void; applyStashedOp(content: any): Promise; rollback?(message: any, localOpMetadata: unknown): void; } /** * Mock implementation of IDeltaConnection * @internal */ export declare class MockEmptyDeltaConnection implements IDeltaConnection { connected: boolean; attach(handler: any): void; submit(messageContent: any): number; dirty(): void; } /** * Mock implementation of IChannelStorageService * @legacy @beta */ export declare class MockObjectStorageService implements IChannelStorageService { private readonly contents; private readonly snapshotTree; /** * @param contents - Key value pairs that represent a snapshot. * The keys are the path to the contents of a blob in the snapshot tree. The corresponding values are its contents. * * @remarks * The snapshot contents must not change after it has been passed here as the changes will not be reflected * in the snapshot tree retrieved via `getSnapshotTree`. */ constructor(contents: { [key: string]: string; }); readBlob(path: string): Promise; contains(path: string): Promise; list(path: string): Promise; getSnapshotTree(): ISnapshotTree; } /** * Mock implementation of IChannelServices * @legacy @beta */ export declare class MockSharedObjectServices implements IChannelServices { static createFromSummary(summaryTree: ISummaryTree): MockSharedObjectServices; deltaConnection: IDeltaConnection; objectStorage: MockObjectStorageService; constructor(contents: { [key: string]: string; }); } /** * Create an ISnapshotTree from contents object (reverse of setContentsFromSummaryTree) * @param contents - Object with path/value pairs * @returns ISnapshotTree representing the hierarchical structure */ export declare function createSnapshotTreeFromContents(contents: { [key: string]: string; }): ISnapshotTree; //# sourceMappingURL=mocks.d.ts.map