@fluid-experimental/tree 0.59.3003 → 0.59.4000-71128

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.
Files changed (86) hide show
  1. package/dist/Forest.js +1 -1
  2. package/dist/Forest.js.map +1 -1
  3. package/dist/SharedTree.d.ts +89 -30
  4. package/dist/SharedTree.d.ts.map +1 -1
  5. package/dist/SharedTree.js +93 -58
  6. package/dist/SharedTree.js.map +1 -1
  7. package/dist/SharedTreeEncoder.d.ts +1 -1
  8. package/dist/SharedTreeEncoder.d.ts.map +1 -1
  9. package/dist/SharedTreeEncoder.js.map +1 -1
  10. package/dist/id-compressor/IdCompressor.d.ts +19 -45
  11. package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
  12. package/dist/id-compressor/IdCompressor.js +151 -151
  13. package/dist/id-compressor/IdCompressor.js.map +1 -1
  14. package/dist/id-compressor/SessionIdNormalizer.d.ts +1 -16
  15. package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  16. package/dist/id-compressor/SessionIdNormalizer.js +23 -21
  17. package/dist/id-compressor/SessionIdNormalizer.js.map +1 -1
  18. package/dist/id-compressor/persisted-types/0.0.1.d.ts +23 -4
  19. package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  20. package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js.map +1 -1
  24. package/lib/Forest.js +1 -1
  25. package/lib/Forest.js.map +1 -1
  26. package/lib/SharedTree.d.ts +89 -30
  27. package/lib/SharedTree.d.ts.map +1 -1
  28. package/lib/SharedTree.js +94 -59
  29. package/lib/SharedTree.js.map +1 -1
  30. package/lib/SharedTreeEncoder.d.ts +1 -1
  31. package/lib/SharedTreeEncoder.d.ts.map +1 -1
  32. package/lib/SharedTreeEncoder.js.map +1 -1
  33. package/lib/id-compressor/IdCompressor.d.ts +19 -45
  34. package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
  35. package/lib/id-compressor/IdCompressor.js +152 -152
  36. package/lib/id-compressor/IdCompressor.js.map +1 -1
  37. package/lib/id-compressor/SessionIdNormalizer.d.ts +1 -16
  38. package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -1
  39. package/lib/id-compressor/SessionIdNormalizer.js +23 -21
  40. package/lib/id-compressor/SessionIdNormalizer.js.map +1 -1
  41. package/lib/id-compressor/persisted-types/0.0.1.d.ts +23 -4
  42. package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  43. package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
  44. package/lib/index.d.ts +1 -1
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js.map +1 -1
  47. package/lib/test/IdCompressor.perf.tests.js +47 -67
  48. package/lib/test/IdCompressor.perf.tests.js.map +1 -1
  49. package/lib/test/IdCompressor.tests.js +196 -101
  50. package/lib/test/IdCompressor.tests.js.map +1 -1
  51. package/lib/test/Summary.tests.d.ts +0 -1
  52. package/lib/test/Summary.tests.d.ts.map +1 -1
  53. package/lib/test/Summary.tests.js +0 -3
  54. package/lib/test/Summary.tests.js.map +1 -1
  55. package/lib/test/Virtualization.tests.js +0 -4
  56. package/lib/test/Virtualization.tests.js.map +1 -1
  57. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
  58. package/lib/test/fuzz/SharedTreeFuzzTests.js +3 -1
  59. package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
  60. package/lib/test/utilities/IdCompressorTestUtilities.d.ts +14 -7
  61. package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
  62. package/lib/test/utilities/IdCompressorTestUtilities.js +40 -20
  63. package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
  64. package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
  65. package/lib/test/utilities/SharedTreeTests.js +27 -51
  66. package/lib/test/utilities/SharedTreeTests.js.map +1 -1
  67. package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
  68. package/lib/test/utilities/SharedTreeVersioningTests.js +19 -19
  69. package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
  70. package/lib/test/utilities/SummaryLoadPerfTests.js +1 -1
  71. package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
  72. package/lib/test/utilities/TestCommon.d.ts +4 -0
  73. package/lib/test/utilities/TestCommon.d.ts.map +1 -1
  74. package/lib/test/utilities/TestCommon.js +6 -0
  75. package/lib/test/utilities/TestCommon.js.map +1 -1
  76. package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
  77. package/lib/test/utilities/TestUtilities.js +4 -6
  78. package/lib/test/utilities/TestUtilities.js.map +1 -1
  79. package/package.json +24 -19
  80. package/src/Forest.ts +1 -1
  81. package/src/SharedTree.ts +195 -46
  82. package/src/SharedTreeEncoder.ts +1 -1
  83. package/src/id-compressor/IdCompressor.ts +171 -198
  84. package/src/id-compressor/SessionIdNormalizer.ts +29 -41
  85. package/src/id-compressor/persisted-types/0.0.1.ts +25 -4
  86. package/src/index.ts +4 -0
@@ -114,6 +114,14 @@ export class IdCompressorTestNetwork {
114
114
  getCompressorUnsafe(client) {
115
115
  return this.getCompressor(client);
116
116
  }
117
+ /**
118
+ * Returns a mutable handle to a compressor in the network. Use of mutation methods will break the network invariants and
119
+ * should only be used if the network will not be used again. Additionally, the returned compressor will be invalidated/unusable
120
+ * if any network operations cause it to be regenerated (serialization/deserialization, etc.).
121
+ */
122
+ getCompressorUnsafeNoProxy(client) {
123
+ return this.compressors.get(client);
124
+ }
117
125
  /**
118
126
  * 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)
119
127
  */
@@ -121,7 +129,7 @@ export class IdCompressorTestNetwork {
121
129
  return this.idLogs.get(client);
122
130
  }
123
131
  /**
124
- * Returns data for all IDs received by this client, including ack's of their own (i.e. their own IDs will appear twice)
132
+ * Returns data for all IDs received by this client, including ack's of their own.
125
133
  */
126
134
  getSequencedIdLog(client) {
127
135
  return this.sequencedIdLogs.get(client);
@@ -162,28 +170,32 @@ export class IdCompressorTestNetwork {
162
170
  assert(numIds > 0, 'Must allocate a non-zero number of IDs');
163
171
  const compressor = this.compressors.get(client);
164
172
  let nextIdIndex = 0;
173
+ const opSpaceIds = [];
165
174
  for (const [overrideIndex, uuid] of Object.entries(overrides)
166
175
  .map(([id, uuid]) => [Number.parseInt(id, 10), uuid])
167
176
  .sort(([a], [b]) => a - b)) {
168
177
  while (nextIdIndex < overrideIndex) {
169
- this.addNewId(client, compressor.generateCompressedId(), undefined, client, false);
178
+ const newId = compressor.generateCompressedId();
179
+ opSpaceIds.push(compressor.normalizeToOpSpace(newId));
180
+ this.addNewId(client, newId, undefined, client, false);
170
181
  nextIdIndex += 1;
171
182
  }
172
- this.addNewId(client, compressor.generateCompressedId(uuid), uuid, client, false);
183
+ const newOverrideId = compressor.generateCompressedId(uuid);
184
+ opSpaceIds.push(compressor.normalizeToOpSpace(newOverrideId));
185
+ this.addNewId(client, newOverrideId, uuid, client, false);
173
186
  nextIdIndex += 1;
174
187
  }
175
188
  const numTrailingIds = numIds - nextIdIndex;
176
- let range;
177
189
  if (numTrailingIds > 0) {
178
- range = compressor.generateCompressedIdRange(numTrailingIds);
179
- const ids = compressor.getIdsFromRange(range, compressor.localSessionId);
190
+ const sessionSpaceIds = generateCompressedIds(compressor, numTrailingIds);
180
191
  for (let i = 0; i < numTrailingIds; i++) {
181
- this.addNewId(client, ids.get(i), undefined, client, false);
192
+ this.addNewId(client, sessionSpaceIds[i], undefined, client, false);
182
193
  }
194
+ sessionSpaceIds.forEach((id) => opSpaceIds.push(compressor.normalizeToOpSpace(id)));
183
195
  }
184
196
  const creationRange = compressor.takeNextCreationRange();
185
- this.serverOperations.push([creationRange, client]);
186
- return nextIdIndex === 0 ? { range: range !== null && range !== void 0 ? range : fail(), sessionId: compressor.localSessionId } : creationRange;
197
+ this.serverOperations.push([creationRange, opSpaceIds, client]);
198
+ return nextIdIndex === 0 ? opSpaceIds : creationRange;
187
199
  }
188
200
  /**
189
201
  * Delivers all undelivered ID ranges and cluster capacity changes from the server to the target clients.
@@ -197,13 +209,13 @@ export class IdCompressorTestNetwork {
197
209
  compressorTo.clusterCapacity = operation;
198
210
  }
199
211
  else {
200
- const [range, clientFrom] = operation;
212
+ const [range, opSpaceIds, clientFrom] = operation;
201
213
  compressorTo.finalizeCreationRange(range);
202
214
  const ids = getIds(range);
203
215
  if (ids !== undefined) {
204
216
  let overrideIndex = 0;
205
217
  const overrides = ids.overrides;
206
- for (let id = ids.first; id >= ids.last; id--) {
218
+ for (const id of opSpaceIds) {
207
219
  let override;
208
220
  if (overrides !== undefined &&
209
221
  overrideIndex < overrides.length &&
@@ -273,9 +285,6 @@ export class IdCompressorTestNetwork {
273
285
  for (const [current, next] of getLogIndices(i)) {
274
286
  const [compressorA, idDataA] = current;
275
287
  const sessionSpaceIdA = idDataA.id;
276
- if (isLocalId(sessionSpaceIdA)) {
277
- localCount += 1;
278
- }
279
288
  const idIndex = getOrCreate(idIndicesAggregator, idDataA.originatingClient, () => 0);
280
289
  originatingClient !== null && originatingClient !== void 0 ? originatingClient : (originatingClient = idDataA.originatingClient);
281
290
  assert(idDataA.originatingClient === originatingClient, 'Test infra gave wrong originating client to TestIdData');
@@ -304,8 +313,9 @@ export class IdCompressorTestNetwork {
304
313
  const opSpaceIdA = compressorA.normalizeToOpSpace(sessionSpaceIdA);
305
314
  if (isLocalId(opSpaceIdA)) {
306
315
  expect.fail('IDs should have been finalized.');
316
+ fail();
307
317
  }
308
- // TODO: This cast can be removed on typescript 4.6
318
+ expect(compressorA.normalizeToSessionSpace(opSpaceIdA, compressorA.localSessionId)).equals(sessionSpaceIdA);
309
319
  finalIds.add(opSpaceIdA);
310
320
  const uuidAOpSpace = compressorA.decompress(opSpaceIdA);
311
321
  expect(uuidASessionSpace).to.equal(uuidAOpSpace);
@@ -328,12 +338,12 @@ export class IdCompressorTestNetwork {
328
338
  }
329
339
  rowCount += 1;
330
340
  }
331
- // A local count > 1 indicates that this ID was unified, as more than one client has a local ID for it
332
- // in their session space.
341
+ // A local count === 0 indicates the ID was created as an eager final, and thus cannot have had an
342
+ // override to unify.
333
343
  if (rowCount === this.sequencedIdLogs.size && localCount <= 1) {
334
- expect(localCount).to.equal(1);
344
+ expect(localCount).to.lessThanOrEqual(1);
335
345
  for (const [[compressor, { id, originatingClient }]] of getLogIndices(i)) {
336
- expect(compressor.attributeId(id)).to.equal(originatingClient);
346
+ expect(compressor.attributeId(id)).to.equal(attributionIds.get(originatingClient));
337
347
  }
338
348
  }
339
349
  expect(uuids.size).to.equal(finalIds.size);
@@ -420,7 +430,7 @@ export function makeOpGenerator(options) {
420
430
  function allocateIdsGenerator({ activeClients, clusterSize, random }) {
421
431
  const client = random.pick(activeClients);
422
432
  const maxIdsPerUsage = clusterSize * 2;
423
- const numIds = Math.floor(random.real(0, 1) ** 2 * maxIdsPerUsage) + 1;
433
+ const numIds = Math.floor(random.real(0, 1) ** 3 * maxIdsPerUsage) + 1;
424
434
  const overrides = {};
425
435
  if (includeOverrides && random.bool(1 / 4)) {
426
436
  for (let j = 0; j < numIds; j++) {
@@ -539,4 +549,14 @@ export function padToUuidLength(str) {
539
549
  function padToLength(str, char, length) {
540
550
  return char.repeat(length - str.length) + str;
541
551
  }
552
+ /**
553
+ * Helper to generate a fixed number of IDs.
554
+ */
555
+ export function generateCompressedIds(compressor, count) {
556
+ const ids = [];
557
+ for (let i = 0; i < count; i++) {
558
+ ids.push(compressor.generateCompressedId());
559
+ }
560
+ return ids;
561
+ }
542
562
  //# sourceMappingURL=IdCompressorTestUtilities.js.map
@@ -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, IdRangeDescriptor, isLocalId } from '../../id-compressor/IdCompressor';\nimport {\n\tcreateSessionId,\n\tensureSessionUuid,\n\tNumericUuid,\n\tnumericUuidFromStableId,\n\tstableIdFromNumericUuid,\n} from '../../id-compressor/NumericUuid';\nimport { FinalCompressedId, SessionId, StableId, SessionSpaceCompressedId, AttributionId } 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: ([range: IdCreationRange, clientFrom: Client] | number)[] = [];\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 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 (i.e. their own IDs will appear twice)\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(\n\t\tclient: Client,\n\t\tnumIds: number\n\t): { range: IdRangeDescriptor<SessionSpaceCompressedId>; sessionId: SessionId };\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): { range: IdRangeDescriptor<SessionSpaceCompressedId>; sessionId: SessionId } | 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\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\tthis.addNewId(client, compressor.generateCompressedId(), undefined, client, false);\n\t\t\t\tnextIdIndex += 1;\n\t\t\t}\n\t\t\tthis.addNewId(client, compressor.generateCompressedId(uuid), uuid, client, false);\n\t\t\tnextIdIndex += 1;\n\t\t}\n\t\tconst numTrailingIds = numIds - nextIdIndex;\n\t\tlet range: IdRangeDescriptor<SessionSpaceCompressedId> | undefined;\n\t\tif (numTrailingIds > 0) {\n\t\t\trange = compressor.generateCompressedIdRange(numTrailingIds);\n\t\t\tconst ids = compressor.getIdsFromRange(range, compressor.localSessionId);\n\t\t\tfor (let i = 0; i < numTrailingIds; i++) {\n\t\t\t\tthis.addNewId(client, ids.get(i), undefined, client, false);\n\t\t\t}\n\t\t}\n\t\tconst creationRange = compressor.takeNextCreationRange();\n\t\tthis.serverOperations.push([creationRange, client]);\n\t\treturn nextIdIndex === 0 ? { range: range ?? fail(), sessionId: compressor.localSessionId } : 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, 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 (let id = ids.first; id >= ids.last; id--) {\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\tif (isLocalId(sessionSpaceIdA)) {\n\t\t\t\t\tlocalCount += 1;\n\t\t\t\t}\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}\n\t\t\t\t// TODO: This cast can be removed on typescript 4.6\n\t\t\t\tfinalIds.add(opSpaceIdA as FinalCompressedId);\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 > 1 indicates that this ID was unified, as more than one client has a local ID for it\n\t\t\t// in their session space.\n\t\t\tif (rowCount === this.sequencedIdLogs.size && localCount <= 1) {\n\t\t\t\texpect(localCount).to.equal(1);\n\t\t\t\tfor (const [[compressor, { id, originatingClient }]] of getLogIndices(i)) {\n\t\t\t\t\texpect(compressor.attributeId(id)).to.equal(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) ** 2 * 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"]}
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 +1 @@
1
- {"version":3,"file":"SharedTreeTests.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/SharedTreeTests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH,OAAO,EAeN,WAAW,EACX,MAAM,uBAAuB,CAAC;AAa/B,OAAO,EAGN,2BAA2B,EAC3B,wBAAwB,EAcxB,MAAM,iBAAiB,CAAC;AAazB;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,WAAW,EACxB,qCAAqC,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,2BAA2B,QAy9C1G"}
1
+ {"version":3,"file":"SharedTreeTests.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/SharedTreeTests.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH,OAAO,EAeN,WAAW,EACX,MAAM,uBAAuB,CAAC;AAa/B,OAAO,EAGN,2BAA2B,EAC3B,wBAAwB,EAcxB,MAAM,iBAAiB,CAAC;AAazB;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,WAAW,EACxB,qCAAqC,EAAE,CAAC,OAAO,CAAC,EAAE,wBAAwB,KAAK,2BAA2B,QAu9C1G"}
@@ -23,6 +23,7 @@ import { InterningTreeCompressor } from '../../TreeCompressor';
23
23
  import { SharedTreeEncoder_0_0_2, SharedTreeEncoder_0_1_1 } from '../../SharedTreeEncoder';
24
24
  import { sequencedIdNormalizer } from '../../NodeIdUtilities';
25
25
  import { convertNodeDataIds } from '../../IdConversion';
26
+ import { generateStableId, nilUuid } from '../../UuidUtilities';
26
27
  import { buildLeaf, SimpleTestTree } from './TestNode';
27
28
  import { TestFluidHandle, TestFluidSerializer } from './TestSerializer';
28
29
  import { runSharedTreeUndoRedoTestSuite } from './UndoRedoTests';
@@ -216,18 +217,16 @@ export function runSharedTreeOperationsTests(title, writeFormat, setUpTestShared
216
217
  sharedTree.applyEdit(Change.build([], 0));
217
218
  });
218
219
  });
219
- // TODO:#461: Reenable
220
- it.skip('correctly reports attribution ID', () => {
221
- // const attributionId = generateStableId();
222
- // const { tree } = setUpTestSharedTree({ attributionId });
223
- // expect(tree.attributionId).to.equal(writeFormat === WriteFormat.v0_0_2 ? nilUuid : attributionId);
220
+ it('correctly reports attribution ID', () => {
221
+ const attributionId = generateStableId();
222
+ const { tree } = setUpTestSharedTree({ attributionId });
223
+ expect(tree.attributionId).to.equal(writeFormat === WriteFormat.v0_0_2 ? nilUuid : attributionId);
224
224
  });
225
- // TODO:#461: Reenable
226
- it.skip('correctly attributes node IDs', () => {
227
- // const attributionId = generateStableId();
228
- // const { tree } = setUpTestSharedTree({ attributionId });
229
- // const id = tree.generateNodeId();
230
- // expect(tree.attributeNodeId(id)).to.equal(writeFormat === WriteFormat.v0_0_2 ? nilUuid : attributionId);
225
+ it('correctly attributes node IDs', () => {
226
+ const attributionId = generateStableId();
227
+ const { tree } = setUpTestSharedTree({ attributionId });
228
+ const id = tree.generateNodeId();
229
+ expect(tree.attributeNodeId(id)).to.equal(writeFormat === WriteFormat.v0_0_2 ? nilUuid : attributionId);
231
230
  });
232
231
  runSharedTreeUndoRedoTestSuite(Object.assign({ localMode: true }, undoRedoOptions));
233
232
  });
@@ -459,43 +458,22 @@ export function runSharedTreeOperationsTests(title, writeFormat, setUpTestShared
459
458
  const blobContents = await blobHandle.get();
460
459
  expect(IsoBuffer.from(blobContents, 'utf8').toString()).to.equal(blobbedPayload);
461
460
  });
462
- // TODO:#461: Reenable
463
- it.skip('can exchange attribution IDs', () => {
464
- // const attributionId1 = generateStableId();
465
- // const { tree: sharedTree1, containerRuntimeFactory } = setUpTestSharedTree({
466
- // ...tree1Options,
467
- // attributionId: attributionId1,
468
- // });
469
- // const attributionId2 = generateStableId();
470
- // const { tree: sharedTree2 } = setUpTestSharedTree({
471
- // ...createSecondTreeOptions(containerRuntimeFactory),
472
- // attributionId: attributionId2,
473
- // });
474
- // containerRuntimeFactory.processAllMessages();
475
- // const nodeId1 = sharedTree1.generateNodeId();
476
- // const stableNodeId1 = sharedTree1.convertToStableNodeId(nodeId1);
477
- // sharedTree1.applyEdit(
478
- // ...Change.insertTree(
479
- // [buildLeaf(nodeId1)],
480
- // StablePlace.atEndOf(testTrait(sharedTree1.currentView))
481
- // )
482
- // );
483
- // containerRuntimeFactory.processAllMessages();
484
- // expect(sharedTree2.attributeNodeId(sharedTree2.convertToNodeId(stableNodeId1))).to.equal(
485
- // attributionId1
486
- // );
487
- // const nodeId2 = sharedTree2.generateNodeId();
488
- // const stableNodeId2 = sharedTree2.convertToStableNodeId(nodeId1);
489
- // sharedTree2.applyEdit(
490
- // ...Change.insertTree(
491
- // [buildLeaf(nodeId2)],
492
- // StablePlace.atEndOf(testTrait(sharedTree2.currentView))
493
- // )
494
- // );
495
- // containerRuntimeFactory.processAllMessages();
496
- // expect(sharedTree1.attributeNodeId(sharedTree1.convertToNodeId(stableNodeId2))).to.equal(
497
- // attributionId2
498
- // );
461
+ it('can exchange attribution IDs', () => {
462
+ const attributionId1 = generateStableId();
463
+ const { tree: sharedTree1, containerRuntimeFactory } = setUpTestSharedTree(Object.assign(Object.assign({}, tree1Options), { attributionId: attributionId1 }));
464
+ const attributionId2 = generateStableId();
465
+ const { tree: sharedTree2 } = setUpTestSharedTree(Object.assign(Object.assign({}, createSecondTreeOptions(containerRuntimeFactory)), { attributionId: attributionId2 }));
466
+ containerRuntimeFactory.processAllMessages();
467
+ const nodeId1 = sharedTree1.generateNodeId();
468
+ const stableNodeId1 = sharedTree1.convertToStableNodeId(nodeId1);
469
+ sharedTree1.applyEdit(...Change.insertTree([buildLeaf(nodeId1)], StablePlace.atEndOf(testTrait(sharedTree1.currentView))));
470
+ containerRuntimeFactory.processAllMessages();
471
+ expect(sharedTree2.attributeNodeId(sharedTree2.convertToNodeId(stableNodeId1))).to.equal(attributionId1);
472
+ const nodeId2 = sharedTree2.generateNodeId();
473
+ const stableNodeId2 = sharedTree2.convertToStableNodeId(nodeId1);
474
+ sharedTree2.applyEdit(...Change.insertTree([buildLeaf(nodeId2)], StablePlace.atEndOf(testTrait(sharedTree2.currentView))));
475
+ containerRuntimeFactory.processAllMessages();
476
+ expect(sharedTree1.attributeNodeId(sharedTree1.convertToNodeId(stableNodeId2))).to.equal(attributionId2);
499
477
  });
500
478
  }
501
479
  });
@@ -539,8 +517,7 @@ export function runSharedTreeOperationsTests(title, writeFormat, setUpTestShared
539
517
  const treeContent = JSON.parse(serialized);
540
518
  let parsedTree;
541
519
  if (writeFormat === WriteFormat.v0_1_1) {
542
- // TODO:#461: Pass in attribution ID
543
- parsedTree = new SharedTreeEncoder_0_1_1(true).decodeSummary(treeContent);
520
+ parsedTree = new SharedTreeEncoder_0_1_1(true).decodeSummary(treeContent, sharedTree.attributionId);
544
521
  }
545
522
  else {
546
523
  parsedTree = new SharedTreeEncoder_0_0_2(true).decodeSummary(treeContent);
@@ -866,7 +843,6 @@ export function runSharedTreeOperationsTests(title, writeFormat, setUpTestShared
866
843
  writeFormat,
867
844
  summarizeHistory: false,
868
845
  });
869
- testObjectProvider.logger.registerExpectedEvent({ eventName: 'fluid:telemetry:Batching:LengthTooBig' }, { eventName: 'fluid:telemetry:Batching:LengthTooBig' }, { eventName: 'fluid:telemetry:Batching:LengthTooBig' });
870
846
  applyNoop(tree);
871
847
  await testObjectProvider.ensureSynchronized();
872
848
  const firstSummaryVersion = await waitForSummary(container);