@fluidframework/test-utils 0.55.0-48551 → 0.56.0
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.
- package/dist/loaderContainerTracker.js +1 -1
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/testObjectProvider.d.ts +12 -15
- package/dist/testObjectProvider.d.ts.map +1 -1
- package/dist/testObjectProvider.js +11 -18
- package/dist/testObjectProvider.js.map +1 -1
- package/dist/timeoutUtils.d.ts.map +1 -1
- package/dist/timeoutUtils.js +8 -5
- package/dist/timeoutUtils.js.map +1 -1
- package/package.json +21 -21
- package/src/loaderContainerTracker.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/testObjectProvider.ts +23 -31
- package/src/timeoutUtils.ts +12 -7
|
@@ -102,7 +102,7 @@ class LoaderContainerTracker {
|
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
trackLastProposal(container) {
|
|
105
|
-
container.
|
|
105
|
+
container.on("codeDetailsProposed", (value, proposal) => {
|
|
106
106
|
if (proposal.sequenceNumber > this.lastProposalSeqNum) {
|
|
107
107
|
this.lastProposalSeqNum = proposal.sequenceNumber;
|
|
108
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.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 { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { Container } from \"@fluidframework/container-loader\";\nimport { IDocumentMessage, ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n // A short number for debug output\n index: number;\n\n // LoaderContainerTracker paused state\n paused: boolean;\n\n // Tracking trailing no-op that may or may be acked by the server so we can discount them\n // See issue #5629\n startTrailingNoOps: number;\n trailingNoOps: number;\n\n // Track last proposal to ensure no unresolved proposal\n lastProposal: number;\n}\n\nexport class LoaderContainerTracker implements IOpProcessingController {\n private readonly containers = new Map<IContainer, ContainerRecord>();\n private lastProposalSeqNum: number = 0;\n\n /**\n * Add a loader to start to track any container created from them\n * @param loader - loader to start tracking any container created.\n */\n public add<LoaderType extends IHostLoader>(loader: LoaderType) {\n // TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n const patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n const boundFn = fn.bind(loader);\n return async (...args: T[]) => {\n const container = await boundFn(...args);\n this.addContainer(container);\n return container;\n };\n };\n loader.resolve = patch(loader.resolve);\n loader.createDetachedContainer = patch(loader.createDetachedContainer);\n loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);\n }\n\n /**\n * Utility function to add container to be tracked.\n *\n * @param container - container to add\n */\n private addContainer(container: IContainer) {\n // ignore summarizer\n if (!container.deltaManager.clientDetails.capabilities.interactive) { return; }\n\n // don't add container that is already tracked\n if (this.containers.has(container)) { return; }\n\n const record = {\n index: this.containers.size,\n paused: false,\n startTrailingNoOps: 0,\n trailingNoOps: 0,\n lastProposal: 0,\n };\n this.containers.set(container, record);\n this.trackTrailingNoOps(container, record);\n this.trackLastProposal(container);\n this.setupTrace(container, record.index);\n }\n\n /**\n * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n *\n * @param container - the container to track\n * @param record - the record to update the trailing op information\n */\n private trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n if (msg.type === MessageType.NoOp) {\n // Track the NoOp that was sent.\n if (record.trailingNoOps === 0) {\n // record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n record.startTrailingNoOps = msg.clientSequenceNumber;\n }\n record.trailingNoOps++;\n } else {\n // Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n record.trailingNoOps = 0;\n }\n }\n });\n\n container.deltaManager.inbound.on(\"push\", (message) => {\n // Received the no op back, update the record if we are tracking\n if (message.type === MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && record.trailingNoOps !== 0\n && record.startTrailingNoOps <= message.clientSequenceNumber\n ) {\n // NoOp might have coalesced and skipped ahead some sequence number\n // update the record and skip ahead as well\n const oldStartTrailingNoOps = record.startTrailingNoOps;\n record.startTrailingNoOps = message.clientSequenceNumber + 1;\n record.trailingNoOps -= (record.startTrailingNoOps - oldStartTrailingNoOps);\n }\n });\n\n container.on(\"disconnected\", () => {\n // reset on disconnect.\n record.trailingNoOps = 0;\n });\n }\n\n private trackLastProposal(container: IContainer) {\n container.getQuorum().on(\"addProposal\", (proposal) => {\n if (proposal.sequenceNumber > this.lastProposalSeqNum) {\n this.lastProposalSeqNum = proposal.sequenceNumber;\n }\n });\n }\n\n /**\n * Reset the tracker, closing all containers and stop tracking them.\n */\n public reset() {\n this.lastProposalSeqNum = 0;\n for (const container of this.containers.keys()) {\n container.close();\n }\n this.containers.clear();\n\n // REVIEW: do we need to unpatch the loaders?\n }\n\n /**\n * Make sure all the tracked containers are synchronized.\n * - No isDirty (non-readonly) containers\n * - No extra clientId in quorum of any container that is not tracked and still opened.\n * - i.e. no pending Join/Leave message.\n * - No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n * - lastSequenceNumber of all container is the same\n * - clientSequenceNumberObserved is the same as clientSequenceNumber sent\n * - this overlaps with !isDirty, but include task scheduler ops.\n * - Trailing NoOp is tracked and don't count as pending ops.\n */\n public async ensureSynchronized(...containers: IContainer[]) {\n const resumed = this.resumeProcessing(...containers);\n\n let waitingSequenceNumberSynchronized = false;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const containersToApply = this.getContainers(containers);\n if (containersToApply.length === 0) { break; }\n\n // Ignore readonly dirty containers, because it can't sent up and nothing can be done about it being dirty\n const dirtyContainers =\n containersToApply.filter((c) => c.deltaManager.readOnlyInfo.readonly !== true && c.isDirty);\n if (dirtyContainers.length === 0) {\n // Wait for all the leave messages\n const pendingClients = this.getPendingClients(containersToApply);\n if (pendingClients.length === 0) {\n if (this.isSequenceNumberSynchronized(containersToApply)) {\n // done, we are in sync\n break;\n }\n if (!waitingSequenceNumberSynchronized) {\n // Only write it out once\n waitingSequenceNumberSynchronized = true;\n debugWait(\"Waiting for sequence number synchronized\");\n await this.waitForAnyInboundOps(containersToApply);\n }\n } else {\n waitingSequenceNumberSynchronized = false;\n await this.waitForPendingClients(pendingClients);\n }\n } else {\n // Wait for all the containers to be saved\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);\n waitingSequenceNumberSynchronized = false;\n await Promise.all(dirtyContainers.map(async (c) => new Promise((resolve) => c.once(\"saved\", resolve))));\n }\n\n // yield a turn to allow side effect of the ops we just processed execute before we check again\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Pause all container that was resumed\n // don't call pause if resumed is empty and pause everything, which is not what we want\n if (resumed.length !== 0) {\n await this.pauseProcessing(...resumed);\n }\n\n debugWait(\"Synchronized\");\n }\n\n /**\n * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * @param containersToApply - the set of containers to check\n */\n private getPendingClients(containersToApply: IContainer[]) {\n // All the clientId we track should be a superset of the quorum, otherwise, we are missing\n // leave messages\n const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n const openedClientId = openedDocuments.map((container) => (container as Container).clientId);\n\n const pendingClients: [IContainer, Set<string>][] = [];\n containersToApply.forEach((container) => {\n const pendingClientId = new Set<string>();\n const quorum = container.getQuorum();\n quorum.getMembers().forEach((client, clientId) => {\n // ignore summarizer\n if (!client.client.details.capabilities.interactive) { return; }\n if (!openedClientId.includes(clientId)) {\n pendingClientId.add(clientId);\n }\n });\n\n if (pendingClientId.size !== 0) {\n pendingClients.push([container, pendingClientId]);\n }\n });\n return pendingClients;\n }\n\n /**\n * Utility to check synchronization based on sequence number\n * See ensureSynchronized for more detail\n *\n * @param containersToApply - the set of containers to check\n */\n private isSequenceNumberSynchronized(containersToApply: IContainer[]) {\n // clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n // We need both client sequence number and isDirty check because:\n // - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n // - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n // the ops in the first place, clientSequenceNumber is not assigned\n\n const isClientSequenceNumberSynchronized = containersToApply.every((container) => {\n if (container.deltaManager.readOnlyInfo.readonly === true) {\n // Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n // because we transition to readonly when outbound is not empty or the in transit op got lost\n return true;\n }\n // Note that in read only mode, the op won't be submitted\n let deltaManager = (container.deltaManager as any);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { trailingNoOps } = this.containers.get(container)!;\n // Back-compat: clientSequenceNumber & clientSequenceNumberObserved moved to ConnectionManager in 0.53\n if (!(\"clientSequenceNumber\" in deltaManager)) {\n deltaManager = deltaManager.connectionManager;\n }\n assert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n assert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n return deltaManager.clientSequenceNumber ===\n (deltaManager.clientSequenceNumberObserved as number) + trailingNoOps;\n });\n\n if (!isClientSequenceNumberSynchronized) {\n return false;\n }\n\n const minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n if (minSeqNum < this.lastProposalSeqNum) {\n // There is an unresolved proposal\n return false;\n }\n\n // Check to see if all the container has process the same number of ops.\n const seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n return containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\n }\n\n /**\n * Utility to wait for any clientId in quorum that is NOT associated with any container we\n * tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * Note that this function doesn't account for container that got added after we started waiting\n *\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n const unconnectedClients =\n Array.from(this.containers.keys()).filter((c) => !c.closed && !(c as Container).connected);\n return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {\n return new Promise<void>((resolve) => {\n const cleanup = () => {\n unconnectedClients.forEach((c) => c.off(\"connected\", handler));\n container.getQuorum().off(\"removeMember\", handler);\n };\n const handler = (clientId: string) => {\n pendingClientId.delete(clientId);\n if (pendingClientId.size === 0) {\n cleanup();\n resolve();\n }\n };\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const index = this.containers.get(container)!.index;\n debugWait(`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`);\n unconnectedClients.forEach((c) => c.on(\"connected\", handler));\n container.getQuorum().on(\"removeMember\", handler);\n container.on(\"closed\", () => {\n cleanup();\n resolve();\n });\n });\n }));\n }\n\n /**\n * Utility to wait for any inbound ops from a set of containers\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForAnyInboundOps(containersToApply: IContainer[]) {\n return new Promise<void>((resolve) => {\n const handler = () => {\n containersToApply.map((c) => {\n c.deltaManager.inbound.off(\"push\", handler);\n });\n resolve();\n };\n containersToApply.map((c) => {\n c.deltaManager.inbound.on(\"push\", handler);\n });\n });\n }\n\n /**\n * Resume all queue activities on all paused tracked containers and return them\n */\n public resumeProcessing(...containers: IContainer[]) {\n const resumed: IContainer[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && record.paused) {\n debugWait(`${record.index}: container resumed`);\n container.deltaManager.inbound.resume();\n container.deltaManager.outbound.resume();\n resumed.push(container);\n record.paused = false;\n }\n }\n return resumed;\n }\n\n /**\n * Pause all queue activities on the containers given, or all tracked containers\n * Any containers given that is not tracked will be ignored.\n */\n public async pauseProcessing(...containers: IContainer[]) {\n const pauseP: Promise<void>[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && !record.paused) {\n debugWait(`${record.index}: container paused`);\n pauseP.push(container.deltaManager.inbound.pause());\n pauseP.push(container.deltaManager.outbound.pause());\n record.paused = true;\n }\n }\n await Promise.all(pauseP);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * inbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processIncoming(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.inbound);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * outbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processOutgoing(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.outbound);\n }\n\n /**\n * Implementation of processIncoming and processOutgoing\n */\n private async processQueue<U>(containers: IContainer[], getQueue: (container: IContainer) => IDeltaQueue<U>) {\n await this.pauseProcessing(...containers);\n const resumed: IDeltaQueue<U>[] = [];\n\n const containersToApply = this.getContainers(containers);\n const inflightTracker = new Map<IContainer, number>();\n const cleanup: (() => void)[] = [];\n for (const container of containersToApply) {\n const queue = getQueue(container);\n\n // track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n // to make sure they are sequenced.\n cleanup.push(this.setupInOutTracker(container, inflightTracker));\n queue.resume();\n resumed.push(queue);\n }\n\n while (resumed.some((queue) => !queue.idle)) {\n debugWait(\"Wait until queue is idle\");\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Make sure all the op that we sent out are acked first\n // This is no op if we are processing incoming\n if (inflightTracker.size) {\n debugWait(\"Wait for inflight ops\");\n do {\n await this.waitForAnyInboundOps(containersToApply);\n } while (inflightTracker.size);\n }\n\n // remove the handlers\n cleanup.forEach((clean) => clean());\n\n await Promise.all(resumed.map(async (queue) => queue.pause()));\n }\n\n /**\n * Utility to set up listener to track the outbound ops until it round trip back\n * Returns a function to remove the handler after it is done.\n *\n * @param container - the container to setup\n * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n */\n private setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n const outHandler = (messages: IDocumentMessage[]) => {\n for (const message of messages) {\n if (message.type !== MessageType.NoOp) {\n inflightTracker.set(container, message.clientSequenceNumber);\n }\n }\n };\n const inHandler = (message: ISequencedDocumentMessage) => {\n if (message.type !== MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && inflightTracker.get(container) === message.clientSequenceNumber) {\n inflightTracker.delete(container);\n }\n };\n\n container.deltaManager.outbound.on(\"op\", outHandler);\n container.deltaManager.inbound.on(\"push\", inHandler);\n\n return () => {\n container.deltaManager.outbound.off(\"op\", outHandler);\n container.deltaManager.inbound.off(\"push\", inHandler);\n };\n }\n\n /**\n * Setup debug traces for connection and ops\n */\n private setupTrace(container: IContainer, index: number) {\n if (debugOp.enabled) {\n const getContentsString = (type: string, msgContents: any) => {\n try {\n if (type !== MessageType.Operation) {\n if (typeof msgContents === \"string\") { return msgContents; }\n return JSON.stringify(msgContents);\n }\n let address = \"\";\n\n // contents comes in the wire as JSON string (\"push\" event)\n // But already parsed when apply (\"op\" event)\n let contents = typeof msgContents === \"string\" ?\n JSON.parse(msgContents) : msgContents;\n // eslint-disable-next-line no-null/no-null\n while (contents !== undefined && contents !== null) {\n if (contents.contents?.address !== undefined) {\n address += `/${contents.contents.address}`;\n contents = contents.contents.contents;\n } else if (contents.content?.address !== undefined) {\n address += `/${contents.content.address}`;\n contents = contents.content.contents;\n } else {\n break;\n }\n }\n if (address) {\n return `${address} ${JSON.stringify(contents)}`;\n }\n return JSON.stringify(contents);\n } catch (e) {\n return `${e.message}: ${e.stack}`;\n }\n };\n debugOp(`${index}: ADD: clientId: ${(container as Container).clientId}`);\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n debugOp(`${index}: OUT: `\n + `cli: ${msg.clientSequenceNumber.toString().padStart(3)} `\n + `rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n }\n });\n const getInboundHandler = (type: string) => {\n return (msg: ISequencedDocumentMessage) => {\n const clientSeq = msg.clientId === (container as Container).clientId ?\n `cli: ${msg.clientSequenceNumber.toString().padStart(3)}` : \" \";\n debugOp(`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} `\n + `${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n };\n };\n container.deltaManager.inbound.on(\"push\", getInboundHandler(\"IN \"));\n container.deltaManager.inbound.on(\"op\", getInboundHandler(\"OP \"));\n container.deltaManager.on(\"connect\", (details) => {\n debugOp(`${index}: CON: clientId: ${details.clientId}`);\n });\n container.deltaManager.on(\"disconnect\", (reason) => {\n debugOp(`${index}: DIS: ${reason}`);\n });\n }\n }\n\n /**\n * Filter out the opened containers based on param.\n * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n * all open containers.\n */\n private getContainers(containers: IContainer[]) {\n const containersToApply = containers.length === 0 ? Array.from(this.containers.keys()) : containers;\n return containersToApply.filter((container) => !container.closed);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.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 { assert } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { Container } from \"@fluidframework/container-loader\";\nimport { IDocumentMessage, ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n // A short number for debug output\n index: number;\n\n // LoaderContainerTracker paused state\n paused: boolean;\n\n // Tracking trailing no-op that may or may be acked by the server so we can discount them\n // See issue #5629\n startTrailingNoOps: number;\n trailingNoOps: number;\n\n // Track last proposal to ensure no unresolved proposal\n lastProposal: number;\n}\n\nexport class LoaderContainerTracker implements IOpProcessingController {\n private readonly containers = new Map<IContainer, ContainerRecord>();\n private lastProposalSeqNum: number = 0;\n\n /**\n * Add a loader to start to track any container created from them\n * @param loader - loader to start tracking any container created.\n */\n public add<LoaderType extends IHostLoader>(loader: LoaderType) {\n // TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n const patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n const boundFn = fn.bind(loader);\n return async (...args: T[]) => {\n const container = await boundFn(...args);\n this.addContainer(container);\n return container;\n };\n };\n loader.resolve = patch(loader.resolve);\n loader.createDetachedContainer = patch(loader.createDetachedContainer);\n loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);\n }\n\n /**\n * Utility function to add container to be tracked.\n *\n * @param container - container to add\n */\n private addContainer(container: IContainer) {\n // ignore summarizer\n if (!container.deltaManager.clientDetails.capabilities.interactive) { return; }\n\n // don't add container that is already tracked\n if (this.containers.has(container)) { return; }\n\n const record = {\n index: this.containers.size,\n paused: false,\n startTrailingNoOps: 0,\n trailingNoOps: 0,\n lastProposal: 0,\n };\n this.containers.set(container, record);\n this.trackTrailingNoOps(container, record);\n this.trackLastProposal(container);\n this.setupTrace(container, record.index);\n }\n\n /**\n * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n *\n * @param container - the container to track\n * @param record - the record to update the trailing op information\n */\n private trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n if (msg.type === MessageType.NoOp) {\n // Track the NoOp that was sent.\n if (record.trailingNoOps === 0) {\n // record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n record.startTrailingNoOps = msg.clientSequenceNumber;\n }\n record.trailingNoOps++;\n } else {\n // Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n record.trailingNoOps = 0;\n }\n }\n });\n\n container.deltaManager.inbound.on(\"push\", (message) => {\n // Received the no op back, update the record if we are tracking\n if (message.type === MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && record.trailingNoOps !== 0\n && record.startTrailingNoOps <= message.clientSequenceNumber\n ) {\n // NoOp might have coalesced and skipped ahead some sequence number\n // update the record and skip ahead as well\n const oldStartTrailingNoOps = record.startTrailingNoOps;\n record.startTrailingNoOps = message.clientSequenceNumber + 1;\n record.trailingNoOps -= (record.startTrailingNoOps - oldStartTrailingNoOps);\n }\n });\n\n container.on(\"disconnected\", () => {\n // reset on disconnect.\n record.trailingNoOps = 0;\n });\n }\n\n private trackLastProposal(container: IContainer) {\n container.on(\"codeDetailsProposed\", (value, proposal) => {\n if (proposal.sequenceNumber > this.lastProposalSeqNum) {\n this.lastProposalSeqNum = proposal.sequenceNumber;\n }\n });\n }\n\n /**\n * Reset the tracker, closing all containers and stop tracking them.\n */\n public reset() {\n this.lastProposalSeqNum = 0;\n for (const container of this.containers.keys()) {\n container.close();\n }\n this.containers.clear();\n\n // REVIEW: do we need to unpatch the loaders?\n }\n\n /**\n * Make sure all the tracked containers are synchronized.\n * - No isDirty (non-readonly) containers\n * - No extra clientId in quorum of any container that is not tracked and still opened.\n * - i.e. no pending Join/Leave message.\n * - No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n * - lastSequenceNumber of all container is the same\n * - clientSequenceNumberObserved is the same as clientSequenceNumber sent\n * - this overlaps with !isDirty, but include task scheduler ops.\n * - Trailing NoOp is tracked and don't count as pending ops.\n */\n public async ensureSynchronized(...containers: IContainer[]) {\n const resumed = this.resumeProcessing(...containers);\n\n let waitingSequenceNumberSynchronized = false;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const containersToApply = this.getContainers(containers);\n if (containersToApply.length === 0) { break; }\n\n // Ignore readonly dirty containers, because it can't sent up and nothing can be done about it being dirty\n const dirtyContainers =\n containersToApply.filter((c) => c.deltaManager.readOnlyInfo.readonly !== true && c.isDirty);\n if (dirtyContainers.length === 0) {\n // Wait for all the leave messages\n const pendingClients = this.getPendingClients(containersToApply);\n if (pendingClients.length === 0) {\n if (this.isSequenceNumberSynchronized(containersToApply)) {\n // done, we are in sync\n break;\n }\n if (!waitingSequenceNumberSynchronized) {\n // Only write it out once\n waitingSequenceNumberSynchronized = true;\n debugWait(\"Waiting for sequence number synchronized\");\n await this.waitForAnyInboundOps(containersToApply);\n }\n } else {\n waitingSequenceNumberSynchronized = false;\n await this.waitForPendingClients(pendingClients);\n }\n } else {\n // Wait for all the containers to be saved\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);\n waitingSequenceNumberSynchronized = false;\n await Promise.all(dirtyContainers.map(async (c) => new Promise((resolve) => c.once(\"saved\", resolve))));\n }\n\n // yield a turn to allow side effect of the ops we just processed execute before we check again\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Pause all container that was resumed\n // don't call pause if resumed is empty and pause everything, which is not what we want\n if (resumed.length !== 0) {\n await this.pauseProcessing(...resumed);\n }\n\n debugWait(\"Synchronized\");\n }\n\n /**\n * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * @param containersToApply - the set of containers to check\n */\n private getPendingClients(containersToApply: IContainer[]) {\n // All the clientId we track should be a superset of the quorum, otherwise, we are missing\n // leave messages\n const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n const openedClientId = openedDocuments.map((container) => (container as Container).clientId);\n\n const pendingClients: [IContainer, Set<string>][] = [];\n containersToApply.forEach((container) => {\n const pendingClientId = new Set<string>();\n const quorum = container.getQuorum();\n quorum.getMembers().forEach((client, clientId) => {\n // ignore summarizer\n if (!client.client.details.capabilities.interactive) { return; }\n if (!openedClientId.includes(clientId)) {\n pendingClientId.add(clientId);\n }\n });\n\n if (pendingClientId.size !== 0) {\n pendingClients.push([container, pendingClientId]);\n }\n });\n return pendingClients;\n }\n\n /**\n * Utility to check synchronization based on sequence number\n * See ensureSynchronized for more detail\n *\n * @param containersToApply - the set of containers to check\n */\n private isSequenceNumberSynchronized(containersToApply: IContainer[]) {\n // clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n // We need both client sequence number and isDirty check because:\n // - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n // - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n // the ops in the first place, clientSequenceNumber is not assigned\n\n const isClientSequenceNumberSynchronized = containersToApply.every((container) => {\n if (container.deltaManager.readOnlyInfo.readonly === true) {\n // Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n // because we transition to readonly when outbound is not empty or the in transit op got lost\n return true;\n }\n // Note that in read only mode, the op won't be submitted\n let deltaManager = (container.deltaManager as any);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { trailingNoOps } = this.containers.get(container)!;\n // Back-compat: clientSequenceNumber & clientSequenceNumberObserved moved to ConnectionManager in 0.53\n if (!(\"clientSequenceNumber\" in deltaManager)) {\n deltaManager = deltaManager.connectionManager;\n }\n assert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n assert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n return deltaManager.clientSequenceNumber ===\n (deltaManager.clientSequenceNumberObserved as number) + trailingNoOps;\n });\n\n if (!isClientSequenceNumberSynchronized) {\n return false;\n }\n\n const minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n if (minSeqNum < this.lastProposalSeqNum) {\n // There is an unresolved proposal\n return false;\n }\n\n // Check to see if all the container has process the same number of ops.\n const seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n return containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\n }\n\n /**\n * Utility to wait for any clientId in quorum that is NOT associated with any container we\n * tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * Note that this function doesn't account for container that got added after we started waiting\n *\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n const unconnectedClients =\n Array.from(this.containers.keys()).filter((c) => !c.closed && !(c as Container).connected);\n return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {\n return new Promise<void>((resolve) => {\n const cleanup = () => {\n unconnectedClients.forEach((c) => c.off(\"connected\", handler));\n container.getQuorum().off(\"removeMember\", handler);\n };\n const handler = (clientId: string) => {\n pendingClientId.delete(clientId);\n if (pendingClientId.size === 0) {\n cleanup();\n resolve();\n }\n };\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const index = this.containers.get(container)!.index;\n debugWait(`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`);\n unconnectedClients.forEach((c) => c.on(\"connected\", handler));\n container.getQuorum().on(\"removeMember\", handler);\n container.on(\"closed\", () => {\n cleanup();\n resolve();\n });\n });\n }));\n }\n\n /**\n * Utility to wait for any inbound ops from a set of containers\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForAnyInboundOps(containersToApply: IContainer[]) {\n return new Promise<void>((resolve) => {\n const handler = () => {\n containersToApply.map((c) => {\n c.deltaManager.inbound.off(\"push\", handler);\n });\n resolve();\n };\n containersToApply.map((c) => {\n c.deltaManager.inbound.on(\"push\", handler);\n });\n });\n }\n\n /**\n * Resume all queue activities on all paused tracked containers and return them\n */\n public resumeProcessing(...containers: IContainer[]) {\n const resumed: IContainer[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && record.paused) {\n debugWait(`${record.index}: container resumed`);\n container.deltaManager.inbound.resume();\n container.deltaManager.outbound.resume();\n resumed.push(container);\n record.paused = false;\n }\n }\n return resumed;\n }\n\n /**\n * Pause all queue activities on the containers given, or all tracked containers\n * Any containers given that is not tracked will be ignored.\n */\n public async pauseProcessing(...containers: IContainer[]) {\n const pauseP: Promise<void>[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && !record.paused) {\n debugWait(`${record.index}: container paused`);\n pauseP.push(container.deltaManager.inbound.pause());\n pauseP.push(container.deltaManager.outbound.pause());\n record.paused = true;\n }\n }\n await Promise.all(pauseP);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * inbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processIncoming(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.inbound);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * outbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processOutgoing(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.outbound);\n }\n\n /**\n * Implementation of processIncoming and processOutgoing\n */\n private async processQueue<U>(containers: IContainer[], getQueue: (container: IContainer) => IDeltaQueue<U>) {\n await this.pauseProcessing(...containers);\n const resumed: IDeltaQueue<U>[] = [];\n\n const containersToApply = this.getContainers(containers);\n const inflightTracker = new Map<IContainer, number>();\n const cleanup: (() => void)[] = [];\n for (const container of containersToApply) {\n const queue = getQueue(container);\n\n // track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n // to make sure they are sequenced.\n cleanup.push(this.setupInOutTracker(container, inflightTracker));\n queue.resume();\n resumed.push(queue);\n }\n\n while (resumed.some((queue) => !queue.idle)) {\n debugWait(\"Wait until queue is idle\");\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Make sure all the op that we sent out are acked first\n // This is no op if we are processing incoming\n if (inflightTracker.size) {\n debugWait(\"Wait for inflight ops\");\n do {\n await this.waitForAnyInboundOps(containersToApply);\n } while (inflightTracker.size);\n }\n\n // remove the handlers\n cleanup.forEach((clean) => clean());\n\n await Promise.all(resumed.map(async (queue) => queue.pause()));\n }\n\n /**\n * Utility to set up listener to track the outbound ops until it round trip back\n * Returns a function to remove the handler after it is done.\n *\n * @param container - the container to setup\n * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n */\n private setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n const outHandler = (messages: IDocumentMessage[]) => {\n for (const message of messages) {\n if (message.type !== MessageType.NoOp) {\n inflightTracker.set(container, message.clientSequenceNumber);\n }\n }\n };\n const inHandler = (message: ISequencedDocumentMessage) => {\n if (message.type !== MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && inflightTracker.get(container) === message.clientSequenceNumber) {\n inflightTracker.delete(container);\n }\n };\n\n container.deltaManager.outbound.on(\"op\", outHandler);\n container.deltaManager.inbound.on(\"push\", inHandler);\n\n return () => {\n container.deltaManager.outbound.off(\"op\", outHandler);\n container.deltaManager.inbound.off(\"push\", inHandler);\n };\n }\n\n /**\n * Setup debug traces for connection and ops\n */\n private setupTrace(container: IContainer, index: number) {\n if (debugOp.enabled) {\n const getContentsString = (type: string, msgContents: any) => {\n try {\n if (type !== MessageType.Operation) {\n if (typeof msgContents === \"string\") { return msgContents; }\n return JSON.stringify(msgContents);\n }\n let address = \"\";\n\n // contents comes in the wire as JSON string (\"push\" event)\n // But already parsed when apply (\"op\" event)\n let contents = typeof msgContents === \"string\" ?\n JSON.parse(msgContents) : msgContents;\n // eslint-disable-next-line no-null/no-null\n while (contents !== undefined && contents !== null) {\n if (contents.contents?.address !== undefined) {\n address += `/${contents.contents.address}`;\n contents = contents.contents.contents;\n } else if (contents.content?.address !== undefined) {\n address += `/${contents.content.address}`;\n contents = contents.content.contents;\n } else {\n break;\n }\n }\n if (address) {\n return `${address} ${JSON.stringify(contents)}`;\n }\n return JSON.stringify(contents);\n } catch (e) {\n return `${e.message}: ${e.stack}`;\n }\n };\n debugOp(`${index}: ADD: clientId: ${(container as Container).clientId}`);\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n debugOp(`${index}: OUT: `\n + `cli: ${msg.clientSequenceNumber.toString().padStart(3)} `\n + `rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n }\n });\n const getInboundHandler = (type: string) => {\n return (msg: ISequencedDocumentMessage) => {\n const clientSeq = msg.clientId === (container as Container).clientId ?\n `cli: ${msg.clientSequenceNumber.toString().padStart(3)}` : \" \";\n debugOp(`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} `\n + `${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n };\n };\n container.deltaManager.inbound.on(\"push\", getInboundHandler(\"IN \"));\n container.deltaManager.inbound.on(\"op\", getInboundHandler(\"OP \"));\n container.deltaManager.on(\"connect\", (details) => {\n debugOp(`${index}: CON: clientId: ${details.clientId}`);\n });\n container.deltaManager.on(\"disconnect\", (reason) => {\n debugOp(`${index}: DIS: ${reason}`);\n });\n }\n }\n\n /**\n * Filter out the opened containers based on param.\n * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n * all open containers.\n */\n private getContainers(containers: IContainer[]) {\n const containersToApply = containers.length === 0 ? Array.from(this.containers.keys()) : containers;\n return containersToApply.filter((container) => !container.closed);\n }\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -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 = "0.
|
|
8
|
+
export declare const pkgVersion = "0.56.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,WAAW,CAAC"}
|
package/dist/packageVersion.js
CHANGED
|
@@ -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 = "0.
|
|
11
|
+
exports.pkgVersion = "0.56.0";
|
|
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,
|
|
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,QAAQ,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 = \"0.56.0\";\n"]}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { IContainer, IHostLoader
|
|
5
|
+
import { IContainer, IHostLoader } from "@fluidframework/container-definitions";
|
|
6
6
|
import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
|
|
7
|
-
import {
|
|
7
|
+
import { ILoaderProps, Loader } from "@fluidframework/container-loader";
|
|
8
8
|
import { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
|
|
9
9
|
import { IFluidCodeDetails, IRequestHeader } from "@fluidframework/core-interfaces";
|
|
10
10
|
import { IDocumentServiceFactory, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
|
|
@@ -19,14 +19,14 @@ export interface IOpProcessingController {
|
|
|
19
19
|
}
|
|
20
20
|
export interface ITestObjectProvider {
|
|
21
21
|
createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;
|
|
22
|
-
createLoader(packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
23
|
-
createContainer(entryPoint: fluidEntryPoint,
|
|
24
|
-
loadContainer(entryPoint: fluidEntryPoint,
|
|
22
|
+
createLoader(packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>, loaderProps?: Partial<ILoaderProps>): IHostLoader;
|
|
23
|
+
createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>): Promise<IContainer>;
|
|
24
|
+
loadContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>, requestHeader?: IRequestHeader): Promise<IContainer>;
|
|
25
25
|
/**
|
|
26
26
|
* Used to create a test Container. The Loader/ContainerRuntime/DataRuntime might be different versioned.
|
|
27
27
|
* In generateLocalCompatTest(), this Container and its runtime will be arbitrarily-versioned.
|
|
28
28
|
*/
|
|
29
|
-
makeTestLoader(testContainerConfig?: ITestContainerConfig
|
|
29
|
+
makeTestLoader(testContainerConfig?: ITestContainerConfig): IHostLoader;
|
|
30
30
|
makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>;
|
|
31
31
|
loadTestContainer(testContainerConfig?: ITestContainerConfig, requestHeader?: IRequestHeader): Promise<IContainer>;
|
|
32
32
|
/**
|
|
@@ -56,16 +56,13 @@ export interface ITestContainerConfig {
|
|
|
56
56
|
/** Container runtime options for the container instance */
|
|
57
57
|
runtimeOptions?: IContainerRuntimeOptions;
|
|
58
58
|
/** Loader options for the loader used to create containers */
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
export interface ITestLoaderOptions extends ILoaderOptions {
|
|
62
|
-
logger?: ITelemetryBaseLogger;
|
|
59
|
+
loaderProps?: Partial<ILoaderProps>;
|
|
63
60
|
}
|
|
64
61
|
export declare const createDocumentId: () => string;
|
|
65
62
|
/**
|
|
66
63
|
* Shared base class for test object provider. Contain code for loader and container creation and loading
|
|
67
64
|
*/
|
|
68
|
-
export declare class TestObjectProvider {
|
|
65
|
+
export declare class TestObjectProvider implements ITestObjectProvider {
|
|
69
66
|
readonly LoaderConstructor: typeof Loader;
|
|
70
67
|
readonly driver: ITestDriver;
|
|
71
68
|
readonly createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;
|
|
@@ -95,7 +92,7 @@ export declare class TestObjectProvider {
|
|
|
95
92
|
*
|
|
96
93
|
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
97
94
|
*/
|
|
98
|
-
createLoader(packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
95
|
+
createLoader(packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>, loaderProps?: Partial<ILoaderProps>): Loader;
|
|
99
96
|
/**
|
|
100
97
|
* Create a container using a default document id and code details.
|
|
101
98
|
* Container created is automatically added to the OpProcessingController to manage op flow
|
|
@@ -105,14 +102,14 @@ export declare class TestObjectProvider {
|
|
|
105
102
|
*
|
|
106
103
|
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
107
104
|
*/
|
|
108
|
-
createContainer(entryPoint: fluidEntryPoint,
|
|
109
|
-
loadContainer(entryPoint: fluidEntryPoint,
|
|
105
|
+
createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>): Promise<IContainer>;
|
|
106
|
+
loadContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>, requestHeader?: IRequestHeader): Promise<IContainer>;
|
|
110
107
|
/**
|
|
111
108
|
* Make a test loader. Containers created/loaded through this loader will be added to the OpProcessingController.
|
|
112
109
|
* The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run
|
|
113
110
|
* @param testContainerConfig - optional configuring the test Container
|
|
114
111
|
*/
|
|
115
|
-
makeTestLoader(testContainerConfig?: ITestContainerConfig
|
|
112
|
+
makeTestLoader(testContainerConfig?: ITestContainerConfig): Loader;
|
|
116
113
|
/**
|
|
117
114
|
* Make a container using a default document id and code details
|
|
118
115
|
* Container loaded is automatically added to the OpProcessingController to manage op flow
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testObjectProvider.d.ts","sourceRoot":"","sources":["../src/testObjectProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"testObjectProvider.d.ts","sourceRoot":"","sources":["../src/testObjectProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -109,21 +109,14 @@ class TestObjectProvider {
|
|
|
109
109
|
*
|
|
110
110
|
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
111
111
|
*/
|
|
112
|
-
createLoader(packageEntries,
|
|
112
|
+
createLoader(packageEntries, loaderProps) {
|
|
113
|
+
var _a, _b, _c;
|
|
113
114
|
const multiSinkLogger = new telemetry_utils_1.MultiSinkLogger();
|
|
114
115
|
multiSinkLogger.addLogger(this.logger);
|
|
115
|
-
if ((
|
|
116
|
-
multiSinkLogger.addLogger(
|
|
116
|
+
if ((loaderProps === null || loaderProps === void 0 ? void 0 : loaderProps.logger) !== undefined) {
|
|
117
|
+
multiSinkLogger.addLogger(loaderProps.logger);
|
|
117
118
|
}
|
|
118
|
-
const codeLoader = new localCodeLoader_1.LocalCodeLoader(packageEntries);
|
|
119
|
-
const loader = new this.LoaderConstructor({
|
|
120
|
-
urlResolver: this.urlResolver,
|
|
121
|
-
documentServiceFactory: this.documentServiceFactory,
|
|
122
|
-
codeLoader,
|
|
123
|
-
logger: multiSinkLogger,
|
|
124
|
-
options,
|
|
125
|
-
detachedBlobStorage,
|
|
126
|
-
});
|
|
119
|
+
const loader = new this.LoaderConstructor(Object.assign(Object.assign({}, loaderProps), { logger: multiSinkLogger, codeLoader: (_a = loaderProps === null || loaderProps === void 0 ? void 0 : loaderProps.codeLoader) !== null && _a !== void 0 ? _a : new localCodeLoader_1.LocalCodeLoader(packageEntries), urlResolver: (_b = loaderProps === null || loaderProps === void 0 ? void 0 : loaderProps.urlResolver) !== null && _b !== void 0 ? _b : this.urlResolver, documentServiceFactory: (_c = loaderProps === null || loaderProps === void 0 ? void 0 : loaderProps.documentServiceFactory) !== null && _c !== void 0 ? _c : this.documentServiceFactory }));
|
|
127
120
|
this._loaderContainerTracker.add(loader);
|
|
128
121
|
return loader;
|
|
129
122
|
}
|
|
@@ -136,11 +129,11 @@ class TestObjectProvider {
|
|
|
136
129
|
*
|
|
137
130
|
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
138
131
|
*/
|
|
139
|
-
async createContainer(entryPoint,
|
|
132
|
+
async createContainer(entryPoint, loaderProps) {
|
|
140
133
|
if (this._documentCreated) {
|
|
141
134
|
throw new Error("Only one container/document can be created. To load the container/document use loadContainer");
|
|
142
135
|
}
|
|
143
|
-
const loader = this.createLoader([[defaultCodeDetails, entryPoint]],
|
|
136
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
144
137
|
const container = await localLoader_1.createAndAttachContainer(defaultCodeDetails, loader, this.driver.createCreateNewRequest(this.documentId));
|
|
145
138
|
this._documentCreated = true;
|
|
146
139
|
// r11s driver will generate a new ID for the new container.
|
|
@@ -148,8 +141,8 @@ class TestObjectProvider {
|
|
|
148
141
|
this._documentIdStrategy.update(container.resolvedUrl);
|
|
149
142
|
return container;
|
|
150
143
|
}
|
|
151
|
-
async loadContainer(entryPoint,
|
|
152
|
-
const loader = this.createLoader([[defaultCodeDetails, entryPoint]],
|
|
144
|
+
async loadContainer(entryPoint, loaderProps, requestHeader) {
|
|
145
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
153
146
|
return loader.resolve({ url: await this.driver.createContainerUrl(this.documentId), headers: requestHeader });
|
|
154
147
|
}
|
|
155
148
|
/**
|
|
@@ -157,8 +150,8 @@ class TestObjectProvider {
|
|
|
157
150
|
* The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run
|
|
158
151
|
* @param testContainerConfig - optional configuring the test Container
|
|
159
152
|
*/
|
|
160
|
-
makeTestLoader(testContainerConfig
|
|
161
|
-
return this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig === null || testContainerConfig === void 0 ? void 0 : testContainerConfig.
|
|
153
|
+
makeTestLoader(testContainerConfig) {
|
|
154
|
+
return this.createLoader([[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]], testContainerConfig === null || testContainerConfig === void 0 ? void 0 : testContainerConfig.loaderProps);
|
|
162
155
|
}
|
|
163
156
|
/**
|
|
164
157
|
* Make a container using a default document id and code details
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testObjectProvider.js","sourceRoot":"","sources":["../src/testObjectProvider.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 { IContainer, IHostLoader, ILoaderOptions } from \"@fluidframework/container-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport { IDetachedBlobStorage, Loader, waitContainerToCatchUp } from \"@fluidframework/container-loader\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { IFluidCodeDetails, IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport { IDocumentServiceFactory, IResolvedUrl, IUrlResolver } from \"@fluidframework/driver-definitions\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport { ITestDriver, TestDriverTypes } from \"@fluidframework/test-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { ChildLogger, MultiSinkLogger } from \"@fluidframework/telemetry-utils\";\nimport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nimport { fluidEntryPoint, LocalCodeLoader } from \"./localCodeLoader\";\nimport { createAndAttachContainer } from \"./localLoader\";\nimport { ChannelFactoryRegistry } from \"./testFluidObject\";\n\nconst defaultCodeDetails: IFluidCodeDetails = {\n package: \"defaultTestPackage\",\n config: {},\n};\n\nexport interface IOpProcessingController {\n processIncoming(...containers: IContainer[]): Promise<void>;\n processOutgoing(...containers: IContainer[]): Promise<void>;\n pauseProcessing(...containers: IContainer[]): Promise<void>;\n resumeProcessing(...containers: IContainer[]): void;\n}\n\nexport interface ITestObjectProvider {\n createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;\n createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n options?: ITestLoaderOptions,\n detachedBlobStorage?: IDetachedBlobStorage,\n ): IHostLoader;\n createContainer(entryPoint: fluidEntryPoint, options?: ITestLoaderOptions): Promise<IContainer>;\n loadContainer(\n entryPoint: fluidEntryPoint,\n options?: ITestLoaderOptions,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer>;\n\n /**\n * Used to create a test Container. The Loader/ContainerRuntime/DataRuntime might be different versioned.\n * In generateLocalCompatTest(), this Container and its runtime will be arbitrarily-versioned.\n */\n makeTestLoader(testContainerConfig?: ITestContainerConfig, detachedBlobStorage?: IDetachedBlobStorage): IHostLoader,\n makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>,\n loadTestContainer(testContainerConfig?: ITestContainerConfig, requestHeader?: IRequestHeader): Promise<IContainer>,\n /**\n *\n * @param url - Resolved container URL\n */\n updateDocumentId(url: IResolvedUrl | undefined): void,\n\n logger: ITelemetryBaseLogger,\n documentServiceFactory: IDocumentServiceFactory,\n urlResolver: IUrlResolver,\n defaultCodeDetails: IFluidCodeDetails,\n opProcessingController: IOpProcessingController,\n\n ensureSynchronized(): Promise<void>;\n reset(): void,\n\n documentId: string,\n driver: ITestDriver;\n}\n\nexport enum DataObjectFactoryType {\n Primed, // default\n Test,\n}\n\nexport interface ITestContainerConfig {\n /** TestFluidDataObject instead of PrimedDataStore */\n fluidDataObjectType?: DataObjectFactoryType,\n\n /** An array of channel name and DDS factory pair to create on container creation time */\n registry?: ChannelFactoryRegistry,\n\n /** Container runtime options for the container instance */\n runtimeOptions?: IContainerRuntimeOptions,\n\n /** Loader options for the loader used to create containers */\n loaderOptions?: ITestLoaderOptions,\n}\n\n// new interface to help inject custom loggers to tests\nexport interface ITestLoaderOptions extends ILoaderOptions {\n logger?: ITelemetryBaseLogger;\n}\n\nexport const createDocumentId = (): string => uuid();\n\ninterface IDocumentIdStrategy {\n get(): string;\n update(resolvedUrl?: IResolvedUrl): void;\n reset(): void;\n}\n\n/**\n * Document ID is treated differently by test drivers. The key difference is in generating\n * a new container ID and accessing the container in multi-instance test cases.\n */\nfunction getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {\n let documentId = createDocumentId();\n switch (type) {\n case \"odsp\":\n return {\n get: () => documentId,\n update: () => { }, // do not update the document ID in odsp test cases\n reset: () => documentId = createDocumentId(),\n };\n default:\n return {\n get: () => documentId,\n update: (resolvedUrl?: IResolvedUrl) => {\n // Extract the document ID from the resolved container's URL and reset the ID property\n ensureFluidResolvedUrl(resolvedUrl);\n documentId = resolvedUrl.id ?? documentId;\n },\n reset: () => documentId = createDocumentId(),\n };\n }\n}\n\n/**\n * Shared base class for test object provider. Contain code for loader and container creation and loading\n */\nexport class TestObjectProvider {\n private readonly _loaderContainerTracker = new LoaderContainerTracker();\n private _documentServiceFactory: IDocumentServiceFactory | undefined;\n private _urlResolver: IUrlResolver | undefined;\n private _logger: ITelemetryBaseLogger | undefined;\n private readonly _documentIdStrategy: IDocumentIdStrategy;\n // Since documentId doesn't change we can only create/make one container. Call the load functions instead.\n private _documentCreated = false;\n\n /**\n * Manage objects for loading and creating container, including the driver, loader, and OpProcessingController\n * @param createFluidEntryPoint - callback to create a fluidEntryPoint, with an optional set of channel name\n * and factory for TestFluidObject\n */\n constructor(\n public readonly LoaderConstructor: typeof Loader,\n public readonly driver: ITestDriver,\n public readonly createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint,\n ) {\n this._documentIdStrategy = getDocumentIdStrategy(driver.type);\n }\n\n get logger() {\n if (this._logger === undefined) {\n this._logger = ChildLogger.create(getTestLogger?.(), undefined,\n {\n all: {\n driverType: this.driver.type,\n driverEndpointName: this.driver.endpointName,\n driverTenantName: this.driver.tenantName,\n driverUserIndex: this.driver.userIndex,\n },\n });\n }\n return this._logger;\n }\n\n get documentServiceFactory() {\n if (!this._documentServiceFactory) {\n this._documentServiceFactory = this.driver.createDocumentServiceFactory();\n }\n return this._documentServiceFactory;\n }\n\n get urlResolver() {\n if (!this._urlResolver) {\n this._urlResolver = this.driver.createUrlResolver();\n }\n return this._urlResolver;\n }\n\n get documentId() {\n return this._documentIdStrategy.get();\n }\n\n get defaultCodeDetails() {\n return defaultCodeDetails;\n }\n\n get opProcessingController(): IOpProcessingController {\n return this._loaderContainerTracker;\n }\n\n /**\n * Create a loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n options?: ITestLoaderOptions,\n detachedBlobStorage?: IDetachedBlobStorage,\n ) {\n const multiSinkLogger = new MultiSinkLogger();\n multiSinkLogger.addLogger(this.logger);\n if (options?.logger !== undefined) {\n multiSinkLogger.addLogger(options.logger);\n }\n\n const codeLoader = new LocalCodeLoader(packageEntries);\n const loader = new this.LoaderConstructor({\n urlResolver: this.urlResolver,\n documentServiceFactory: this.documentServiceFactory,\n codeLoader,\n logger: multiSinkLogger,\n options,\n detachedBlobStorage,\n });\n this._loaderContainerTracker.add(loader);\n return loader;\n }\n\n /**\n * Create a container using a default document id and code details.\n * Container created is automatically added to the OpProcessingController to manage op flow\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public async createContainer(entryPoint: fluidEntryPoint, options?: ITestLoaderOptions) {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadContainer\");\n }\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], options);\n const container = await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId),\n );\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n public async loadContainer(entryPoint: fluidEntryPoint, options?: ITestLoaderOptions,\n requestHeader?: IRequestHeader): Promise<IContainer> {\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], options);\n return loader.resolve({ url: await this.driver.createContainerUrl(this.documentId), headers: requestHeader });\n }\n\n /**\n * Make a test loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n * The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run\n * @param testContainerConfig - optional configuring the test Container\n */\n public makeTestLoader(testContainerConfig?: ITestContainerConfig, detachedBlobStorage?: IDetachedBlobStorage) {\n return this.createLoader(\n [[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n testContainerConfig?.loaderOptions,\n detachedBlobStorage,\n );\n }\n\n /**\n * Make a container using a default document id and code details\n * Container loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n */\n public async makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer> {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadTestContainer\");\n }\n const loader = this.makeTestLoader(testContainerConfig);\n const container =\n await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId));\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n /**\n * Load a container using a default document id and code details.\n * IContainer loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n * @param requestHeader - optional headers to be supplied to the loader\n */\n public async loadTestContainer(\n testContainerConfig?: ITestContainerConfig,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer> {\n const loader = this.makeTestLoader(testContainerConfig);\n const container = await loader.resolve({\n url: await this.driver.createContainerUrl(this.documentId),\n headers: requestHeader,\n });\n await waitContainerToCatchUp(container);\n return container;\n }\n\n public reset() {\n this._loaderContainerTracker.reset();\n this._documentServiceFactory = undefined;\n this._urlResolver = undefined;\n this._documentIdStrategy.reset();\n this._logger = undefined;\n this._documentCreated = false;\n }\n\n public async ensureSynchronized() {\n return this._loaderContainerTracker.ensureSynchronized();\n }\n\n updateDocumentId(resolvedUrl: IResolvedUrl | undefined) {\n this._documentIdStrategy.update(resolvedUrl);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"testObjectProvider.js","sourceRoot":"","sources":["../src/testObjectProvider.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 { IContainer, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/common-definitions\";\nimport { ILoaderProps, Loader, waitContainerToCatchUp } from \"@fluidframework/container-loader\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { IFluidCodeDetails, IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport { IDocumentServiceFactory, IResolvedUrl, IUrlResolver } from \"@fluidframework/driver-definitions\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport { ITestDriver, TestDriverTypes } from \"@fluidframework/test-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { ChildLogger, MultiSinkLogger } from \"@fluidframework/telemetry-utils\";\nimport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nimport { fluidEntryPoint, LocalCodeLoader } from \"./localCodeLoader\";\nimport { createAndAttachContainer } from \"./localLoader\";\nimport { ChannelFactoryRegistry } from \"./testFluidObject\";\n\nconst defaultCodeDetails: IFluidCodeDetails = {\n package: \"defaultTestPackage\",\n config: {},\n};\n\nexport interface IOpProcessingController {\n processIncoming(...containers: IContainer[]): Promise<void>;\n processOutgoing(...containers: IContainer[]): Promise<void>;\n pauseProcessing(...containers: IContainer[]): Promise<void>;\n resumeProcessing(...containers: IContainer[]): void;\n}\n\nexport interface ITestObjectProvider {\n createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;\n createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n loaderProps?: Partial<ILoaderProps>,\n ): IHostLoader;\n createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>): Promise<IContainer>;\n loadContainer(\n entryPoint: fluidEntryPoint,\n loaderProps?: Partial<ILoaderProps>,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer>;\n\n /**\n * Used to create a test Container. The Loader/ContainerRuntime/DataRuntime might be different versioned.\n * In generateLocalCompatTest(), this Container and its runtime will be arbitrarily-versioned.\n */\n makeTestLoader(testContainerConfig?: ITestContainerConfig): IHostLoader,\n makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>,\n loadTestContainer(testContainerConfig?: ITestContainerConfig, requestHeader?: IRequestHeader): Promise<IContainer>,\n /**\n *\n * @param url - Resolved container URL\n */\n updateDocumentId(url: IResolvedUrl | undefined): void,\n\n logger: ITelemetryBaseLogger,\n documentServiceFactory: IDocumentServiceFactory,\n urlResolver: IUrlResolver,\n defaultCodeDetails: IFluidCodeDetails,\n opProcessingController: IOpProcessingController,\n\n ensureSynchronized(): Promise<void>;\n reset(): void,\n\n documentId: string,\n driver: ITestDriver;\n}\n\nexport enum DataObjectFactoryType {\n Primed, // default\n Test,\n}\n\nexport interface ITestContainerConfig {\n /** TestFluidDataObject instead of PrimedDataStore */\n fluidDataObjectType?: DataObjectFactoryType,\n\n /** An array of channel name and DDS factory pair to create on container creation time */\n registry?: ChannelFactoryRegistry,\n\n /** Container runtime options for the container instance */\n runtimeOptions?: IContainerRuntimeOptions,\n\n /** Loader options for the loader used to create containers */\n loaderProps?: Partial<ILoaderProps>,\n}\n\nexport const createDocumentId = (): string => uuid();\n\ninterface IDocumentIdStrategy {\n get(): string;\n update(resolvedUrl?: IResolvedUrl): void;\n reset(): void;\n}\n\n/**\n * Document ID is treated differently by test drivers. The key difference is in generating\n * a new container ID and accessing the container in multi-instance test cases.\n */\nfunction getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {\n let documentId = createDocumentId();\n switch (type) {\n case \"odsp\":\n return {\n get: () => documentId,\n update: () => { }, // do not update the document ID in odsp test cases\n reset: () => documentId = createDocumentId(),\n };\n default:\n return {\n get: () => documentId,\n update: (resolvedUrl?: IResolvedUrl) => {\n // Extract the document ID from the resolved container's URL and reset the ID property\n ensureFluidResolvedUrl(resolvedUrl);\n documentId = resolvedUrl.id ?? documentId;\n },\n reset: () => documentId = createDocumentId(),\n };\n }\n}\n\n/**\n * Shared base class for test object provider. Contain code for loader and container creation and loading\n */\nexport class TestObjectProvider implements ITestObjectProvider {\n private readonly _loaderContainerTracker = new LoaderContainerTracker();\n private _documentServiceFactory: IDocumentServiceFactory | undefined;\n private _urlResolver: IUrlResolver | undefined;\n private _logger: ITelemetryBaseLogger | undefined;\n private readonly _documentIdStrategy: IDocumentIdStrategy;\n // Since documentId doesn't change we can only create/make one container. Call the load functions instead.\n private _documentCreated = false;\n\n /**\n * Manage objects for loading and creating container, including the driver, loader, and OpProcessingController\n * @param createFluidEntryPoint - callback to create a fluidEntryPoint, with an optional set of channel name\n * and factory for TestFluidObject\n */\n constructor(\n public readonly LoaderConstructor: typeof Loader,\n public readonly driver: ITestDriver,\n public readonly createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint,\n ) {\n this._documentIdStrategy = getDocumentIdStrategy(driver.type);\n }\n\n get logger() {\n if (this._logger === undefined) {\n this._logger = ChildLogger.create(getTestLogger?.(), undefined,\n {\n all: {\n driverType: this.driver.type,\n driverEndpointName: this.driver.endpointName,\n driverTenantName: this.driver.tenantName,\n driverUserIndex: this.driver.userIndex,\n },\n });\n }\n return this._logger;\n }\n\n get documentServiceFactory() {\n if (!this._documentServiceFactory) {\n this._documentServiceFactory = this.driver.createDocumentServiceFactory();\n }\n return this._documentServiceFactory;\n }\n\n get urlResolver() {\n if (!this._urlResolver) {\n this._urlResolver = this.driver.createUrlResolver();\n }\n return this._urlResolver;\n }\n\n get documentId() {\n return this._documentIdStrategy.get();\n }\n\n get defaultCodeDetails() {\n return defaultCodeDetails;\n }\n\n get opProcessingController(): IOpProcessingController {\n return this._loaderContainerTracker;\n }\n\n /**\n * Create a loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n loaderProps?: Partial<ILoaderProps>,\n ) {\n const multiSinkLogger = new MultiSinkLogger();\n multiSinkLogger.addLogger(this.logger);\n if (loaderProps?.logger !== undefined) {\n multiSinkLogger.addLogger(loaderProps.logger);\n }\n\n const loader = new this.LoaderConstructor({\n ... loaderProps,\n logger: multiSinkLogger,\n codeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),\n urlResolver: loaderProps?.urlResolver ?? this.urlResolver,\n documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,\n });\n this._loaderContainerTracker.add(loader);\n return loader;\n }\n\n /**\n * Create a container using a default document id and code details.\n * Container created is automatically added to the OpProcessingController to manage op flow\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public async createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>) {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadContainer\");\n }\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n const container = await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId),\n );\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n public async loadContainer(\n entryPoint: fluidEntryPoint,\n loaderProps?: Partial<ILoaderProps>,\n requestHeader?: IRequestHeader): Promise<IContainer> {\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n return loader.resolve({ url: await this.driver.createContainerUrl(this.documentId), headers: requestHeader });\n }\n\n /**\n * Make a test loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n * The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run\n * @param testContainerConfig - optional configuring the test Container\n */\n public makeTestLoader(testContainerConfig?: ITestContainerConfig) {\n return this.createLoader(\n [[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n testContainerConfig?.loaderProps,\n );\n }\n\n /**\n * Make a container using a default document id and code details\n * Container loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n */\n public async makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer> {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadTestContainer\");\n }\n const loader = this.makeTestLoader(testContainerConfig);\n const container =\n await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId));\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n /**\n * Load a container using a default document id and code details.\n * IContainer loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n * @param requestHeader - optional headers to be supplied to the loader\n */\n public async loadTestContainer(\n testContainerConfig?: ITestContainerConfig,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer> {\n const loader = this.makeTestLoader(testContainerConfig);\n const container = await loader.resolve({\n url: await this.driver.createContainerUrl(this.documentId),\n headers: requestHeader,\n });\n await waitContainerToCatchUp(container);\n return container;\n }\n\n public reset() {\n this._loaderContainerTracker.reset();\n this._documentServiceFactory = undefined;\n this._urlResolver = undefined;\n this._documentIdStrategy.reset();\n this._logger = undefined;\n this._documentCreated = false;\n }\n\n public async ensureSynchronized() {\n return this._loaderContainerTracker.ensureSynchronized();\n }\n\n updateDocumentId(resolvedUrl: IResolvedUrl | undefined) {\n this._documentIdStrategy.update(resolvedUrl);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACZ;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EACvC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG9D;AAED,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,EAChG,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GAC5D,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACZ;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EACvC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG9D;AAED,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,EAChG,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GAC5D,OAAO,CAAC,CAAC,CAAC,CA0BZ"}
|
package/dist/timeoutUtils.js
CHANGED
|
@@ -12,19 +12,22 @@ async function timeoutAwait(promise, timeoutOptions = {}) {
|
|
|
12
12
|
exports.timeoutAwait = timeoutAwait;
|
|
13
13
|
async function timeoutPromise(executor, timeoutOptions = {}) {
|
|
14
14
|
var _a;
|
|
15
|
+
const timeout = timeoutOptions.durationMs !== undefined
|
|
16
|
+
&& Number.isFinite(timeoutOptions.durationMs)
|
|
17
|
+
&& timeoutOptions.durationMs > 0
|
|
18
|
+
? timeoutOptions.durationMs : exports.defaultTimeoutDurationMs;
|
|
15
19
|
// create the timeout error outside the async task, so it's callstack includes
|
|
16
20
|
// the original call site, this makes it easier to debug
|
|
17
21
|
const err = timeoutOptions.reject === false
|
|
18
22
|
? undefined
|
|
19
|
-
: new Error((_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "
|
|
23
|
+
: new Error(`${(_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "Timed out"}(${timeout}ms)`);
|
|
20
24
|
return new Promise((resolve, reject) => {
|
|
21
|
-
|
|
22
|
-
const timeout = setTimeout(() => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err), (_a = timeoutOptions.durationMs) !== null && _a !== void 0 ? _a : exports.defaultTimeoutDurationMs);
|
|
25
|
+
const timer = setTimeout(() => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err), timeout);
|
|
23
26
|
executor((value) => {
|
|
24
|
-
clearTimeout(
|
|
27
|
+
clearTimeout(timer);
|
|
25
28
|
resolve(value);
|
|
26
29
|
}, (reason) => {
|
|
27
|
-
clearTimeout(
|
|
30
|
+
clearTimeout(timer);
|
|
28
31
|
reject(reason);
|
|
29
32
|
});
|
|
30
33
|
});
|
package/dist/timeoutUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEU,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAarC,KAAK,UAAU,YAAY,CAC9B,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAG,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AALD,oCAKC;AAEM,KAAK,UAAU,cAAc,CAChC,QAAgG,EAChG,iBAAyD,EAAE;;IAE3D,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEU,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAarC,KAAK,UAAU,YAAY,CAC9B,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAG,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AALD,oCAKC;AAEM,KAAK,UAAU,cAAc,CAChC,QAAgG,EAChG,iBAAyD,EAAE;;IAE3D,MAAM,OAAO,GACT,cAAc,CAAC,UAAU,KAAK,SAAS;WACpC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC;WAC1C,cAAc,CAAC,UAAU,GAAG,CAAC;QAC5B,CAAC,CAAE,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,gCAAwB,CAAC;IAChE,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,MAAA,cAAc,CAAC,QAAQ,mCAAI,WAAW,IAAI,OAAO,KAAK,CAAC,CAAC;IAC3E,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAC,MAAM,EAAC,EAAE;QACpC,MAAM,KAAK,GAAG,UAAU,CACpB,GAAE,EAAE,CAAA,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EACjF,OAAO,CAAC,CAAC;QAEb,QAAQ,CACJ,CAAC,KAAK,EAAE,EAAE;YACN,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACP,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC;AA7BD,wCA6BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const defaultTimeoutDurationMs = 250;\n\nexport interface TimeoutWithError {\n durationMs?: number;\n reject?: true;\n errorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n durationMs?: number;\n reject: false;\n value: T;\n}\n\nexport async function timeoutAwait<T = void>(\n promise: PromiseLike<T>,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n return Promise.race([promise, timeoutPromise<T>(() => { }, timeoutOptions)]);\n}\n\nexport async function timeoutPromise<T = void>(\n executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n const timeout =\n timeoutOptions.durationMs !== undefined\n && Number.isFinite(timeoutOptions.durationMs)\n && timeoutOptions.durationMs > 0\n ? timeoutOptions.durationMs : defaultTimeoutDurationMs;\n // create the timeout error outside the async task, so it's callstack includes\n // the original call site, this makes it easier to debug\n const err = timeoutOptions.reject === false\n ? undefined\n : new Error(`${timeoutOptions.errorMsg ?? \"Timed out\"}(${timeout}ms)`);\n return new Promise<T>((resolve,reject)=>{\n const timer = setTimeout(\n ()=>timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),\n timeout);\n\n executor(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (reason) => {\n clearTimeout(timer);\n reject(reason);\n });\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/test-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.0",
|
|
4
4
|
"description": "Utilities for Fluid tests",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": "https://github.com/microsoft/FluidFramework",
|
|
@@ -49,34 +49,34 @@
|
|
|
49
49
|
"temp-directory": "nyc/.nyc_output"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@fluidframework/aqueduct": "0.
|
|
52
|
+
"@fluidframework/aqueduct": "^0.56.0",
|
|
53
53
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
54
54
|
"@fluidframework/common-utils": "^0.32.1",
|
|
55
|
-
"@fluidframework/container-definitions": "^0.
|
|
56
|
-
"@fluidframework/container-loader": "0.
|
|
57
|
-
"@fluidframework/container-runtime": "0.
|
|
58
|
-
"@fluidframework/container-runtime-definitions": "0.
|
|
59
|
-
"@fluidframework/core-interfaces": "^0.
|
|
60
|
-
"@fluidframework/datastore": "0.
|
|
61
|
-
"@fluidframework/datastore-definitions": "0.
|
|
62
|
-
"@fluidframework/driver-definitions": "^0.
|
|
63
|
-
"@fluidframework/driver-utils": "0.
|
|
64
|
-
"@fluidframework/local-driver": "0.
|
|
65
|
-
"@fluidframework/map": "0.
|
|
55
|
+
"@fluidframework/container-definitions": "^0.45.0",
|
|
56
|
+
"@fluidframework/container-loader": "^0.56.0",
|
|
57
|
+
"@fluidframework/container-runtime": "^0.56.0",
|
|
58
|
+
"@fluidframework/container-runtime-definitions": "^0.56.0",
|
|
59
|
+
"@fluidframework/core-interfaces": "^0.42.0",
|
|
60
|
+
"@fluidframework/datastore": "^0.56.0",
|
|
61
|
+
"@fluidframework/datastore-definitions": "^0.56.0",
|
|
62
|
+
"@fluidframework/driver-definitions": "^0.44.0",
|
|
63
|
+
"@fluidframework/driver-utils": "^0.56.0",
|
|
64
|
+
"@fluidframework/local-driver": "^0.56.0",
|
|
65
|
+
"@fluidframework/map": "^0.56.0",
|
|
66
66
|
"@fluidframework/protocol-definitions": "^0.1026.0",
|
|
67
|
-
"@fluidframework/request-handler": "0.
|
|
68
|
-
"@fluidframework/routerlicious-driver": "0.
|
|
69
|
-
"@fluidframework/runtime-definitions": "0.
|
|
70
|
-
"@fluidframework/runtime-utils": "0.
|
|
71
|
-
"@fluidframework/telemetry-utils": "0.
|
|
72
|
-
"@fluidframework/test-driver-definitions": "0.
|
|
73
|
-
"@fluidframework/test-runtime-utils": "0.
|
|
67
|
+
"@fluidframework/request-handler": "^0.56.0",
|
|
68
|
+
"@fluidframework/routerlicious-driver": "^0.56.0",
|
|
69
|
+
"@fluidframework/runtime-definitions": "^0.56.0",
|
|
70
|
+
"@fluidframework/runtime-utils": "^0.56.0",
|
|
71
|
+
"@fluidframework/telemetry-utils": "^0.56.0",
|
|
72
|
+
"@fluidframework/test-driver-definitions": "^0.56.0",
|
|
73
|
+
"@fluidframework/test-runtime-utils": "^0.56.0",
|
|
74
74
|
"debug": "^4.1.1",
|
|
75
75
|
"uuid": "^8.3.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@fluidframework/build-common": "^0.23.0",
|
|
79
|
-
"@fluidframework/eslint-config-fluid": "^0.25.0
|
|
79
|
+
"@fluidframework/eslint-config-fluid": "^0.25.0",
|
|
80
80
|
"@microsoft/api-extractor": "^7.16.1",
|
|
81
81
|
"@rushstack/eslint-config": "^2.5.1",
|
|
82
82
|
"@types/diff": "^3.5.1",
|
|
@@ -123,7 +123,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
private trackLastProposal(container: IContainer) {
|
|
126
|
-
container.
|
|
126
|
+
container.on("codeDetailsProposed", (value, proposal) => {
|
|
127
127
|
if (proposal.sequenceNumber > this.lastProposalSeqNum) {
|
|
128
128
|
this.lastProposalSeqNum = proposal.sequenceNumber;
|
|
129
129
|
}
|
package/src/packageVersion.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IContainer, IHostLoader
|
|
6
|
+
import { IContainer, IHostLoader } from "@fluidframework/container-definitions";
|
|
7
7
|
import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
|
|
8
|
-
import {
|
|
8
|
+
import { ILoaderProps, Loader, waitContainerToCatchUp } from "@fluidframework/container-loader";
|
|
9
9
|
import { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
|
|
10
10
|
import { IFluidCodeDetails, IRequestHeader } from "@fluidframework/core-interfaces";
|
|
11
11
|
import { IDocumentServiceFactory, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
|
|
@@ -34,13 +34,12 @@ export interface ITestObjectProvider {
|
|
|
34
34
|
createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;
|
|
35
35
|
createLoader(
|
|
36
36
|
packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
37
|
-
|
|
38
|
-
detachedBlobStorage?: IDetachedBlobStorage,
|
|
37
|
+
loaderProps?: Partial<ILoaderProps>,
|
|
39
38
|
): IHostLoader;
|
|
40
|
-
createContainer(entryPoint: fluidEntryPoint,
|
|
39
|
+
createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>): Promise<IContainer>;
|
|
41
40
|
loadContainer(
|
|
42
41
|
entryPoint: fluidEntryPoint,
|
|
43
|
-
|
|
42
|
+
loaderProps?: Partial<ILoaderProps>,
|
|
44
43
|
requestHeader?: IRequestHeader,
|
|
45
44
|
): Promise<IContainer>;
|
|
46
45
|
|
|
@@ -48,7 +47,7 @@ export interface ITestObjectProvider {
|
|
|
48
47
|
* Used to create a test Container. The Loader/ContainerRuntime/DataRuntime might be different versioned.
|
|
49
48
|
* In generateLocalCompatTest(), this Container and its runtime will be arbitrarily-versioned.
|
|
50
49
|
*/
|
|
51
|
-
makeTestLoader(testContainerConfig?: ITestContainerConfig
|
|
50
|
+
makeTestLoader(testContainerConfig?: ITestContainerConfig): IHostLoader,
|
|
52
51
|
makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>,
|
|
53
52
|
loadTestContainer(testContainerConfig?: ITestContainerConfig, requestHeader?: IRequestHeader): Promise<IContainer>,
|
|
54
53
|
/**
|
|
@@ -86,12 +85,7 @@ export interface ITestContainerConfig {
|
|
|
86
85
|
runtimeOptions?: IContainerRuntimeOptions,
|
|
87
86
|
|
|
88
87
|
/** Loader options for the loader used to create containers */
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// new interface to help inject custom loggers to tests
|
|
93
|
-
export interface ITestLoaderOptions extends ILoaderOptions {
|
|
94
|
-
logger?: ITelemetryBaseLogger;
|
|
88
|
+
loaderProps?: Partial<ILoaderProps>,
|
|
95
89
|
}
|
|
96
90
|
|
|
97
91
|
export const createDocumentId = (): string => uuid();
|
|
@@ -131,7 +125,7 @@ function getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {
|
|
|
131
125
|
/**
|
|
132
126
|
* Shared base class for test object provider. Contain code for loader and container creation and loading
|
|
133
127
|
*/
|
|
134
|
-
export class TestObjectProvider {
|
|
128
|
+
export class TestObjectProvider implements ITestObjectProvider {
|
|
135
129
|
private readonly _loaderContainerTracker = new LoaderContainerTracker();
|
|
136
130
|
private _documentServiceFactory: IDocumentServiceFactory | undefined;
|
|
137
131
|
private _urlResolver: IUrlResolver | undefined;
|
|
@@ -204,23 +198,20 @@ export class TestObjectProvider {
|
|
|
204
198
|
*/
|
|
205
199
|
public createLoader(
|
|
206
200
|
packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
207
|
-
|
|
208
|
-
detachedBlobStorage?: IDetachedBlobStorage,
|
|
201
|
+
loaderProps?: Partial<ILoaderProps>,
|
|
209
202
|
) {
|
|
210
203
|
const multiSinkLogger = new MultiSinkLogger();
|
|
211
204
|
multiSinkLogger.addLogger(this.logger);
|
|
212
|
-
if (
|
|
213
|
-
multiSinkLogger.addLogger(
|
|
205
|
+
if (loaderProps?.logger !== undefined) {
|
|
206
|
+
multiSinkLogger.addLogger(loaderProps.logger);
|
|
214
207
|
}
|
|
215
208
|
|
|
216
|
-
const codeLoader = new LocalCodeLoader(packageEntries);
|
|
217
209
|
const loader = new this.LoaderConstructor({
|
|
218
|
-
|
|
219
|
-
documentServiceFactory: this.documentServiceFactory,
|
|
220
|
-
codeLoader,
|
|
210
|
+
... loaderProps,
|
|
221
211
|
logger: multiSinkLogger,
|
|
222
|
-
|
|
223
|
-
|
|
212
|
+
codeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),
|
|
213
|
+
urlResolver: loaderProps?.urlResolver ?? this.urlResolver,
|
|
214
|
+
documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,
|
|
224
215
|
});
|
|
225
216
|
this._loaderContainerTracker.add(loader);
|
|
226
217
|
return loader;
|
|
@@ -235,12 +226,12 @@ export class TestObjectProvider {
|
|
|
235
226
|
*
|
|
236
227
|
* @param packageEntries - list of code details and fluidEntryPoint pairs.
|
|
237
228
|
*/
|
|
238
|
-
public async createContainer(entryPoint: fluidEntryPoint,
|
|
229
|
+
public async createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>) {
|
|
239
230
|
if (this._documentCreated) {
|
|
240
231
|
throw new Error(
|
|
241
232
|
"Only one container/document can be created. To load the container/document use loadContainer");
|
|
242
233
|
}
|
|
243
|
-
const loader = this.createLoader([[defaultCodeDetails, entryPoint]],
|
|
234
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
244
235
|
const container = await createAndAttachContainer(
|
|
245
236
|
defaultCodeDetails,
|
|
246
237
|
loader,
|
|
@@ -253,9 +244,11 @@ export class TestObjectProvider {
|
|
|
253
244
|
return container;
|
|
254
245
|
}
|
|
255
246
|
|
|
256
|
-
public async loadContainer(
|
|
247
|
+
public async loadContainer(
|
|
248
|
+
entryPoint: fluidEntryPoint,
|
|
249
|
+
loaderProps?: Partial<ILoaderProps>,
|
|
257
250
|
requestHeader?: IRequestHeader): Promise<IContainer> {
|
|
258
|
-
const loader = this.createLoader([[defaultCodeDetails, entryPoint]],
|
|
251
|
+
const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);
|
|
259
252
|
return loader.resolve({ url: await this.driver.createContainerUrl(this.documentId), headers: requestHeader });
|
|
260
253
|
}
|
|
261
254
|
|
|
@@ -264,11 +257,10 @@ export class TestObjectProvider {
|
|
|
264
257
|
* The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run
|
|
265
258
|
* @param testContainerConfig - optional configuring the test Container
|
|
266
259
|
*/
|
|
267
|
-
public makeTestLoader(testContainerConfig?: ITestContainerConfig
|
|
260
|
+
public makeTestLoader(testContainerConfig?: ITestContainerConfig) {
|
|
268
261
|
return this.createLoader(
|
|
269
262
|
[[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],
|
|
270
|
-
testContainerConfig?.
|
|
271
|
-
detachedBlobStorage,
|
|
263
|
+
testContainerConfig?.loaderProps,
|
|
272
264
|
);
|
|
273
265
|
}
|
|
274
266
|
|
package/src/timeoutUtils.ts
CHANGED
|
@@ -27,23 +27,28 @@ export async function timeoutPromise<T = void>(
|
|
|
27
27
|
executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,
|
|
28
28
|
timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},
|
|
29
29
|
): Promise<T> {
|
|
30
|
+
const timeout =
|
|
31
|
+
timeoutOptions.durationMs !== undefined
|
|
32
|
+
&& Number.isFinite(timeoutOptions.durationMs)
|
|
33
|
+
&& timeoutOptions.durationMs > 0
|
|
34
|
+
? timeoutOptions.durationMs : defaultTimeoutDurationMs;
|
|
30
35
|
// create the timeout error outside the async task, so it's callstack includes
|
|
31
36
|
// the original call site, this makes it easier to debug
|
|
32
37
|
const err = timeoutOptions.reject === false
|
|
33
38
|
? undefined
|
|
34
|
-
: new Error(timeoutOptions.errorMsg ?? "
|
|
35
|
-
return new Promise<T>((resolve,
|
|
36
|
-
const
|
|
37
|
-
()
|
|
38
|
-
|
|
39
|
+
: new Error(`${timeoutOptions.errorMsg ?? "Timed out"}(${timeout}ms)`);
|
|
40
|
+
return new Promise<T>((resolve,reject)=>{
|
|
41
|
+
const timer = setTimeout(
|
|
42
|
+
()=>timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),
|
|
43
|
+
timeout);
|
|
39
44
|
|
|
40
45
|
executor(
|
|
41
46
|
(value) => {
|
|
42
|
-
clearTimeout(
|
|
47
|
+
clearTimeout(timer);
|
|
43
48
|
resolve(value);
|
|
44
49
|
},
|
|
45
50
|
(reason) => {
|
|
46
|
-
clearTimeout(
|
|
51
|
+
clearTimeout(timer);
|
|
47
52
|
reject(reason);
|
|
48
53
|
});
|
|
49
54
|
});
|