@fluidframework/azure-end-to-end-tests 2.70.0 → 2.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/azure-end-to-end-tests",
3
- "version": "2.70.0",
3
+ "version": "2.72.0",
4
4
  "description": "Azure client end to end tests",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -33,29 +33,29 @@
33
33
  "temp-directory": "nyc/.nyc_output"
34
34
  },
35
35
  "dependencies": {
36
- "@fluid-experimental/data-objects": "~2.70.0",
37
- "@fluid-internal/client-utils": "~2.70.0",
38
- "@fluid-internal/mocha-test-setup": "~2.70.0",
39
- "@fluid-private/test-version-utils": "~2.70.0",
40
- "@fluidframework/aqueduct": "~2.70.0",
41
- "@fluidframework/azure-client": "~2.70.0",
36
+ "@fluid-experimental/data-objects": "~2.72.0",
37
+ "@fluid-internal/client-utils": "~2.72.0",
38
+ "@fluid-internal/mocha-test-setup": "~2.72.0",
39
+ "@fluid-private/test-version-utils": "~2.72.0",
40
+ "@fluidframework/aqueduct": "~2.72.0",
41
+ "@fluidframework/azure-client": "~2.72.0",
42
42
  "@fluidframework/azure-client-legacy": "npm:@fluidframework/azure-client@^1.2.0",
43
- "@fluidframework/container-definitions": "~2.70.0",
44
- "@fluidframework/container-loader": "~2.70.0",
45
- "@fluidframework/core-interfaces": "~2.70.0",
46
- "@fluidframework/counter": "~2.70.0",
47
- "@fluidframework/datastore-definitions": "~2.70.0",
48
- "@fluidframework/fluid-static": "~2.70.0",
49
- "@fluidframework/map": "~2.70.0",
43
+ "@fluidframework/container-definitions": "~2.72.0",
44
+ "@fluidframework/container-loader": "~2.72.0",
45
+ "@fluidframework/core-interfaces": "~2.72.0",
46
+ "@fluidframework/counter": "~2.72.0",
47
+ "@fluidframework/datastore-definitions": "~2.72.0",
48
+ "@fluidframework/fluid-static": "~2.72.0",
49
+ "@fluidframework/map": "~2.72.0",
50
50
  "@fluidframework/map-legacy": "npm:@fluidframework/map@^1.4.0",
51
- "@fluidframework/matrix": "~2.70.0",
52
- "@fluidframework/presence": "~2.70.0",
53
- "@fluidframework/runtime-definitions": "~2.70.0",
54
- "@fluidframework/sequence": "~2.70.0",
55
- "@fluidframework/telemetry-utils": "~2.70.0",
56
- "@fluidframework/test-runtime-utils": "~2.70.0",
57
- "@fluidframework/test-utils": "~2.70.0",
58
- "@fluidframework/tree": "~2.70.0",
51
+ "@fluidframework/matrix": "~2.72.0",
52
+ "@fluidframework/presence": "~2.72.0",
53
+ "@fluidframework/runtime-definitions": "~2.72.0",
54
+ "@fluidframework/sequence": "~2.72.0",
55
+ "@fluidframework/telemetry-utils": "~2.72.0",
56
+ "@fluidframework/test-runtime-utils": "~2.72.0",
57
+ "@fluidframework/test-utils": "~2.72.0",
58
+ "@fluidframework/tree": "~2.72.0",
59
59
  "axios": "^1.8.4",
60
60
  "cross-env": "^7.0.3",
61
61
  "mocha": "^10.8.2",
@@ -68,9 +68,9 @@
68
68
  "devDependencies": {
69
69
  "@biomejs/biome": "~1.9.3",
70
70
  "@fluidframework/build-common": "^2.0.3",
71
- "@fluidframework/build-tools": "^0.58.3",
72
- "@fluidframework/driver-definitions": "~2.70.0",
73
- "@fluidframework/eslint-config-fluid": "^6.1.0",
71
+ "@fluidframework/build-tools": "^0.60.0",
72
+ "@fluidframework/driver-definitions": "~2.72.0",
73
+ "@fluidframework/eslint-config-fluid": "~2.72.0",
74
74
  "@types/mocha": "^10.0.10",
75
75
  "@types/nock": "^9.3.0",
76
76
  "@types/node": "^18.19.0",
@@ -100,8 +100,8 @@
100
100
  "check:biome": "biome check .",
101
101
  "check:format": "npm run check:biome",
102
102
  "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" nyc",
103
- "eslint": "eslint --format stylish src",
104
- "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
103
+ "eslint": "eslint --quiet --format stylish src",
104
+ "eslint:fix": "eslint --quiet --format stylish src --fix --fix-type problem,suggestion,layout",
105
105
  "format": "npm run format:biome",
106
106
  "format:biome": "biome check . --write",
107
107
  "lint": "fluid-build . --task lint",
@@ -9,7 +9,7 @@ import {
9
9
  type AzureRemoteConnectionConfig,
10
10
  type ITelemetryBaseLogger,
11
11
  } from "@fluidframework/azure-client";
12
- // eslint-disable-next-line import/no-internal-modules -- TODO consider a test exposure to avoid /internal
12
+ // eslint-disable-next-line import-x/no-internal-modules -- TODO consider a test exposure to avoid /internal
13
13
  import type { AzureClientPropsInternal } from "@fluidframework/azure-client/internal";
14
14
  import {
15
15
  AzureClient as AzureClientLegacy,
@@ -5,7 +5,7 @@
5
5
 
6
6
  import type { SignalListener } from "@fluid-experimental/data-objects";
7
7
  import { EventEmitter } from "@fluid-internal/client-utils";
8
- // eslint-disable-next-line import/no-internal-modules -- TODO consider a test exposure to avoid /internal
8
+ // eslint-disable-next-line import-x/no-internal-modules -- TODO consider a test exposure to avoid /internal
9
9
  import { createDataObjectKind } from "@fluidframework/aqueduct/internal";
10
10
  import {
11
11
  DataObject,
@@ -14,7 +14,7 @@ import {
14
14
  MessageType,
15
15
  type ISequencedDocumentMessage,
16
16
  } from "@fluidframework/driver-definitions/legacy";
17
- // eslint-disable-next-line import/no-internal-modules -- TODO consider a test exposure to avoid /internal
17
+ // eslint-disable-next-line import-x/no-internal-modules -- TODO consider a test exposure to avoid /internal
18
18
  import { isTreeContainerSchema } from "@fluidframework/fluid-static/internal";
19
19
  import {
20
20
  type ContainerSchema,
@@ -40,10 +40,10 @@ import type {
40
40
  EventEntry,
41
41
  } from "./messageTypes.js";
42
42
 
43
- const connectTimeoutMs = 10_000;
43
+ const testLabel = process.argv[2];
44
44
  // Identifier given to child process
45
- const process_id = process.argv[2];
46
- const verbosity = process.argv[3] ?? "";
45
+ const process_id = process.argv[3];
46
+ const verbosity = process.argv[4] ?? "";
47
47
 
48
48
  const useAzure = process.env.FLUID_CLIENT === "azure";
49
49
  const tenantId = useAzure
@@ -61,6 +61,10 @@ const containerSchema = {
61
61
  },
62
62
  } as const satisfies ContainerSchema;
63
63
 
64
+ function log(...data: unknown[]): void {
65
+ console.log(`[${testLabel}] [${new Date().toISOString()}] [${process_id}]`, ...data);
66
+ }
67
+
64
68
  function telemetryEventInterestLevel(eventName: string): "none" | "basic" | "details" {
65
69
  if (eventName.includes(":Signal") || eventName.includes(":Join")) {
66
70
  return "details";
@@ -82,7 +86,7 @@ function selectiveVerboseLog(event: ITelemetryBaseEvent, logLevel?: LogLevel): v
82
86
  if (interest === "details") {
83
87
  content.details = event.details;
84
88
  }
85
- console.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, content);
89
+ log(`[${logLevel ?? LogLevel.default}]`, content);
86
90
  }
87
91
 
88
92
  /**
@@ -95,6 +99,7 @@ const getOrCreateContainer = async (params: {
95
99
  user: UserIdAndName;
96
100
  scopes?: ScopeType[];
97
101
  createScopes?: ScopeType[];
102
+ connectTimeoutMs: number;
98
103
  }): Promise<{
99
104
  container: IFluidContainer<typeof containerSchema>;
100
105
  services: AzureContainerServices;
@@ -104,7 +109,7 @@ const getOrCreateContainer = async (params: {
104
109
  }> => {
105
110
  let container: IFluidContainer<typeof containerSchema>;
106
111
  let { containerId } = params;
107
- const { logger, onDisconnected, user, scopes, createScopes } = params;
112
+ const { logger, onDisconnected, user, scopes, createScopes, connectTimeoutMs } = params;
108
113
  const connectionProps: AzureRemoteConnectionConfig | AzureLocalConnectionConfig = useAzure
109
114
  ? {
110
115
  tenantId,
@@ -163,7 +168,7 @@ function createSendFunction(): (msg: MessageToParent) => void {
163
168
  const sendFn = process.send.bind(process);
164
169
  if (verbosity.includes("msgs")) {
165
170
  return (msg: MessageToParent) => {
166
- console.log(`[${process_id}] Sending`, msg);
171
+ log(`Sending`, msg);
167
172
  sendFn(msg);
168
173
  };
169
174
  }
@@ -248,11 +253,17 @@ class MessageHandler {
248
253
 
249
254
  private readonly logger: ITelemetryBaseLogger = {
250
255
  send: (event: ITelemetryBaseEvent, logLevel?: LogLevel) => {
256
+ // Filter out non-interactive client telemetry
257
+ const clientType = event.clientType;
258
+ if (typeof clientType === "string" && clientType.startsWith("noninteractive")) {
259
+ return;
260
+ }
261
+
251
262
  // Special case unexpected telemetry event
252
263
  if (event.eventName.endsWith(":JoinResponseWhenAlone")) {
253
264
  this.send({
254
265
  event: "error",
255
- error: `Unexpected ClientJoin response. Details: ${JSON.stringify(event.details)}`,
266
+ error: `Unexpected ClientJoin response. Details: ${JSON.stringify(event.details)}\nLog: ${JSON.stringify(this.log)}`,
256
267
  });
257
268
  // Keep going
258
269
  }
@@ -374,7 +385,7 @@ class MessageHandler {
374
385
  eventCategory: "messageReceived",
375
386
  eventName: msg.command,
376
387
  });
377
- console.log(`[${process_id}] Received`, msg);
388
+ log(`Received`, msg);
378
389
  }
379
390
 
380
391
  if (msg.command === "ping") {
@@ -471,7 +482,10 @@ class MessageHandler {
471
482
  this.presence = presence;
472
483
 
473
484
  // wait for 'ConnectionState.Connected'
474
- await connected;
485
+ await connected.catch((error) => {
486
+ (error as Error).message += `\nLog: ${JSON.stringify(this.log)}`;
487
+ throw error;
488
+ });
475
489
 
476
490
  // Acknowledge connection before sending current attendee information
477
491
  this.send({
@@ -512,9 +526,7 @@ class MessageHandler {
512
526
  connectedCount++;
513
527
  }
514
528
  }
515
- console.log(
516
- `[${process_id}] Report: ${attendees.size} attendees, ${connectedCount} connected`,
517
- );
529
+ log(`Report: ${attendees.size} attendees, ${connectedCount} connected`);
518
530
  } else {
519
531
  this.send({ event: "error", error: `${process_id} is not connected to presence` });
520
532
  }
@@ -712,7 +724,7 @@ function setupMessageHandler(): void {
712
724
  const messageHandler = new MessageHandler();
713
725
  process.on("message", (msg: MessageFromParent) => {
714
726
  messageHandler.onMessage(msg).catch((error: Error) => {
715
- console.error(`Error in client ${process_id}`, error);
727
+ console.error(`[${testLabel}] Error in client ${process_id}`, error);
716
728
  send({ event: "error", error: `${process_id}: ${error.message}` });
717
729
  });
718
730
  });
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- // eslint-disable-next-line import/no-internal-modules
6
+ // eslint-disable-next-line import-x/no-internal-modules
7
7
  import type { JsonSerializable } from "@fluidframework/core-interfaces/internal";
8
8
  import type { ScopeType } from "@fluidframework/driver-definitions/legacy";
9
9
  import type { AttendeeId } from "@fluidframework/presence/beta";
@@ -57,6 +57,7 @@ export interface ConnectCommand {
57
57
  * If not provided, a new Fluid container will be created.
58
58
  */
59
59
  containerId?: string;
60
+ connectTimeoutMs: number;
60
61
  }
61
62
 
62
63
  /**
@@ -58,6 +58,7 @@ interface ChildProcess extends AnyChildProcess {
58
58
  * @returns A collection of child processes and a promise that rejects on the first child error.
59
59
  */
60
60
  export async function forkChildProcesses(
61
+ testLabel: string,
61
62
  numProcesses: number,
62
63
  cleanUpAccumulator: (() => void)[],
63
64
  ): Promise<{
@@ -72,6 +73,7 @@ export async function forkChildProcesses(
72
73
  const childErrorPromises: Promise<never>[] = [];
73
74
  for (let i = 0; i < numProcesses; i++) {
74
75
  const child = fork("./lib/test/multiprocess/childClient.tool.js", [
76
+ testLabel,
75
77
  `child ${i}` /* identifier passed to child process */,
76
78
  childLoggingVerbosity /* console logging verbosity */,
77
79
  ]);
@@ -152,6 +154,7 @@ export async function executeDebugReports(
152
154
  function composeConnectMessage(
153
155
  id: string | number,
154
156
  scopes: ScopeType[] = [ScopeType.DocRead],
157
+ connectTimeoutMs: number,
155
158
  ): ConnectCommand {
156
159
  return {
157
160
  command: "connect",
@@ -161,6 +164,7 @@ function composeConnectMessage(
161
164
  },
162
165
  scopes,
163
166
  createScopes: [ScopeType.DocWrite, ScopeType.DocRead],
167
+ connectTimeoutMs,
164
168
  };
165
169
  }
166
170
 
@@ -255,6 +259,7 @@ export async function connectChildProcesses(
255
259
  const connectContainerCreator = composeConnectMessage(
256
260
  0,
257
261
  writeClients > 0 ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead],
262
+ /* connectTimeoutMs */ readyTimeoutMs,
258
263
  );
259
264
  firstChild.send(connectContainerCreator);
260
265
  }
@@ -264,7 +269,10 @@ export async function connectChildProcesses(
264
269
  durationMs: readyTimeoutMs,
265
270
  errorMsg: "did not receive 'connected' from child process",
266
271
  },
267
- );
272
+ ).catch(async (error) => {
273
+ await executeDebugReports([firstChild]);
274
+ throw error;
275
+ });
268
276
 
269
277
  const attendeeIdPromises: Promise<AttendeeId>[] = [];
270
278
  for (const [index, child] of childProcesses.entries()) {
@@ -275,6 +283,7 @@ export async function connectChildProcesses(
275
283
  const message = composeConnectMessage(
276
284
  index,
277
285
  index < writeClients ? [ScopeType.DocWrite, ScopeType.DocRead] : [ScopeType.DocRead],
286
+ /* connectTimeoutMs */ readyTimeoutMs,
278
287
  );
279
288
  message.containerId = containerId;
280
289
  attendeeIdPromises.push(
@@ -348,6 +357,10 @@ export async function connectAndListenForAttendees(
348
357
  readyTimeoutMs: childConnectTimeoutMs,
349
358
  });
350
359
 
360
+ // These actions are not awaited. They are here to provide additional logging.
361
+ // It is up to the caller to await attendeeIdPromises if desired. This can mean
362
+ // An "error" message is output, but the caller does not care about attendee
363
+ // ids and proceeds.
351
364
  Promise.all(connectResult.attendeeIdPromises)
352
365
  .then(() => console.log("All attendees connected."))
353
366
  .catch((error) => {