@fluid-experimental/tree 1.3.3 → 1.3.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"IdCompressorTestUtilities.js","sourceRoot":"","sources":["../../../src/test/utilities/IdCompressorTestUtilities.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\n/* eslint-disable no-bitwise */\n\nimport { expect } from 'chai';\nimport {\n\tGenerator,\n\tcreateWeightedGenerator,\n\tinterleave,\n\tmakeRandom,\n\tperformFuzzActions as performFuzzActionsBase,\n\trepeat,\n\tSaveInfo,\n\ttake,\n\tBaseFuzzTestState,\n} from '@fluid-internal/stochastic-test-utils';\nimport { assert, assertNotUndefined, ClosedMap, fail, getOrCreate } from '../../Common';\nimport { IdCompressor, isLocalId } from '../../id-compressor/IdCompressor';\nimport {\n\tcreateSessionId,\n\tensureSessionUuid,\n\tNumericUuid,\n\tnumericUuidFromStableId,\n\tstableIdFromNumericUuid,\n} from '../../id-compressor/NumericUuid';\nimport {\n\tFinalCompressedId,\n\tSessionId,\n\tStableId,\n\tSessionSpaceCompressedId,\n\tAttributionId,\n\tOpSpaceCompressedId,\n} from '../../Identifiers';\nimport { getIds } from '../../id-compressor/IdRange';\nimport type {\n\tIdCreationRange,\n\tSerializedIdCompressorWithOngoingSession,\n\tSerializedIdCompressorWithNoSession,\n} from '../../id-compressor';\nimport { assertIsStableId, assertIsUuidString } from '../../UuidUtilities';\nimport { expectDefined } from './TestCommon';\n\n/** Identifies a compressor in a network */\nexport enum Client {\n\tClient1 = 'Client1',\n\tClient2 = 'Client2',\n\tClient3 = 'Client3',\n}\n\n/** Identifies a compressor with respect to a specific operation */\nexport enum SemanticClient {\n\tLocalClient = 'LocalClient',\n}\n\n/** Identifies categories of compressors */\nexport enum MetaClient {\n\tAll = 'All',\n}\n\n/**\n * Used to attribute actions to clients in a distributed collaboration session.\n * `Local` implies a local and unsequenced operation. All others imply sequenced operations.\n */\nexport type OriginatingClient = Client | SemanticClient;\nexport const OriginatingClient = { ...Client, ...SemanticClient };\n\n/** Identifies a compressor to which to send an operation */\nexport type DestinationClient = Client | MetaClient;\nexport const DestinationClient = { ...Client, ...MetaClient };\n\n/**\n * Creates a new compressor with the supplied cluster capacity.\n */\nexport function createCompressor(client: Client, clusterCapacity = 5, attributionId?: AttributionId): IdCompressor {\n\tconst compressor = new IdCompressor(sessionIds.get(client), 1024, attributionId);\n\tcompressor.clusterCapacity = clusterCapacity;\n\treturn compressor;\n}\n\n/**\n * A closed map from NamedClient to T.\n */\nexport type ClientMap<T> = ClosedMap<Client, T>;\n\nfunction makeSessionIds(): ClientMap<SessionId> {\n\tconst stableIds = new Map<Client, SessionId>();\n\tconst clients = Object.values(Client);\n\tfor (let i = 0; i < clients.length; i++) {\n\t\t// Place session uuids roughly in the middle of uuid space to increase odds of encountering interesting\n\t\t// orderings in sorted collections\n\t\tconst sessionId = ensureSessionUuid(assertIsStableId(`88888888-8888-4888-b${i}88-888888888888`));\n\t\tstableIds.set(clients[i], sessionId);\n\t}\n\treturn stableIds as ClientMap<SessionId>;\n}\n\n/**\n * An array of session ID strings corresponding to all non-local `Client` entries.\n */\nexport const sessionIds = makeSessionIds();\n\n/**\n * An array of session uuids corresponding to all non-local `Client` entries.\n */\nexport const sessionNumericUuids = new Map(\n\t[...sessionIds.entries()].map(([client, sessionId]) => {\n\t\treturn [client, numericUuidFromStableId(sessionId)];\n\t})\n) as ClientMap<NumericUuid>;\n\nexport const attributionIds = new Map(\n\tObject.values(Client).map((c, i) => [\n\t\tc,\n\t\tassertIsUuidString(`00000000-0000-0000-0000-${(i + 1).toString(16).padStart(12, '0')}`),\n\t])\n) as ClientMap<AttributionId>;\n\n/** An immutable view of an `IdCompressor` */\nexport interface ReadonlyIdCompressor\n\textends Omit<\n\t\tIdCompressor,\n\t\t'generateCompressedId' | 'generateCompressedIdRange' | 'takeNextCreationRange' | 'finalizeCreationRange'\n\t> {\n\treadonly clusterCapacity: number;\n}\n\n/** Information about a generated ID in a network to be validated by tests */\nexport interface TestIdData {\n\treadonly id: SessionSpaceCompressedId;\n\treadonly originatingClient: Client;\n\treadonly sessionId: SessionId;\n\treadonly sessionNumericUuid: NumericUuid;\n\treadonly expectedOverride: string | undefined;\n\treadonly isSequenced: boolean;\n}\n\n/**\n * Simulates a network of ID compressors.\n * Not suitable for performance testing.\n */\nexport class IdCompressorTestNetwork {\n\t/** The compressors used in this network */\n\tprivate readonly compressors: ClientMap<IdCompressor>;\n\t/** The log of operations seen by the server so far. Append-only. */\n\tprivate readonly serverOperations: (\n\t\t| [creationRange: IdCreationRange, opSpaceIds: OpSpaceCompressedId[], clientFrom: Client]\n\t\t| number\n\t)[] = [];\n\t/** An index into `serverOperations` for each client which represents how many operations have been delivered to that client */\n\tprivate readonly clientProgress: ClientMap<number>;\n\t/** All ids (local and sequenced) that a client has created or received, in order. */\n\tprivate readonly idLogs: ClientMap<TestIdData[]>;\n\t/** All ids that a client has received from the server, in order. */\n\tprivate readonly sequencedIdLogs: ClientMap<TestIdData[]>;\n\n\tpublic constructor(\n\t\tpublic readonly initialClusterSize = 5,\n\t\tprivate readonly onIdReceived?: (network: IdCompressorTestNetwork, clientTo: Client, ids: TestIdData[]) => void\n\t) {\n\t\tconst compressors = new Map<Client, IdCompressor>();\n\t\tconst clientProgress = new Map<Client, number>();\n\t\tconst clientIds = new Map<Client, TestIdData[]>();\n\t\tconst clientSequencedIds = new Map<Client, TestIdData[]>();\n\t\tfor (const client of Object.values(Client)) {\n\t\t\tconst compressor = createCompressor(client, initialClusterSize, attributionIds.get(client));\n\t\t\tcompressors.set(client, compressor);\n\t\t\tclientProgress.set(client, 0);\n\t\t\tclientIds.set(client, []);\n\t\t\tclientSequencedIds.set(client, []);\n\t\t}\n\t\tthis.compressors = compressors as ClientMap<IdCompressor>;\n\t\tthis.clientProgress = clientProgress as ClientMap<number>;\n\t\tthis.idLogs = clientIds as ClientMap<TestIdData[]>;\n\t\tthis.sequencedIdLogs = clientSequencedIds as ClientMap<TestIdData[]>;\n\t}\n\n\t/**\n\t * Returns an immutable handle to a compressor in the network.\n\t */\n\tpublic getCompressor(client: Client): ReadonlyIdCompressor {\n\t\tconst compressors = this.compressors;\n\t\tconst handler = {\n\t\t\tget(_, property) {\n\t\t\t\tconst compressor = compressors.get(client);\n\t\t\t\treturn compressor[property];\n\t\t\t},\n\t\t\tset(_, property, value): boolean {\n\t\t\t\tconst compressor = compressors.get(client);\n\t\t\t\tcompressor[property] = value;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t};\n\t\treturn new Proxy<IdCompressor>({} as unknown as IdCompressor, handler);\n\t}\n\n\t/**\n\t * Returns a mutable handle to a compressor in the network. Use of mutation methods will break the network invariants and\n\t * should only be used if the network will not be used again.\n\t */\n\tpublic getCompressorUnsafe(client: Client): IdCompressor {\n\t\treturn this.getCompressor(client) as IdCompressor;\n\t}\n\n\t/**\n\t * Returns a mutable handle to a compressor in the network. Use of mutation methods will break the network invariants and\n\t * should only be used if the network will not be used again. Additionally, the returned compressor will be invalidated/unusable\n\t * if any network operations cause it to be regenerated (serialization/deserialization, etc.).\n\t */\n\tpublic getCompressorUnsafeNoProxy(client: Client): IdCompressor {\n\t\treturn this.compressors.get(client);\n\t}\n\n\t/**\n\t * Returns data for all IDs created and received by this client, including ack's of their own (i.e. their own IDs will appear twice)\n\t */\n\tpublic getIdLog(client: Client): readonly TestIdData[] {\n\t\treturn this.idLogs.get(client);\n\t}\n\n\t/**\n\t * Returns data for all IDs received by this client, including ack's of their own.\n\t */\n\tpublic getSequencedIdLog(client: Client): readonly TestIdData[] {\n\t\treturn this.sequencedIdLogs.get(client);\n\t}\n\n\t/**\n\t * Get all compressors for the given destination\n\t */\n\tpublic getTargetCompressors(clientTo: DestinationClient): [Client, IdCompressor][] {\n\t\treturn clientTo === MetaClient.All\n\t\t\t? [...this.compressors.entries()]\n\t\t\t: ([[clientTo, this.getCompressor(clientTo)]] as [Client, IdCompressor][]);\n\t}\n\n\t/**\n\t * Submit a capacity change operation to the network. It will not take effect immediately but will be processed in sequence order.\n\t */\n\tpublic enqueueCapacityChange(newClusterCapacity: number): void {\n\t\tthis.serverOperations.push(newClusterCapacity);\n\t}\n\n\tprivate addNewId(\n\t\tclient: Client,\n\t\tid: SessionSpaceCompressedId,\n\t\texpectedOverride: string | undefined,\n\t\toriginatingClient: Client,\n\t\tisSequenced: boolean\n\t): void {\n\t\tconst idData = {\n\t\t\tid,\n\t\t\toriginatingClient,\n\t\t\tsessionId: sessionIds.get(originatingClient),\n\t\t\tsessionNumericUuid: sessionNumericUuids.get(originatingClient),\n\t\t\texpectedOverride,\n\t\t\tisSequenced,\n\t\t};\n\t\tconst clientIds = this.idLogs.get(client);\n\t\tclientIds.push(idData);\n\t\tif (isSequenced) {\n\t\t\tconst sequencedIds = this.sequencedIdLogs.get(client);\n\t\t\tsequencedIds.push(idData);\n\t\t}\n\t\tthis.onIdReceived?.(this, client, clientIds);\n\t}\n\n\t/**\n\t * Allocates a new range of local IDs and enqueues them for future delivery via a `testIdDelivery` action.\n\t * Calls to this method determine the total order of delivery, regardless of when `deliverOperations` is called.\n\t */\n\tpublic allocateAndSendIds(client: Client, numIds: number): OpSpaceCompressedId[];\n\n\t/**\n\t * Allocates a new range of local IDs and enqueues them for future delivery via a `testIdDelivery` action.\n\t * Calls to this method determine the total order of delivery, regardless of when `deliverOperations` is called.\n\t */\n\tpublic allocateAndSendIds(client: Client, numIds: number, overrides: { [index: number]: string }): IdCreationRange;\n\n\tpublic allocateAndSendIds(\n\t\tclient: Client,\n\t\tnumIds: number,\n\t\toverrides: { [index: number]: string } = {}\n\t): OpSpaceCompressedId[] | IdCreationRange {\n\t\tassert(numIds > 0, 'Must allocate a non-zero number of IDs');\n\t\tconst compressor = this.compressors.get(client);\n\t\tlet nextIdIndex = 0;\n\t\tconst opSpaceIds: OpSpaceCompressedId[] = [];\n\t\tfor (const [overrideIndex, uuid] of Object.entries(overrides)\n\t\t\t.map(([id, uuid]) => [Number.parseInt(id, 10), uuid] as [number, string])\n\t\t\t.sort(([a], [b]) => a - b)) {\n\t\t\twhile (nextIdIndex < overrideIndex) {\n\t\t\t\tconst newId = compressor.generateCompressedId();\n\t\t\t\topSpaceIds.push(compressor.normalizeToOpSpace(newId));\n\t\t\t\tthis.addNewId(client, newId, undefined, client, false);\n\t\t\t\tnextIdIndex += 1;\n\t\t\t}\n\t\t\tconst newOverrideId = compressor.generateCompressedId(uuid);\n\t\t\topSpaceIds.push(compressor.normalizeToOpSpace(newOverrideId));\n\t\t\tthis.addNewId(client, newOverrideId, uuid, client, false);\n\t\t\tnextIdIndex += 1;\n\t\t}\n\t\tconst numTrailingIds = numIds - nextIdIndex;\n\t\tif (numTrailingIds > 0) {\n\t\t\tconst sessionSpaceIds = generateCompressedIds(compressor, numTrailingIds);\n\t\t\tfor (let i = 0; i < numTrailingIds; i++) {\n\t\t\t\tthis.addNewId(client, sessionSpaceIds[i], undefined, client, false);\n\t\t\t}\n\t\t\tsessionSpaceIds.forEach((id) => opSpaceIds.push(compressor.normalizeToOpSpace(id)));\n\t\t}\n\t\tconst creationRange = compressor.takeNextCreationRange();\n\t\tthis.serverOperations.push([creationRange, opSpaceIds, client]);\n\t\treturn nextIdIndex === 0 ? opSpaceIds : creationRange;\n\t}\n\n\t/**\n\t * Delivers all undelivered ID ranges and cluster capacity changes from the server to the target clients.\n\t */\n\tpublic deliverOperations(clientTakingDelivery: DestinationClient) {\n\t\tfor (const [clientTo, compressorTo] of this.getTargetCompressors(clientTakingDelivery)) {\n\t\t\tfor (let i = this.clientProgress.get(clientTo); i < this.serverOperations.length; i++) {\n\t\t\t\tconst operation = this.serverOperations[i];\n\t\t\t\tif (typeof operation === 'number') {\n\t\t\t\t\tcompressorTo.clusterCapacity = operation;\n\t\t\t\t} else {\n\t\t\t\t\tconst [range, opSpaceIds, clientFrom] = operation;\n\t\t\t\t\tcompressorTo.finalizeCreationRange(range);\n\n\t\t\t\t\tconst ids = getIds(range);\n\t\t\t\t\tif (ids !== undefined) {\n\t\t\t\t\t\tlet overrideIndex = 0;\n\t\t\t\t\t\tconst overrides = ids.overrides;\n\t\t\t\t\t\tfor (const id of opSpaceIds) {\n\t\t\t\t\t\t\tlet override: string | undefined;\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\toverrides !== undefined &&\n\t\t\t\t\t\t\t\toverrideIndex < overrides.length &&\n\t\t\t\t\t\t\t\tid === overrides[overrideIndex][0]\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\toverride = overrides[overrideIndex][1];\n\t\t\t\t\t\t\t\toverrideIndex++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst sessionSpaceId = compressorTo.normalizeToSessionSpace(id, range.sessionId);\n\t\t\t\t\t\t\tthis.addNewId(clientTo, sessionSpaceId, override, clientFrom, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tassert(overrideIndex === (overrides?.length ?? 0));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.clientProgress.set(clientTo, this.serverOperations.length);\n\t\t}\n\t}\n\n\t/**\n\t * Simulate a client disconnecting (and serializing), then reconnecting (and deserializing)\n\t */\n\tpublic goOfflineThenResume(client: Client): void {\n\t\tconst compressor = this.compressors.get(client);\n\t\tconst [_, resumedCompressor] = roundtrip(compressor, true);\n\t\tthis.compressors.set(client, resumedCompressor);\n\t}\n\n\t/**\n\t * Ensure general validity of the network state. Useful for calling periodically or at the end of test scenarios.\n\t */\n\tpublic assertNetworkState(): void {\n\t\tconst sequencedLogs = Object.values(Client).map(\n\t\t\t(client) => [this.compressors.get(client), this.getSequencedIdLog(client)] as const\n\t\t);\n\n\t\tconst maxLogLength = sequencedLogs.map(([_, data]) => data.length).reduce((p, n) => Math.max(p, n));\n\n\t\tfunction getNextLogWithEntryAt(logsIndex: number, entryIndex: number): number | undefined {\n\t\t\tfor (let i = logsIndex; i < sequencedLogs.length; i++) {\n\t\t\t\tconst log = sequencedLogs[i];\n\t\t\t\tif (log[1].length > entryIndex) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst uuids = new Set<string>();\n\t\tconst finalIds = new Set<FinalCompressedId>();\n\t\tconst idIndicesAggregator = new Map<Client, number>();\n\n\t\tfunction* getLogIndices(\n\t\t\tcolumnIndex: number\n\t\t): Iterable<\n\t\t\t[\n\t\t\t\tcurrent: [compressor: IdCompressor, idData: TestIdData],\n\t\t\t\tnext?: [compressor: IdCompressor, idData: TestIdData]\n\t\t\t]\n\t\t> {\n\t\t\tlet current = getNextLogWithEntryAt(0, columnIndex);\n\t\t\twhile (current !== undefined) {\n\t\t\t\tconst next = getNextLogWithEntryAt(current + 1, columnIndex);\n\t\t\t\tconst [compressor, log] = sequencedLogs[current];\n\t\t\t\tif (next === undefined) {\n\t\t\t\t\tyield [[compressor, log[columnIndex]]];\n\t\t\t\t} else {\n\t\t\t\t\tconst [compressorNext, logNext] = sequencedLogs[next];\n\t\t\t\t\tyield [\n\t\t\t\t\t\t[compressor, log[columnIndex]],\n\t\t\t\t\t\t[compressorNext, logNext[columnIndex]],\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0; i < maxLogLength; i++) {\n\t\t\tconst creator: [creator: Client, override?: string][] = [];\n\t\t\tlet originatingClient: Client | undefined;\n\t\t\tlet localCount = 0;\n\t\t\tlet rowCount = 0;\n\t\t\tfor (const [current, next] of getLogIndices(i)) {\n\t\t\t\tconst [compressorA, idDataA] = current;\n\t\t\t\tconst sessionSpaceIdA = idDataA.id;\n\t\t\t\tconst idIndex = getOrCreate(idIndicesAggregator, idDataA.originatingClient, () => 0);\n\t\t\t\toriginatingClient ??= idDataA.originatingClient;\n\t\t\t\tassert(\n\t\t\t\t\tidDataA.originatingClient === originatingClient,\n\t\t\t\t\t'Test infra gave wrong originating client to TestIdData'\n\t\t\t\t);\n\t\t\t\tconst attributionA = compressorA.attributeId(idDataA.id);\n\t\t\t\tif (attributionA !== attributionIds.get(idDataA.originatingClient)) {\n\t\t\t\t\t// Unification\n\t\t\t\t\texpectDefined(idDataA.expectedOverride);\n\t\t\t\t}\n\n\t\t\t\t// Only one client should have this ID as local in its session space, as only one client could have created this ID\n\t\t\t\tif (isLocalId(sessionSpaceIdA)) {\n\t\t\t\t\tlocalCount++;\n\t\t\t\t\texpect(idDataA.sessionId).to.equal(this.compressors.get(originatingClient).localSessionId);\n\t\t\t\t\texpect(creator.length === 0 || creator[creator.length - 1][1] === idDataA.expectedOverride).to.be\n\t\t\t\t\t\t.true;\n\t\t\t\t\tcreator.push([originatingClient, idDataA.expectedOverride]);\n\t\t\t\t}\n\n\t\t\t\tconst uuidASessionSpace = compressorA.decompress(sessionSpaceIdA);\n\t\t\t\tif (idDataA.expectedOverride !== undefined) {\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(idDataA.expectedOverride);\n\t\t\t\t} else {\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(stableIdFromNumericUuid(idDataA.sessionNumericUuid, idIndex));\n\t\t\t\t}\n\t\t\t\texpect(compressorA.recompress(uuidASessionSpace)).to.equal(sessionSpaceIdA);\n\t\t\t\tuuids.add(uuidASessionSpace);\n\t\t\t\tconst opSpaceIdA = compressorA.normalizeToOpSpace(sessionSpaceIdA);\n\t\t\t\tif (isLocalId(opSpaceIdA)) {\n\t\t\t\t\texpect.fail('IDs should have been finalized.');\n\t\t\t\t\tfail();\n\t\t\t\t}\n\t\t\t\texpect(compressorA.normalizeToSessionSpace(opSpaceIdA, compressorA.localSessionId)).equals(\n\t\t\t\t\tsessionSpaceIdA\n\t\t\t\t);\n\t\t\t\tfinalIds.add(opSpaceIdA);\n\t\t\t\tconst uuidAOpSpace = compressorA.decompress(opSpaceIdA);\n\n\t\t\t\texpect(uuidASessionSpace).to.equal(uuidAOpSpace);\n\n\t\t\t\tif (next !== undefined) {\n\t\t\t\t\tconst [compressorB, idDataB] = next;\n\t\t\t\t\tconst sessionSpaceIdB = idDataB.id;\n\n\t\t\t\t\tconst uuidBSessionSpace = compressorB.decompress(sessionSpaceIdB);\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(uuidBSessionSpace);\n\t\t\t\t\tconst opSpaceIdB = compressorB.normalizeToOpSpace(sessionSpaceIdB);\n\t\t\t\t\tif (opSpaceIdA !== opSpaceIdB) {\n\t\t\t\t\t\tcompressorB.normalizeToOpSpace(sessionSpaceIdB);\n\t\t\t\t\t\tcompressorA.normalizeToOpSpace(sessionSpaceIdA);\n\t\t\t\t\t}\n\t\t\t\t\texpect(opSpaceIdA).to.equal(opSpaceIdB);\n\t\t\t\t\tif (isLocalId(opSpaceIdB)) {\n\t\t\t\t\t\tfail('IDs should have been finalized.');\n\t\t\t\t\t}\n\t\t\t\t\tconst uuidBOpSpace = compressorB.decompress(opSpaceIdB);\n\t\t\t\t\texpect(uuidAOpSpace).to.equal(uuidBOpSpace);\n\t\t\t\t}\n\n\t\t\t\trowCount += 1;\n\t\t\t}\n\n\t\t\t// A local count === 0 indicates the ID was created as an eager final, and thus cannot have had an\n\t\t\t// override to unify.\n\t\t\tif (rowCount === this.sequencedIdLogs.size && localCount <= 1) {\n\t\t\t\texpect(localCount).to.lessThanOrEqual(1);\n\t\t\t\tfor (const [[compressor, { id, originatingClient }]] of getLogIndices(i)) {\n\t\t\t\t\texpect(compressor.attributeId(id)).to.equal(attributionIds.get(originatingClient));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texpect(uuids.size).to.equal(finalIds.size);\n\t\t\tassert(originatingClient !== undefined);\n\t\t\tidIndicesAggregator.set(\n\t\t\t\toriginatingClient,\n\t\t\t\tassertNotUndefined(idIndicesAggregator.get(originatingClient)) + 1\n\t\t\t);\n\t\t}\n\n\t\tfor (const [compressor] of sequencedLogs) {\n\t\t\texpectSerializes(compressor);\n\t\t}\n\t}\n}\n\n/**\n * Roundtrips the supplied compressor through serialization and deserialization.\n */\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: true\n): [SerializedIdCompressorWithOngoingSession, IdCompressor];\n\n/**\n * Roundtrips the supplied compressor through serialization and deserialization.\n */\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: false\n): [SerializedIdCompressorWithNoSession, IdCompressor];\n\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: boolean\n): [SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession, IdCompressor] {\n\tif (withSession) {\n\t\tconst serialized = compressor.serialize(withSession);\n\t\treturn [serialized, IdCompressor.deserialize(serialized)];\n\t}\n\n\tconst nonLocalSerialized = compressor.serialize(withSession);\n\treturn [nonLocalSerialized, IdCompressor.deserialize(nonLocalSerialized, createSessionId())];\n}\n\n/**\n * Asserts that the supplied compressor correctly roundtrips through serialization/deserialization.\n */\nexport function expectSerializes(\n\tcompressor: ReadonlyIdCompressor\n): [SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession] {\n\tfunction expectSerializes(\n\t\twithSession: boolean\n\t): SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession {\n\t\tlet serialized: SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession;\n\t\tlet deserialized: IdCompressor;\n\t\tif (withSession) {\n\t\t\t[serialized, deserialized] = roundtrip(compressor, true);\n\t\t} else {\n\t\t\t[serialized, deserialized] = roundtrip(compressor, false);\n\t\t}\n\t\tconst chainCount: number[] = [];\n\t\tfor (let i = 0; i < serialized.sessions.length; i++) {\n\t\t\tchainCount[i] = 0;\n\t\t}\n\t\tconst chainProcessed: number[] = [...chainCount];\n\n\t\tfor (const cluster of serialized.clusters) {\n\t\t\tconst [sessionIndex] = cluster;\n\t\t\texpect(sessionIndex < serialized.sessions.length);\n\t\t\tchainCount[sessionIndex]++;\n\t\t}\n\n\t\tfor (const cluster of serialized.clusters) {\n\t\t\tconst [sessionIndex, capacity, maybeSize] = cluster;\n\t\t\tconst chainIndex = chainProcessed[sessionIndex];\n\t\t\tif (chainIndex < chainCount[sessionIndex] - 1) {\n\t\t\t\texpect(maybeSize === undefined);\n\t\t\t} else {\n\t\t\t\texpect(maybeSize === undefined || typeof maybeSize !== 'number' || maybeSize < capacity);\n\t\t\t}\n\t\t\tchainProcessed[sessionIndex]++;\n\t\t}\n\n\t\texpect(compressor.equals(deserialized, withSession)).to.be.true;\n\t\treturn serialized;\n\t}\n\n\treturn [\n\t\texpectSerializes(false) as SerializedIdCompressorWithNoSession,\n\t\texpectSerializes(true) as SerializedIdCompressorWithOngoingSession,\n\t];\n}\n\n/**\n * Merges 'from' into 'to', and returns 'to'.\n */\nexport function mergeArrayMaps<K, V>(\n\tto: Pick<Map<K, V[]>, 'get' | 'set'>,\n\tfrom: ReadonlyMap<K, V[]>\n): Pick<Map<K, V[]>, 'get' | 'set'> {\n\tfor (const [key, value] of from.entries()) {\n\t\tconst entry = to.get(key);\n\t\tif (entry !== undefined) {\n\t\t\tentry.push(...value);\n\t\t} else {\n\t\t\tto.set(key, [...value]);\n\t\t}\n\t}\n\treturn to;\n}\n\ninterface AllocateIds {\n\ttype: 'allocateIds';\n\tclient: Client;\n\tnumIds: number;\n\toverrides: { [index: number]: string };\n}\n\ninterface DeliverOperations {\n\ttype: 'deliverOperations';\n\tclient: DestinationClient;\n}\n\ninterface ChangeCapacity {\n\ttype: 'changeCapacity';\n\tnewSize: number;\n}\n\ninterface GenerateUnifyingIds {\n\ttype: 'generateUnifyingIds';\n\tclientA: Client;\n\tclientB: Client;\n\tuuid: string;\n}\n\n// Represents intent to go offline then resume.\ninterface Reconnect {\n\ttype: 'reconnect';\n\tclient: Client;\n}\n\ninterface Validate {\n\ttype: 'validate';\n}\n\ntype Operation = AllocateIds | DeliverOperations | ChangeCapacity | GenerateUnifyingIds | Reconnect | Validate;\n\ninterface FuzzTestState extends BaseFuzzTestState {\n\tnetwork: IdCompressorTestNetwork;\n\tactiveClients: Client[];\n\tselectableClients: Client[];\n\tclusterSize: number;\n}\n\nexport interface OperationGenerationConfig {\n\t/** whether or not the fuzz actions will generate override UUIDs */\n\tincludeOverrides: boolean;\n\t/** maximum cluster size of the network. Default: 25 */\n\tmaxClusterSize?: number;\n\t/** Number of ops between validation ops. Default: 200 */\n\tvalidateInterval?: number;\n}\n\nconst defaultOptions = {\n\tincludeOverrides: false,\n\tmaxClusterSize: 25,\n\tvalidateInterval: 200,\n};\n\nexport function makeOpGenerator(options: OperationGenerationConfig): Generator<Operation, FuzzTestState> {\n\tconst { includeOverrides, maxClusterSize, validateInterval } = { ...defaultOptions, ...options };\n\n\tfunction allocateIdsGenerator({ activeClients, clusterSize, random }: FuzzTestState): AllocateIds {\n\t\tconst client = random.pick(activeClients);\n\t\tconst maxIdsPerUsage = clusterSize * 2;\n\t\tconst numIds = Math.floor(random.real(0, 1) ** 3 * maxIdsPerUsage) + 1;\n\t\tconst overrides: AllocateIds['overrides'] = {};\n\t\tif (includeOverrides && random.bool(1 / 4)) {\n\t\t\tfor (let j = 0; j < numIds; j++) {\n\t\t\t\tif (random.bool(1 / 3)) {\n\t\t\t\t\toverrides[j] = random.uuid4();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: 'allocateIds',\n\t\t\tclient,\n\t\t\tnumIds,\n\t\t\toverrides,\n\t\t};\n\t}\n\n\tfunction changeCapacityGenerator({ random }: FuzzTestState): ChangeCapacity {\n\t\treturn {\n\t\t\ttype: 'changeCapacity',\n\t\t\tnewSize: Math.min(Math.floor(random.real(0, 1) ** 2 * maxClusterSize) + 1, maxClusterSize),\n\t\t};\n\t}\n\n\tfunction deliverOperationsGenerator({ random, selectableClients }: FuzzTestState): DeliverOperations {\n\t\treturn {\n\t\t\ttype: 'deliverOperations',\n\t\t\tclient: random.pick([...selectableClients, MetaClient.All]),\n\t\t};\n\t}\n\n\tfunction generateUnifyingIdsGenerator({ activeClients, random }: FuzzTestState): GenerateUnifyingIds {\n\t\tconst clientA = random.pick(activeClients);\n\t\tconst clientB = random.pick(activeClients.filter((c) => c !== clientA));\n\t\treturn { type: 'generateUnifyingIds', clientA, clientB, uuid: random.uuid4() };\n\t}\n\n\tfunction reconnectGenerator({ activeClients, random }: FuzzTestState): Reconnect {\n\t\treturn { type: 'reconnect', client: random.pick(activeClients) };\n\t}\n\n\treturn interleave(\n\t\tcreateWeightedGenerator<Operation, FuzzTestState>([\n\t\t\t[changeCapacityGenerator, 1],\n\t\t\t[allocateIdsGenerator, 8],\n\t\t\t[deliverOperationsGenerator, 4],\n\t\t\t[generateUnifyingIdsGenerator, 1],\n\t\t\t[reconnectGenerator, 1],\n\t\t]),\n\t\ttake(1, repeat<Operation, FuzzTestState>({ type: 'validate' })),\n\t\tvalidateInterval\n\t);\n}\n\n/**\n * Performs random actions on a test network.\n * @param generator - the generator used to provide operations\n * @param network - the test network to test\n * @param seed - the seed for the random generation of the fuzz actions\n * @param observerClient - if provided, this client will never generate local ids\n * @param synchronizeAtEnd - if provided, all client will have all operations delivered from the server at the end of the test\n * @param validator - if provided, this callback will be invoked periodically during the fuzz test.\n */\nexport function performFuzzActions(\n\tgenerator: Generator<Operation, FuzzTestState>,\n\tnetwork: IdCompressorTestNetwork,\n\tseed: number,\n\tobserverClient?: Client,\n\tsynchronizeAtEnd: boolean = true,\n\tvalidator?: (network: IdCompressorTestNetwork) => void,\n\tsaveInfo?: SaveInfo\n): void {\n\tconst random = makeRandom(seed);\n\tconst selectableClients: Client[] = network.getTargetCompressors(MetaClient.All).map(([client]) => client);\n\n\tconst initialState: FuzzTestState = {\n\t\trandom,\n\t\tnetwork,\n\t\tactiveClients: selectableClients.filter((c) => c !== observerClient),\n\t\tselectableClients,\n\t\tclusterSize: network.initialClusterSize,\n\t};\n\n\tperformFuzzActionsBase(\n\t\tgenerator,\n\t\t{\n\t\t\tallocateIds: (state, { client, numIds, overrides }) => {\n\t\t\t\tnetwork.allocateAndSendIds(client, numIds, overrides);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tchangeCapacity: (state, op) => {\n\t\t\t\tnetwork.enqueueCapacityChange(op.newSize);\n\t\t\t\treturn { ...state, clusterSize: op.newSize };\n\t\t\t},\n\t\t\tdeliverOperations: (state, op) => {\n\t\t\t\tnetwork.deliverOperations(op.client);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tgenerateUnifyingIds: (state, { clientA, clientB, uuid }) => {\n\t\t\t\tnetwork.allocateAndSendIds(clientA, 1, { 0: uuid });\n\t\t\t\tnetwork.allocateAndSendIds(clientB, 1, { 0: uuid });\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\treconnect: (state, { client }) => {\n\t\t\t\tnetwork.goOfflineThenResume(client);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tvalidate: (state) => {\n\t\t\t\tnetwork.deliverOperations(DestinationClient.All);\n\t\t\t\tvalidator?.(network);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t},\n\t\tinitialState,\n\t\tsaveInfo\n\t);\n\n\tif (synchronizeAtEnd) {\n\t\tnetwork.deliverOperations(DestinationClient.All);\n\t\tvalidator?.(network);\n\t}\n}\n\n/**\n * Converts the supplied integer to a uuid.\n */\nexport function integerToStableId(num: number | bigint): StableId {\n\tconst bigintNum = BigInt(num);\n\tconst upper = bigintNum >> BigInt(74);\n\tconst middle = (bigintNum & (BigInt(0xfff) << BigInt(62))) >> BigInt(62);\n\tconst lower = bigintNum & BigInt('0x3fffffffffffffff');\n\tconst upperString = padToLength(upper.toString(16), '0', 12);\n\tconst middleString = `4${padToLength(middle.toString(16), '0', 3)}`;\n\tconst lowerString = padToLength((BigInt('0x8000000000000000') | BigInt(lower)).toString(16), '0', 16);\n\tconst uuid = upperString + middleString + lowerString;\n\treturn assertIsStableId(\n\t\t`${uuid.substr(0, 8)}-${uuid.substr(8, 4)}-${uuid.substr(12, 4)}-${uuid.substr(16, 4)}-${uuid.substr(20)}`\n\t);\n}\n\n/**\n * Pads the strings to a length of 32 with zeroes.\n */\nexport function padToUuidLength(str: string): string {\n\treturn padToLength(str, '0', 32);\n}\n\nfunction padToLength(str: string, char: string, length: number): string {\n\treturn char.repeat(length - str.length) + str;\n}\n\n/**\n * Helper to generate a fixed number of IDs.\n */\nexport function generateCompressedIds(compressor: IdCompressor, count: number): SessionSpaceCompressedId[] {\n\tconst ids: SessionSpaceCompressedId[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tids.push(compressor.generateCompressedId());\n\t}\n\treturn ids;\n}\n"]}
1
+ {"version":3,"file":"IdCompressorTestUtilities.js","sourceRoot":"","sources":["../../../src/test/utilities/IdCompressorTestUtilities.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\n/* eslint-disable no-bitwise */\n\nimport { expect } from 'chai';\nimport {\n\tGenerator,\n\tcreateWeightedGenerator,\n\tinterleave,\n\tmakeRandom,\n\tperformFuzzActions as performFuzzActionsBase,\n\trepeat,\n\tSaveInfo,\n\ttake,\n\tBaseFuzzTestState,\n} from '@fluid-internal/stochastic-test-utils';\nimport { assert, assertNotUndefined, ClosedMap, fail, getOrCreate } from '../../Common';\nimport { IdCompressor, isLocalId } from '../../id-compressor/IdCompressor';\nimport {\n\tcreateSessionId,\n\tensureSessionUuid,\n\tNumericUuid,\n\tnumericUuidFromStableId,\n\tstableIdFromNumericUuid,\n} from '../../id-compressor/NumericUuid';\nimport {\n\tFinalCompressedId,\n\tSessionId,\n\tStableId,\n\tSessionSpaceCompressedId,\n\tAttributionId,\n\tOpSpaceCompressedId,\n} from '../../Identifiers';\nimport { getIds } from '../../id-compressor/IdRange';\nimport type {\n\tIdCreationRange,\n\tSerializedIdCompressorWithOngoingSession,\n\tSerializedIdCompressorWithNoSession,\n} from '../../id-compressor';\nimport { assertIsStableId, assertIsUuidString } from '../../UuidUtilities';\nimport { expectDefined } from './TestCommon';\n\n/** Identifies a compressor in a network */\nexport enum Client {\n\tClient1 = 'Client1',\n\tClient2 = 'Client2',\n\tClient3 = 'Client3',\n}\n\n/** Identifies a compressor with respect to a specific operation */\nexport enum SemanticClient {\n\tLocalClient = 'LocalClient',\n}\n\n/** Identifies categories of compressors */\nexport enum MetaClient {\n\tAll = 'All',\n}\n\n/**\n * Used to attribute actions to clients in a distributed collaboration session.\n * `Local` implies a local and unsequenced operation. All others imply sequenced operations.\n */\nexport type OriginatingClient = Client | SemanticClient;\nexport const OriginatingClient = { ...Client, ...SemanticClient };\n\n/** Identifies a compressor to which to send an operation */\nexport type DestinationClient = Client | MetaClient;\nexport const DestinationClient = { ...Client, ...MetaClient };\n\n/**\n * Creates a new compressor with the supplied cluster capacity.\n */\nexport function createCompressor(client: Client, clusterCapacity = 5, attributionId?: AttributionId): IdCompressor {\n\tconst compressor = new IdCompressor(sessionIds.get(client), 1024, attributionId);\n\tcompressor.clusterCapacity = clusterCapacity;\n\treturn compressor;\n}\n\n/**\n * A closed map from NamedClient to T.\n */\nexport type ClientMap<T> = ClosedMap<Client, T>;\n\nfunction makeSessionIds(): ClientMap<SessionId> {\n\tconst stableIds = new Map<Client, SessionId>();\n\tconst clients = Object.values(Client);\n\tfor (let i = 0; i < clients.length; i++) {\n\t\t// Place session uuids roughly in the middle of uuid space to increase odds of encountering interesting\n\t\t// orderings in sorted collections\n\t\tconst sessionId = ensureSessionUuid(assertIsStableId(`88888888-8888-4888-b${i}88-888888888888`));\n\t\tstableIds.set(clients[i], sessionId);\n\t}\n\treturn stableIds as ClientMap<SessionId>;\n}\n\n/**\n * An array of session ID strings corresponding to all non-local `Client` entries.\n */\nexport const sessionIds = makeSessionIds();\n\n/**\n * An array of session uuids corresponding to all non-local `Client` entries.\n */\nexport const sessionNumericUuids = new Map(\n\t[...sessionIds.entries()].map(([client, sessionId]) => {\n\t\treturn [client, numericUuidFromStableId(sessionId)];\n\t})\n) as ClientMap<NumericUuid>;\n\nexport const attributionIds = new Map(\n\tObject.values(Client).map((c, i) => [\n\t\tc,\n\t\tassertIsUuidString(`00000000-0000-0000-0000-${(i + 1).toString(16).padStart(12, '0')}`),\n\t])\n) as ClientMap<AttributionId>;\n\n/** An immutable view of an `IdCompressor` */\nexport interface ReadonlyIdCompressor\n\textends Omit<\n\t\tIdCompressor,\n\t\t'generateCompressedId' | 'generateCompressedIdRange' | 'takeNextCreationRange' | 'finalizeCreationRange'\n\t> {\n\treadonly clusterCapacity: number;\n}\n\n/** Information about a generated ID in a network to be validated by tests */\nexport interface TestIdData {\n\treadonly id: SessionSpaceCompressedId;\n\treadonly originatingClient: Client;\n\treadonly sessionId: SessionId;\n\treadonly sessionNumericUuid: NumericUuid;\n\treadonly expectedOverride: string | undefined;\n\treadonly isSequenced: boolean;\n}\n\n/**\n * Simulates a network of ID compressors.\n * Not suitable for performance testing.\n */\nexport class IdCompressorTestNetwork {\n\t/** The compressors used in this network */\n\tprivate readonly compressors: ClientMap<IdCompressor>;\n\t/** The log of operations seen by the server so far. Append-only. */\n\tprivate readonly serverOperations: (\n\t\t| [creationRange: IdCreationRange, opSpaceIds: OpSpaceCompressedId[], clientFrom: Client]\n\t\t| number\n\t)[] = [];\n\t/** An index into `serverOperations` for each client which represents how many operations have been delivered to that client */\n\tprivate readonly clientProgress: ClientMap<number>;\n\t/** All ids (local and sequenced) that a client has created or received, in order. */\n\tprivate readonly idLogs: ClientMap<TestIdData[]>;\n\t/** All ids that a client has received from the server, in order. */\n\tprivate readonly sequencedIdLogs: ClientMap<TestIdData[]>;\n\n\tpublic constructor(\n\t\tpublic readonly initialClusterSize = 5,\n\t\tprivate readonly onIdReceived?: (network: IdCompressorTestNetwork, clientTo: Client, ids: TestIdData[]) => void\n\t) {\n\t\tconst compressors = new Map<Client, IdCompressor>();\n\t\tconst clientProgress = new Map<Client, number>();\n\t\tconst clientIds = new Map<Client, TestIdData[]>();\n\t\tconst clientSequencedIds = new Map<Client, TestIdData[]>();\n\t\tfor (const client of Object.values(Client)) {\n\t\t\tconst compressor = createCompressor(client, initialClusterSize, attributionIds.get(client));\n\t\t\tcompressors.set(client, compressor);\n\t\t\tclientProgress.set(client, 0);\n\t\t\tclientIds.set(client, []);\n\t\t\tclientSequencedIds.set(client, []);\n\t\t}\n\t\tthis.compressors = compressors as ClientMap<IdCompressor>;\n\t\tthis.clientProgress = clientProgress as ClientMap<number>;\n\t\tthis.idLogs = clientIds as ClientMap<TestIdData[]>;\n\t\tthis.sequencedIdLogs = clientSequencedIds as ClientMap<TestIdData[]>;\n\t}\n\n\t/**\n\t * Returns the number of undelivered operations for the given client that are in flight in the network.\n\t */\n\tpublic getPendingOperations(destination: Client): number {\n\t\treturn this.serverOperations.length - this.clientProgress.get(destination);\n\t}\n\n\t/**\n\t * Returns an immutable handle to a compressor in the network.\n\t */\n\tpublic getCompressor(client: Client): ReadonlyIdCompressor {\n\t\tconst compressors = this.compressors;\n\t\tconst handler = {\n\t\t\tget(_, property) {\n\t\t\t\tconst compressor = compressors.get(client);\n\t\t\t\treturn compressor[property];\n\t\t\t},\n\t\t\tset(_, property, value): boolean {\n\t\t\t\tconst compressor = compressors.get(client);\n\t\t\t\tcompressor[property] = value;\n\t\t\t\treturn true;\n\t\t\t},\n\t\t};\n\t\treturn new Proxy<IdCompressor>({} as unknown as IdCompressor, handler);\n\t}\n\n\t/**\n\t * Returns a mutable handle to a compressor in the network. Use of mutation methods will break the network invariants and\n\t * should only be used if the network will not be used again.\n\t */\n\tpublic getCompressorUnsafe(client: Client): IdCompressor {\n\t\treturn this.getCompressor(client) as IdCompressor;\n\t}\n\n\t/**\n\t * Returns a mutable handle to a compressor in the network. Use of mutation methods will break the network invariants and\n\t * should only be used if the network will not be used again. Additionally, the returned compressor will be invalidated/unusable\n\t * if any network operations cause it to be regenerated (serialization/deserialization, etc.).\n\t */\n\tpublic getCompressorUnsafeNoProxy(client: Client): IdCompressor {\n\t\treturn this.compressors.get(client);\n\t}\n\n\t/**\n\t * Returns data for all IDs created and received by this client, including ack's of their own (i.e. their own IDs will appear twice)\n\t */\n\tpublic getIdLog(client: Client): readonly TestIdData[] {\n\t\treturn this.idLogs.get(client);\n\t}\n\n\t/**\n\t * Returns data for all IDs received by this client, including ack's of their own.\n\t */\n\tpublic getSequencedIdLog(client: Client): readonly TestIdData[] {\n\t\treturn this.sequencedIdLogs.get(client);\n\t}\n\n\t/**\n\t * Get all compressors for the given destination\n\t */\n\tpublic getTargetCompressors(clientTo: DestinationClient): [Client, IdCompressor][] {\n\t\treturn clientTo === MetaClient.All\n\t\t\t? [...this.compressors.entries()]\n\t\t\t: ([[clientTo, this.getCompressor(clientTo)]] as [Client, IdCompressor][]);\n\t}\n\n\t/**\n\t * Submit a capacity change operation to the network. It will not take effect immediately but will be processed in sequence order.\n\t */\n\tpublic enqueueCapacityChange(newClusterCapacity: number): void {\n\t\tthis.serverOperations.push(newClusterCapacity);\n\t}\n\n\tprivate addNewId(\n\t\tclient: Client,\n\t\tid: SessionSpaceCompressedId,\n\t\texpectedOverride: string | undefined,\n\t\toriginatingClient: Client,\n\t\tisSequenced: boolean\n\t): void {\n\t\tconst idData = {\n\t\t\tid,\n\t\t\toriginatingClient,\n\t\t\tsessionId: sessionIds.get(originatingClient),\n\t\t\tsessionNumericUuid: sessionNumericUuids.get(originatingClient),\n\t\t\texpectedOverride,\n\t\t\tisSequenced,\n\t\t};\n\t\tconst clientIds = this.idLogs.get(client);\n\t\tclientIds.push(idData);\n\t\tif (isSequenced) {\n\t\t\tconst sequencedIds = this.sequencedIdLogs.get(client);\n\t\t\tsequencedIds.push(idData);\n\t\t}\n\t\tthis.onIdReceived?.(this, client, clientIds);\n\t}\n\n\t/**\n\t * Allocates a new range of local IDs and enqueues them for future delivery via a `testIdDelivery` action.\n\t * Calls to this method determine the total order of delivery, regardless of when `deliverOperations` is called.\n\t */\n\tpublic allocateAndSendIds(client: Client, numIds: number): OpSpaceCompressedId[];\n\n\t/**\n\t * Allocates a new range of local IDs and enqueues them for future delivery via a `testIdDelivery` action.\n\t * Calls to this method determine the total order of delivery, regardless of when `deliverOperations` is called.\n\t */\n\tpublic allocateAndSendIds(client: Client, numIds: number, overrides: { [index: number]: string }): IdCreationRange;\n\n\tpublic allocateAndSendIds(\n\t\tclient: Client,\n\t\tnumIds: number,\n\t\toverrides: { [index: number]: string } = {}\n\t): OpSpaceCompressedId[] | IdCreationRange {\n\t\tassert(numIds > 0, 'Must allocate a non-zero number of IDs');\n\t\tconst compressor = this.compressors.get(client);\n\t\tlet nextIdIndex = 0;\n\t\tconst opSpaceIds: OpSpaceCompressedId[] = [];\n\t\tfor (const [overrideIndex, uuid] of Object.entries(overrides)\n\t\t\t.map(([id, uuid]) => [Number.parseInt(id, 10), uuid] as [number, string])\n\t\t\t.sort(([a], [b]) => a - b)) {\n\t\t\twhile (nextIdIndex < overrideIndex) {\n\t\t\t\tconst newId = compressor.generateCompressedId();\n\t\t\t\topSpaceIds.push(compressor.normalizeToOpSpace(newId));\n\t\t\t\tthis.addNewId(client, newId, undefined, client, false);\n\t\t\t\tnextIdIndex += 1;\n\t\t\t}\n\t\t\tconst newOverrideId = compressor.generateCompressedId(uuid);\n\t\t\topSpaceIds.push(compressor.normalizeToOpSpace(newOverrideId));\n\t\t\tthis.addNewId(client, newOverrideId, uuid, client, false);\n\t\t\tnextIdIndex += 1;\n\t\t}\n\t\tconst numTrailingIds = numIds - nextIdIndex;\n\t\tif (numTrailingIds > 0) {\n\t\t\tconst sessionSpaceIds = generateCompressedIds(compressor, numTrailingIds);\n\t\t\tfor (let i = 0; i < numTrailingIds; i++) {\n\t\t\t\tthis.addNewId(client, sessionSpaceIds[i], undefined, client, false);\n\t\t\t}\n\t\t\tsessionSpaceIds.forEach((id) => opSpaceIds.push(compressor.normalizeToOpSpace(id)));\n\t\t}\n\t\tconst creationRange = compressor.takeNextCreationRange();\n\t\tthis.serverOperations.push([creationRange, opSpaceIds, client]);\n\t\treturn nextIdIndex === 0 ? opSpaceIds : creationRange;\n\t}\n\n\t/**\n\t * Delivers all undelivered ID ranges and cluster capacity changes from the server to the target clients.\n\t */\n\tpublic deliverOperations(clientTakingDelivery: Client, opsToDeliver?: number);\n\n\t/**\n\t * Delivers all undelivered ID ranges and cluster capacity changes from the server to the target clients.\n\t */\n\tpublic deliverOperations(clientTakingDelivery: DestinationClient);\n\n\t/**\n\t * Delivers all undelivered ID ranges and cluster capacity changes from the server to the target clients.\n\t */\n\tpublic deliverOperations(clientTakingDelivery: DestinationClient, opsToDeliver?: number) {\n\t\tlet opIndexBound: number;\n\t\tif (clientTakingDelivery === DestinationClient.All) {\n\t\t\tassert(opsToDeliver === undefined);\n\t\t\topIndexBound = this.serverOperations.length;\n\t\t} else {\n\t\t\topIndexBound =\n\t\t\t\topsToDeliver !== undefined\n\t\t\t\t\t? this.clientProgress.get(clientTakingDelivery) + opsToDeliver\n\t\t\t\t\t: this.serverOperations.length;\n\t\t}\n\t\tfor (const [clientTo, compressorTo] of this.getTargetCompressors(clientTakingDelivery)) {\n\t\t\tfor (let i = this.clientProgress.get(clientTo); i < opIndexBound; i++) {\n\t\t\t\tconst operation = this.serverOperations[i];\n\t\t\t\tif (typeof operation === 'number') {\n\t\t\t\t\tcompressorTo.clusterCapacity = operation;\n\t\t\t\t} else {\n\t\t\t\t\tconst [range, opSpaceIds, clientFrom] = operation;\n\t\t\t\t\tcompressorTo.finalizeCreationRange(range);\n\n\t\t\t\t\tconst ids = getIds(range);\n\t\t\t\t\tif (ids !== undefined) {\n\t\t\t\t\t\tlet overrideIndex = 0;\n\t\t\t\t\t\tconst overrides = ids.overrides;\n\t\t\t\t\t\tfor (const id of opSpaceIds) {\n\t\t\t\t\t\t\tlet override: string | undefined;\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\toverrides !== undefined &&\n\t\t\t\t\t\t\t\toverrideIndex < overrides.length &&\n\t\t\t\t\t\t\t\tid === overrides[overrideIndex][0]\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\toverride = overrides[overrideIndex][1];\n\t\t\t\t\t\t\t\toverrideIndex++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst sessionSpaceId = compressorTo.normalizeToSessionSpace(id, range.sessionId);\n\t\t\t\t\t\t\tthis.addNewId(clientTo, sessionSpaceId, override, clientFrom, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tassert(overrideIndex === (overrides?.length ?? 0));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.clientProgress.set(clientTo, opIndexBound);\n\t\t}\n\t}\n\n\t/**\n\t * Simulate a client disconnecting (and serializing), then reconnecting (and deserializing)\n\t */\n\tpublic goOfflineThenResume(client: Client): void {\n\t\tconst compressor = this.compressors.get(client);\n\t\tconst [_, resumedCompressor] = roundtrip(compressor, true);\n\t\tthis.compressors.set(client, resumedCompressor);\n\t}\n\n\t/**\n\t * Ensure general validity of the network state. Useful for calling periodically or at the end of test scenarios.\n\t */\n\tpublic assertNetworkState(): void {\n\t\tconst sequencedLogs = Object.values(Client).map(\n\t\t\t(client) => [this.compressors.get(client), this.getSequencedIdLog(client)] as const\n\t\t);\n\n\t\t// First, ensure all clients each generated a unique ID for each of their own calls to generate.\n\t\tfor (const [compressor, ids] of sequencedLogs) {\n\t\t\tconst uuids = new Set<StableId | string>();\n\t\t\tfor (const idData of ids) {\n\t\t\t\tconst uuid = compressor.decompress(idData.id);\n\t\t\t\texpect(!uuids.has(uuid), 'Duplicate UUID generated.');\n\t\t\t\tuuids.add(uuid);\n\t\t\t}\n\t\t}\n\n\t\tconst maxLogLength = sequencedLogs.map(([_, data]) => data.length).reduce((p, n) => Math.max(p, n));\n\n\t\tfunction getNextLogWithEntryAt(logsIndex: number, entryIndex: number): number | undefined {\n\t\t\tfor (let i = logsIndex; i < sequencedLogs.length; i++) {\n\t\t\t\tconst log = sequencedLogs[i];\n\t\t\t\tif (log[1].length > entryIndex) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst uuids = new Set<string>();\n\t\tconst finalIds = new Set<FinalCompressedId>();\n\t\tconst idIndicesAggregator = new Map<Client, number>();\n\n\t\tfunction* getLogIndices(\n\t\t\tcolumnIndex: number\n\t\t): Iterable<\n\t\t\t[\n\t\t\t\tcurrent: [compressor: IdCompressor, idData: TestIdData],\n\t\t\t\tnext?: [compressor: IdCompressor, idData: TestIdData]\n\t\t\t]\n\t\t> {\n\t\t\tlet current = getNextLogWithEntryAt(0, columnIndex);\n\t\t\twhile (current !== undefined) {\n\t\t\t\tconst next = getNextLogWithEntryAt(current + 1, columnIndex);\n\t\t\t\tconst [compressor, log] = sequencedLogs[current];\n\t\t\t\tif (next === undefined) {\n\t\t\t\t\tyield [[compressor, log[columnIndex]]];\n\t\t\t\t} else {\n\t\t\t\t\tconst [compressorNext, logNext] = sequencedLogs[next];\n\t\t\t\t\tyield [\n\t\t\t\t\t\t[compressor, log[columnIndex]],\n\t\t\t\t\t\t[compressorNext, logNext[columnIndex]],\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = 0; i < maxLogLength; i++) {\n\t\t\tconst creator: [creator: Client, override?: string][] = [];\n\t\t\tlet originatingClient: Client | undefined;\n\t\t\tlet localCount = 0;\n\t\t\tlet rowCount = 0;\n\t\t\tfor (const [current, next] of getLogIndices(i)) {\n\t\t\t\tconst [compressorA, idDataA] = current;\n\t\t\t\tconst sessionSpaceIdA = idDataA.id;\n\t\t\t\tconst idIndex = getOrCreate(idIndicesAggregator, idDataA.originatingClient, () => 0);\n\t\t\t\toriginatingClient ??= idDataA.originatingClient;\n\t\t\t\tassert(\n\t\t\t\t\tidDataA.originatingClient === originatingClient,\n\t\t\t\t\t'Test infra gave wrong originating client to TestIdData'\n\t\t\t\t);\n\t\t\t\tconst attributionA = compressorA.attributeId(idDataA.id);\n\t\t\t\tif (attributionA !== attributionIds.get(idDataA.originatingClient)) {\n\t\t\t\t\t// Unification\n\t\t\t\t\texpectDefined(idDataA.expectedOverride);\n\t\t\t\t}\n\n\t\t\t\t// Only one client should have this ID as local in its session space, as only one client could have created this ID\n\t\t\t\tif (isLocalId(sessionSpaceIdA)) {\n\t\t\t\t\tlocalCount++;\n\t\t\t\t\texpect(idDataA.sessionId).to.equal(this.compressors.get(originatingClient).localSessionId);\n\t\t\t\t\texpect(creator.length === 0 || creator[creator.length - 1][1] === idDataA.expectedOverride).to.be\n\t\t\t\t\t\t.true;\n\t\t\t\t\tcreator.push([originatingClient, idDataA.expectedOverride]);\n\t\t\t\t}\n\n\t\t\t\tconst uuidASessionSpace = compressorA.decompress(sessionSpaceIdA);\n\t\t\t\tif (idDataA.expectedOverride !== undefined) {\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(idDataA.expectedOverride);\n\t\t\t\t} else {\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(stableIdFromNumericUuid(idDataA.sessionNumericUuid, idIndex));\n\t\t\t\t}\n\t\t\t\texpect(compressorA.recompress(uuidASessionSpace)).to.equal(sessionSpaceIdA);\n\t\t\t\tuuids.add(uuidASessionSpace);\n\t\t\t\tconst opSpaceIdA = compressorA.normalizeToOpSpace(sessionSpaceIdA);\n\t\t\t\tif (isLocalId(opSpaceIdA)) {\n\t\t\t\t\texpect.fail('IDs should have been finalized.');\n\t\t\t\t\tfail();\n\t\t\t\t}\n\t\t\t\texpect(compressorA.normalizeToSessionSpace(opSpaceIdA, compressorA.localSessionId)).equals(\n\t\t\t\t\tsessionSpaceIdA\n\t\t\t\t);\n\t\t\t\tfinalIds.add(opSpaceIdA);\n\t\t\t\tconst uuidAOpSpace = compressorA.decompress(opSpaceIdA);\n\n\t\t\t\texpect(uuidASessionSpace).to.equal(uuidAOpSpace);\n\n\t\t\t\tif (next !== undefined) {\n\t\t\t\t\tconst [compressorB, idDataB] = next;\n\t\t\t\t\tconst sessionSpaceIdB = idDataB.id;\n\n\t\t\t\t\tconst uuidBSessionSpace = compressorB.decompress(sessionSpaceIdB);\n\t\t\t\t\texpect(uuidASessionSpace).to.equal(uuidBSessionSpace);\n\t\t\t\t\tconst opSpaceIdB = compressorB.normalizeToOpSpace(sessionSpaceIdB);\n\t\t\t\t\tif (opSpaceIdA !== opSpaceIdB) {\n\t\t\t\t\t\tcompressorB.normalizeToOpSpace(sessionSpaceIdB);\n\t\t\t\t\t\tcompressorA.normalizeToOpSpace(sessionSpaceIdA);\n\t\t\t\t\t}\n\t\t\t\t\texpect(opSpaceIdA).to.equal(opSpaceIdB);\n\t\t\t\t\tif (isLocalId(opSpaceIdB)) {\n\t\t\t\t\t\tfail('IDs should have been finalized.');\n\t\t\t\t\t}\n\t\t\t\t\tconst uuidBOpSpace = compressorB.decompress(opSpaceIdB);\n\t\t\t\t\texpect(uuidAOpSpace).to.equal(uuidBOpSpace);\n\t\t\t\t}\n\n\t\t\t\trowCount += 1;\n\t\t\t}\n\n\t\t\t// A local count === 0 indicates the ID was created as an eager final, and thus cannot have had an\n\t\t\t// override to unify.\n\t\t\tif (rowCount === this.sequencedIdLogs.size && localCount <= 1) {\n\t\t\t\texpect(localCount).to.lessThanOrEqual(1);\n\t\t\t\tfor (const [[compressor, { id, originatingClient }]] of getLogIndices(i)) {\n\t\t\t\t\texpect(compressor.attributeId(id)).to.equal(attributionIds.get(originatingClient));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texpect(uuids.size).to.equal(finalIds.size);\n\t\t\tassert(originatingClient !== undefined);\n\t\t\tidIndicesAggregator.set(\n\t\t\t\toriginatingClient,\n\t\t\t\tassertNotUndefined(idIndicesAggregator.get(originatingClient)) + 1\n\t\t\t);\n\t\t}\n\n\t\tfor (const [compressor] of sequencedLogs) {\n\t\t\texpectSerializes(compressor);\n\t\t}\n\t}\n}\n\n/**\n * Roundtrips the supplied compressor through serialization and deserialization.\n */\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: true\n): [SerializedIdCompressorWithOngoingSession, IdCompressor];\n\n/**\n * Roundtrips the supplied compressor through serialization and deserialization.\n */\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: false\n): [SerializedIdCompressorWithNoSession, IdCompressor];\n\nexport function roundtrip(\n\tcompressor: ReadonlyIdCompressor,\n\twithSession: boolean\n): [SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession, IdCompressor] {\n\tif (withSession) {\n\t\tconst serialized = compressor.serialize(withSession);\n\t\treturn [serialized, IdCompressor.deserialize(serialized)];\n\t}\n\n\tconst nonLocalSerialized = compressor.serialize(withSession);\n\treturn [nonLocalSerialized, IdCompressor.deserialize(nonLocalSerialized, createSessionId())];\n}\n\n/**\n * Asserts that the supplied compressor correctly roundtrips through serialization/deserialization.\n */\nexport function expectSerializes(\n\tcompressor: ReadonlyIdCompressor\n): [SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession] {\n\tfunction expectSerializes(\n\t\twithSession: boolean\n\t): SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession {\n\t\tlet serialized: SerializedIdCompressorWithOngoingSession | SerializedIdCompressorWithNoSession;\n\t\tlet deserialized: IdCompressor;\n\t\tif (withSession) {\n\t\t\t[serialized, deserialized] = roundtrip(compressor, true);\n\t\t} else {\n\t\t\t[serialized, deserialized] = roundtrip(compressor, false);\n\t\t}\n\t\tconst chainCount: number[] = [];\n\t\tfor (let i = 0; i < serialized.sessions.length; i++) {\n\t\t\tchainCount[i] = 0;\n\t\t}\n\t\tconst chainProcessed: number[] = [...chainCount];\n\n\t\tfor (const cluster of serialized.clusters) {\n\t\t\tconst [sessionIndex] = cluster;\n\t\t\texpect(sessionIndex < serialized.sessions.length).to.be.true;\n\t\t\tchainCount[sessionIndex]++;\n\t\t}\n\n\t\tfor (const cluster of serialized.clusters) {\n\t\t\tconst [sessionIndex, capacity, maybeSize] = cluster;\n\t\t\tconst chainIndex = chainProcessed[sessionIndex];\n\t\t\tif (chainIndex < chainCount[sessionIndex] - 1) {\n\t\t\t\texpect(typeof maybeSize !== 'number').to.be.true;\n\t\t\t} else {\n\t\t\t\texpect(maybeSize === undefined || typeof maybeSize !== 'number' || maybeSize < capacity).to.be.true;\n\t\t\t}\n\t\t\tchainProcessed[sessionIndex]++;\n\t\t}\n\n\t\texpect(compressor.equals(deserialized, withSession)).to.be.true;\n\t\treturn serialized;\n\t}\n\n\treturn [\n\t\texpectSerializes(false) as SerializedIdCompressorWithNoSession,\n\t\texpectSerializes(true) as SerializedIdCompressorWithOngoingSession,\n\t];\n}\n\n/**\n * Merges 'from' into 'to', and returns 'to'.\n */\nexport function mergeArrayMaps<K, V>(\n\tto: Pick<Map<K, V[]>, 'get' | 'set'>,\n\tfrom: ReadonlyMap<K, V[]>\n): Pick<Map<K, V[]>, 'get' | 'set'> {\n\tfor (const [key, value] of from.entries()) {\n\t\tconst entry = to.get(key);\n\t\tif (entry !== undefined) {\n\t\t\tentry.push(...value);\n\t\t} else {\n\t\t\tto.set(key, [...value]);\n\t\t}\n\t}\n\treturn to;\n}\n\ninterface AllocateIds {\n\ttype: 'allocateIds';\n\tclient: Client;\n\tnumIds: number;\n\toverrides: { [index: number]: string };\n}\n\ninterface DeliverAllOperations {\n\ttype: 'deliverAllOperations';\n}\n\ninterface DeliverSomeOperations {\n\ttype: 'deliverSomeOperations';\n\tclient: Client;\n\tcount: number;\n}\n\ninterface ChangeCapacity {\n\ttype: 'changeCapacity';\n\tnewSize: number;\n}\n\ninterface GenerateUnifyingIds {\n\ttype: 'generateUnifyingIds';\n\tclientA: Client;\n\tclientB: Client;\n\tuuid: string;\n}\n\n// Represents intent to go offline then resume.\ninterface Reconnect {\n\ttype: 'reconnect';\n\tclient: Client;\n}\n\ninterface Validate {\n\ttype: 'validate';\n}\n\ntype Operation =\n\t| AllocateIds\n\t| DeliverSomeOperations\n\t| DeliverAllOperations\n\t| ChangeCapacity\n\t| GenerateUnifyingIds\n\t| Reconnect\n\t| Validate;\n\ninterface FuzzTestState extends BaseFuzzTestState {\n\tnetwork: IdCompressorTestNetwork;\n\tactiveClients: Client[];\n\tselectableClients: Client[];\n\tclusterSize: number;\n}\n\nexport interface OperationGenerationConfig {\n\t/** whether or not the fuzz actions will generate override UUIDs */\n\tincludeOverrides: boolean;\n\t/** maximum cluster size of the network. Default: 25 */\n\tmaxClusterSize?: number;\n\t/** Number of ops between validation ops. Default: 200 */\n\tvalidateInterval?: number;\n}\n\nconst defaultOptions = {\n\tincludeOverrides: false,\n\tmaxClusterSize: 25,\n\tvalidateInterval: 200,\n};\n\nexport function makeOpGenerator(options: OperationGenerationConfig): Generator<Operation, FuzzTestState> {\n\tconst { includeOverrides, maxClusterSize, validateInterval } = { ...defaultOptions, ...options };\n\n\tfunction allocateIdsGenerator({ activeClients, clusterSize, random }: FuzzTestState): AllocateIds {\n\t\tconst client = random.pick(activeClients);\n\t\tconst maxIdsPerUsage = clusterSize * 2;\n\t\tconst numIds = Math.floor(random.real(0, 1) ** 3 * maxIdsPerUsage) + 1;\n\t\tconst overrides: AllocateIds['overrides'] = {};\n\t\tif (includeOverrides && random.bool(1 / 4)) {\n\t\t\tfor (let j = 0; j < numIds; j++) {\n\t\t\t\tif (random.bool(1 / 3)) {\n\t\t\t\t\toverrides[j] = random.uuid4();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: 'allocateIds',\n\t\t\tclient,\n\t\t\tnumIds,\n\t\t\toverrides,\n\t\t};\n\t}\n\n\tfunction changeCapacityGenerator({ random }: FuzzTestState): ChangeCapacity {\n\t\treturn {\n\t\t\ttype: 'changeCapacity',\n\t\t\tnewSize: Math.min(Math.floor(random.real(0, 1) ** 2 * maxClusterSize) + 1, maxClusterSize),\n\t\t};\n\t}\n\n\tfunction deliverAllOperationsGenerator(): DeliverAllOperations {\n\t\treturn {\n\t\t\ttype: 'deliverAllOperations',\n\t\t};\n\t}\n\n\tfunction deliverSomeOperationsGenerator({\n\t\trandom,\n\t\tselectableClients,\n\t\tnetwork,\n\t}: FuzzTestState): DeliverSomeOperations {\n\t\tconst pendingClients = selectableClients.filter((c) => network.getPendingOperations(c) > 0);\n\t\tif (pendingClients.length === 0) {\n\t\t\treturn {\n\t\t\t\ttype: 'deliverSomeOperations',\n\t\t\t\tclient: random.pick(selectableClients),\n\t\t\t\tcount: 0,\n\t\t\t};\n\t\t}\n\t\tconst client = random.pick(pendingClients);\n\t\treturn {\n\t\t\ttype: 'deliverSomeOperations',\n\t\t\tclient,\n\t\t\tcount: random.integer(1, network.getPendingOperations(client)),\n\t\t};\n\t}\n\n\tfunction generateUnifyingIdsGenerator({ activeClients, random }: FuzzTestState): GenerateUnifyingIds {\n\t\tconst clientA = random.pick(activeClients);\n\t\tconst clientB = random.pick(activeClients.filter((c) => c !== clientA));\n\t\treturn { type: 'generateUnifyingIds', clientA, clientB, uuid: random.uuid4() };\n\t}\n\n\tfunction reconnectGenerator({ activeClients, random }: FuzzTestState): Reconnect {\n\t\treturn { type: 'reconnect', client: random.pick(activeClients) };\n\t}\n\n\treturn interleave(\n\t\tcreateWeightedGenerator<Operation, FuzzTestState>([\n\t\t\t[changeCapacityGenerator, 1],\n\t\t\t[allocateIdsGenerator, 16],\n\t\t\t[deliverAllOperationsGenerator, 2],\n\t\t\t[deliverSomeOperationsGenerator, 6],\n\t\t\t[generateUnifyingIdsGenerator, 2],\n\t\t\t[reconnectGenerator, 1],\n\t\t]),\n\t\ttake(1, repeat<Operation, FuzzTestState>({ type: 'validate' })),\n\t\tvalidateInterval\n\t);\n}\n\n/**\n * Performs random actions on a test network.\n * @param generator - the generator used to provide operations\n * @param network - the test network to test\n * @param seed - the seed for the random generation of the fuzz actions\n * @param observerClient - if provided, this client will never generate local ids\n * @param synchronizeAtEnd - if provided, all client will have all operations delivered from the server at the end of the test\n * @param validator - if provided, this callback will be invoked periodically during the fuzz test.\n */\nexport function performFuzzActions(\n\tgenerator: Generator<Operation, FuzzTestState>,\n\tnetwork: IdCompressorTestNetwork,\n\tseed: number,\n\tobserverClient?: Client,\n\tsynchronizeAtEnd: boolean = true,\n\tvalidator?: (network: IdCompressorTestNetwork) => void,\n\tsaveInfo?: SaveInfo\n): void {\n\tconst random = makeRandom(seed);\n\tconst selectableClients: Client[] = network.getTargetCompressors(MetaClient.All).map(([client]) => client);\n\n\tconst initialState: FuzzTestState = {\n\t\trandom,\n\t\tnetwork,\n\t\tactiveClients: selectableClients.filter((c) => c !== observerClient),\n\t\tselectableClients,\n\t\tclusterSize: network.initialClusterSize,\n\t};\n\n\tperformFuzzActionsBase(\n\t\tgenerator,\n\t\t{\n\t\t\tallocateIds: (state, { client, numIds, overrides }) => {\n\t\t\t\tnetwork.allocateAndSendIds(client, numIds, overrides);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tchangeCapacity: (state, op) => {\n\t\t\t\tnetwork.enqueueCapacityChange(op.newSize);\n\t\t\t\treturn { ...state, clusterSize: op.newSize };\n\t\t\t},\n\t\t\tdeliverSomeOperations: (state, op) => {\n\t\t\t\tnetwork.deliverOperations(op.client, op.count);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tdeliverAllOperations: (state) => {\n\t\t\t\tnetwork.deliverOperations(DestinationClient.All);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tgenerateUnifyingIds: (state, { clientA, clientB, uuid }) => {\n\t\t\t\tnetwork.allocateAndSendIds(clientA, 1, { 0: uuid });\n\t\t\t\tnetwork.allocateAndSendIds(clientB, 1, { 0: uuid });\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\treconnect: (state, { client }) => {\n\t\t\t\tnetwork.goOfflineThenResume(client);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t\tvalidate: (state) => {\n\t\t\t\tnetwork.deliverOperations(DestinationClient.All);\n\t\t\t\tvalidator?.(network);\n\t\t\t\treturn state;\n\t\t\t},\n\t\t},\n\t\tinitialState,\n\t\tsaveInfo\n\t);\n\n\tif (synchronizeAtEnd) {\n\t\tnetwork.deliverOperations(DestinationClient.All);\n\t\tvalidator?.(network);\n\t}\n}\n\n/**\n * Converts the supplied integer to a uuid.\n */\nexport function integerToStableId(num: number | bigint): StableId {\n\tconst bigintNum = BigInt(num);\n\tconst upper = bigintNum >> BigInt(74);\n\tconst middle = (bigintNum & (BigInt(0xfff) << BigInt(62))) >> BigInt(62);\n\tconst lower = bigintNum & BigInt('0x3fffffffffffffff');\n\tconst upperString = padToLength(upper.toString(16), '0', 12);\n\tconst middleString = `4${padToLength(middle.toString(16), '0', 3)}`;\n\tconst lowerString = padToLength((BigInt('0x8000000000000000') | BigInt(lower)).toString(16), '0', 16);\n\tconst uuid = upperString + middleString + lowerString;\n\treturn assertIsStableId(\n\t\t`${uuid.substr(0, 8)}-${uuid.substr(8, 4)}-${uuid.substr(12, 4)}-${uuid.substr(16, 4)}-${uuid.substr(20)}`\n\t);\n}\n\n/**\n * Pads the strings to a length of 32 with zeroes.\n */\nexport function padToUuidLength(str: string): string {\n\treturn padToLength(str, '0', 32);\n}\n\nfunction padToLength(str: string, char: string, length: number): string {\n\treturn char.repeat(length - str.length) + str;\n}\n\n/**\n * Helper to generate a fixed number of IDs.\n */\nexport function generateCompressedIds(compressor: IdCompressor, count: number): SessionSpaceCompressedId[] {\n\tconst ids: SessionSpaceCompressedId[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tids.push(compressor.generateCompressedId());\n\t}\n\treturn ids;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/tree",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "Distributed tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -38,13 +38,13 @@
38
38
  "dependencies": {
39
39
  "@fluidframework/common-definitions": "^0.20.1",
40
40
  "@fluidframework/common-utils": "^0.32.2",
41
- "@fluidframework/container-definitions": "^1.3.3",
42
- "@fluidframework/core-interfaces": "^1.3.3",
43
- "@fluidframework/datastore-definitions": "^1.3.3",
41
+ "@fluidframework/container-definitions": "^1.3.4",
42
+ "@fluidframework/core-interfaces": "^1.3.4",
43
+ "@fluidframework/datastore-definitions": "^1.3.4",
44
44
  "@fluidframework/protocol-definitions": "^0.1028.2000",
45
- "@fluidframework/runtime-definitions": "^1.3.3",
46
- "@fluidframework/shared-object-base": "^1.3.3",
47
- "@fluidframework/telemetry-utils": "^1.3.3",
45
+ "@fluidframework/runtime-definitions": "^1.3.4",
46
+ "@fluidframework/shared-object-base": "^1.3.4",
47
+ "@fluidframework/telemetry-utils": "^1.3.4",
48
48
  "buffer": "^6.0.3",
49
49
  "denque": "^1.5.1",
50
50
  "lru-cache": "^6.0.0",
@@ -52,19 +52,19 @@
52
52
  "uuid": "^8.3.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@fluid-internal/stochastic-test-utils": "^1.3.3",
55
+ "@fluid-internal/stochastic-test-utils": "^1.3.4",
56
56
  "@fluid-tools/benchmark": "^0.40.0",
57
57
  "@fluidframework/build-common": "^0.24.0",
58
- "@fluidframework/container-loader": "^1.3.3",
59
- "@fluidframework/container-runtime": "^1.3.3",
58
+ "@fluidframework/container-loader": "^1.3.4",
59
+ "@fluidframework/container-runtime": "^1.3.4",
60
60
  "@fluidframework/eslint-config-fluid": "^0.28.2000",
61
- "@fluidframework/mocha-test-setup": "^1.3.3",
62
- "@fluidframework/runtime-utils": "^1.3.3",
63
- "@fluidframework/test-driver-definitions": "^1.3.3",
64
- "@fluidframework/test-drivers": "^1.3.3",
65
- "@fluidframework/test-runtime-utils": "^1.3.3",
66
- "@fluidframework/test-utils": "^1.3.3",
67
- "@fluidframework/undo-redo": "^1.3.3",
61
+ "@fluidframework/mocha-test-setup": "^1.3.4",
62
+ "@fluidframework/runtime-utils": "^1.3.4",
63
+ "@fluidframework/test-driver-definitions": "^1.3.4",
64
+ "@fluidframework/test-drivers": "^1.3.4",
65
+ "@fluidframework/test-runtime-utils": "^1.3.4",
66
+ "@fluidframework/test-utils": "^1.3.4",
67
+ "@fluidframework/undo-redo": "^1.3.4",
68
68
  "@microsoft/api-extractor": "^7.22.2",
69
69
  "@rushstack/eslint-config": "^2.5.1",
70
70
  "@types/lru-cache": "^5.1.0",
@@ -576,14 +576,14 @@ export class IdCompressor {
576
576
  const lastKnownFinal =
577
577
  this.sessionIdNormalizer.getLastFinalId() ??
578
578
  fail('Cluster exists but normalizer does not have an entry for it.');
579
- const lastFinalInCluster = (currentBaseFinalId +
579
+ const lastAlignedFinalInCluster = (currentBaseFinalId +
580
580
  Math.min(currentCluster.count + finalizeCount, currentCluster.capacity) -
581
581
  1) as FinalCompressedId;
582
- if (lastFinalInCluster > lastKnownFinal) {
583
- eagerFinalIdCount = lastFinalInCluster - (lastKnownFinal + 1);
582
+ if (lastAlignedFinalInCluster > lastKnownFinal) {
583
+ eagerFinalIdCount = lastAlignedFinalInCluster - (lastKnownFinal + 1);
584
584
  this.sessionIdNormalizer.addFinalIds(
585
585
  (lastKnownFinal + 1) as FinalCompressedId,
586
- lastFinalInCluster,
586
+ lastAlignedFinalInCluster,
587
587
  currentCluster
588
588
  );
589
589
  }
@@ -619,9 +619,20 @@ export class IdCompressor {
619
619
  // overflow = 2: ----
620
620
  // localIdPivot^
621
621
  // lastFinalizedFinal^
622
- const lastFinalizedFinal = (currentBaseFinalId + currentCluster.count - 1) as FinalCompressedId;
623
- const finalPivot = (lastFinalizedFinal - overflow + 1) as FinalCompressedId;
624
- this.sessionIdNormalizer.addFinalIds(finalPivot, lastFinalizedFinal, currentCluster);
622
+ const newLastFinalizedFinal = (currentBaseFinalId +
623
+ currentCluster.count -
624
+ 1) as FinalCompressedId;
625
+ assert(
626
+ session.lastFinalizedLocalId !== undefined,
627
+ 'Cluster already exists for session but there is no finalized local ID'
628
+ );
629
+ const finalPivot = (newLastFinalizedFinal - overflow + 1) as FinalCompressedId;
630
+ // Inform the normalizer of all IDs that we now know will end up being finalized into this cluster, including the ones
631
+ // that were given out as locals (non-eager) because they exceeded the bounds of the current cluster before it was expanded.
632
+ // It is safe to associate the unfinalized locals with their future final IDs even before the ranges for those locals are
633
+ // actually finalized, because total order broadcast guarantees that any usage of those final IDs will be observed after
634
+ // the finalization of the ranges.
635
+ this.sessionIdNormalizer.registerFinalIdBlock(finalPivot, expansionAmount, currentCluster);
625
636
  this.logger?.sendTelemetryEvent({
626
637
  eventName: 'IdCompressor:ClusterExpansion',
627
638
  sessionId: this.localSessionId,
@@ -690,8 +701,7 @@ export class IdCompressor {
690
701
  clusterCapacity: newCapacity,
691
702
  clusterCount: remainingCount,
692
703
  });
693
- const lastFinalizedFinal = (newBaseFinalId + newCluster.count - 1) as FinalCompressedId;
694
- this.sessionIdNormalizer.addFinalIds(newBaseFinalId, lastFinalizedFinal, newCluster);
704
+ this.sessionIdNormalizer.registerFinalIdBlock(newBaseFinalId, newCluster.capacity, newCluster);
695
705
  }
696
706
 
697
707
  this.checkClusterForCollision(newCluster);
@@ -975,10 +985,12 @@ export class IdCompressor {
975
985
  let eagerFinalId: (FinalCompressedId & SessionSpaceCompressedId) | undefined;
976
986
  let cluster: IdCluster | undefined;
977
987
  if (currentClusterDetails !== undefined) {
978
- const { clusterBase } = currentClusterDetails;
979
988
  cluster = currentClusterDetails.cluster;
980
989
  const lastFinalKnown = sessionIdNormalizer.getLastFinalId();
981
- if (lastFinalKnown !== undefined && lastFinalKnown - clusterBase + 1 < cluster.capacity) {
990
+ if (
991
+ lastFinalKnown !== undefined &&
992
+ lastFinalKnown - currentClusterDetails.clusterBase + 1 < cluster.capacity
993
+ ) {
982
994
  eagerFinalId = (lastFinalKnown + 1) as FinalCompressedId & SessionSpaceCompressedId;
983
995
  }
984
996
  }
@@ -1155,15 +1167,14 @@ export class IdCompressor {
1155
1167
  const inversionKey = IdCompressor.createInversionKey(override);
1156
1168
  const compressionMapping =
1157
1169
  this.clustersAndOverridesInversion.get(inversionKey) ?? fail('Bimap is malformed.');
1158
- if (
1159
- !IdCompressor.isClusterInfo(compressionMapping) &&
1170
+ return !IdCompressor.isClusterInfo(compressionMapping) &&
1160
1171
  !IdCompressor.isUnfinalizedOverride(compressionMapping) &&
1161
1172
  compressionMapping.associatedLocalId === id
1162
- ) {
1163
- return compressionMapping.originalOverridingFinal;
1164
- }
1173
+ ? compressionMapping.originalOverridingFinal
1174
+ : (id as OpSpaceCompressedId);
1165
1175
  }
1166
- return id as OpSpaceCompressedId;
1176
+ const possibleFinal = this.sessionIdNormalizer.getFinalId(id);
1177
+ return possibleFinal?.[0] ?? (id as OpSpaceCompressedId);
1167
1178
  }
1168
1179
  const [correspondingFinal, cluster] =
1169
1180
  this.sessionIdNormalizer.getFinalId(id) ??
@@ -222,16 +222,17 @@ export class SessionIdNormalizer<TRangeObject> {
222
222
  }
223
223
 
224
224
  /**
225
- * Registers a final ID with this normalizer.
226
- * If there are any local IDs at the tip of session-space that do not have a corresponding final, it will be registered (aligned) with
227
- * the first of those. Otherwise, will be registered as the next ID in session space in creation order. An example:
225
+ * Registers one or more final IDs with this normalizer.
226
+ * If there are any local IDs at the tip of session-space that do not have a corresponding final, they will be registered (aligned)
227
+ * starting with the first of those. Otherwise, will be registered as the next ID in session space in creation order.
228
228
  *
229
+ * An example:
229
230
  * Locals: [-1, -2, X, -4]
230
231
  * Finals: [ 0, 1, 2, X]
231
232
  * Calling `addFinalIds` with first === last === 5 results in the following:
232
233
  * Locals: [-1, -2, X, -4]
233
234
  * Finals: [ 0, 1, 2, 5]
234
- * Calling `addFinalIds` with first === last === 6 results in the following:
235
+ * Subsequently calling `addFinalIds` with first === last === 6 results in the following:
235
236
  * Locals: [-1, -2, X, -4, X]
236
237
  * Finals: [ 0, 1, 2, 5, 6]
237
238
  *
@@ -252,18 +253,8 @@ export class SessionIdNormalizer<TRangeObject> {
252
253
  finalRangesObj[1] = [firstFinal, lastFinal, rangeObject];
253
254
  nextLocal = Math.min(this.nextLocalId, firstLocal - (lastFinal - firstFinal) - 1) as LocalCompressedId;
254
255
  } else {
255
- const isSingle = isSingleRange(finalRanges);
256
- let lastFinalRange: FinalRange<TRangeObject>;
257
- let firstAlignedLocal: LocalCompressedId;
258
- if (isSingle) {
259
- firstAlignedLocal = firstLocal;
260
- lastFinalRange = finalRanges;
261
- } else {
262
- [firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');
263
- }
264
-
265
- const [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;
266
- const lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);
256
+ const [firstAlignedLocal, lastAlignedLocal, lastAlignedFinal, lastFinalRange] =
257
+ this.getAlignmentOfLastRange(firstLocal, finalRanges);
267
258
  nextLocal = Math.min(
268
259
  this.nextLocalId,
269
260
  lastAlignedLocal - (lastFinal - firstFinal) - 2
@@ -273,7 +264,7 @@ export class SessionIdNormalizer<TRangeObject> {
273
264
  } else {
274
265
  const alignedLocal = (lastAlignedLocal - 1) as LocalCompressedId;
275
266
  let rangeMap: FinalRangesMap<TRangeObject>;
276
- if (isSingle) {
267
+ if (isSingleRange(finalRanges)) {
277
268
  // Convert the single range to a range collection
278
269
  rangeMap = SessionIdNormalizer.makeFinalRangesMap();
279
270
  rangeMap.append(firstAlignedLocal, lastFinalRange);
@@ -292,6 +283,70 @@ export class SessionIdNormalizer<TRangeObject> {
292
283
  this.nextLocalId = nextLocal;
293
284
  }
294
285
 
286
+ /**
287
+ * Alerts the normalizer to the existence of a block of final IDs that are *allocated* (but may not be entirely used).
288
+ *
289
+ * The normalizer may have unaligned (unfinalized) local IDs; any such outstanding locals will be eagerly aligned with
290
+ * as many finals from the registered block as possible.
291
+ *
292
+ * It is important to register blocks via this method as soon as they are created for future eager final generations to be utilized, as such
293
+ * generation is dependant on the normalizer being up-to-date with which local IDs have been aligned with finals. If, for instance,
294
+ * a block of finals is not immediately registered with the normalizer and there are outstanding locals that would have aligned with them,
295
+ * those locals will not be finalized until their creation range is finalized, which could be later if the block was created by an earlier
296
+ * creation range's finalization but is large enough to span them both. In this scenario, no eager finals can be generated until the second
297
+ * creation range is finalized.
298
+ *
299
+ * A usage example:
300
+ * Locals: [-1, -2, X, -4, -5, -6]
301
+ * Finals: [ 0, 1, 2, X, X, X]
302
+ * Calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 10 results in the following:
303
+ * Locals: [-1, -2, X, -4, -5, -6]
304
+ * Finals: [ 0, 1, 2, 5, 6, 7]
305
+ * Instead calling `registerFinalIdBlock` with firstFinalInBlock === 5 and count === 2 results in the following:
306
+ * Locals: [-1, -2, X, -4, -5, -6]
307
+ * Finals: [ 0, 1, 2, 5, 6, X]
308
+ *
309
+ */
310
+ public registerFinalIdBlock(firstFinalInBlock: FinalCompressedId, count: number, rangeObject: TRangeObject): void {
311
+ assert(count >= 1, 'Malformed normalization block.');
312
+ const [firstLocal, [lastLocal, finalRanges]] =
313
+ this.idRanges.last() ?? fail('Final ID block should not be registered before any locals.');
314
+ let unalignedLocalCount: number;
315
+ if (finalRanges === undefined) {
316
+ unalignedLocalCount = firstLocal - lastLocal + 1;
317
+ } else {
318
+ const [_, lastAlignedLocal] = this.getAlignmentOfLastRange(firstLocal, finalRanges);
319
+ unalignedLocalCount = lastAlignedLocal - lastLocal;
320
+ }
321
+ assert(unalignedLocalCount > 0, 'Final ID block should not be registered without an existing local range.');
322
+ const lastFinal = (firstFinalInBlock + Math.min(unalignedLocalCount, count) - 1) as FinalCompressedId;
323
+ this.addFinalIds(firstFinalInBlock, lastFinal, rangeObject);
324
+ }
325
+
326
+ private getAlignmentOfLastRange(
327
+ firstLocal: LocalCompressedId,
328
+ finalRanges: FinalRanges<TRangeObject>
329
+ ): [
330
+ firstAlignedLocal: LocalCompressedId,
331
+ lastAlignedLocal: LocalCompressedId,
332
+ lastAlignedFinal: FinalCompressedId,
333
+ lastFinalRange: FinalRange<TRangeObject>
334
+ ] {
335
+ const isSingle = isSingleRange(finalRanges);
336
+ let lastFinalRange: FinalRange<TRangeObject>;
337
+ let firstAlignedLocal: LocalCompressedId;
338
+ if (isSingle) {
339
+ firstAlignedLocal = firstLocal;
340
+ lastFinalRange = finalRanges;
341
+ } else {
342
+ [firstAlignedLocal, lastFinalRange] = finalRanges.last() ?? fail('Map should be non-empty.');
343
+ }
344
+
345
+ const [firstAlignedFinal, lastAlignedFinal] = lastFinalRange;
346
+ const lastAlignedLocal = firstAlignedLocal - (lastAlignedFinal - firstAlignedFinal);
347
+ return [firstAlignedLocal, lastAlignedLocal as LocalCompressedId, lastAlignedFinal, lastFinalRange];
348
+ }
349
+
295
350
  /**
296
351
  * Returns an enumerable of all session-space IDs known to this normalizer, in creation order.
297
352
  */