test(matrix): share client startup and backfill fixtures

This commit is contained in:
Vincent Koc
2026-04-12 09:24:32 +01:00
parent b5dfeaab4c
commit 4cfebae118
2 changed files with 107 additions and 121 deletions

View File

@@ -70,6 +70,24 @@ function primeAccountClientMocks(params?: {
return { mainAuth, opsAuth, mainClient, opsClient };
}
function createPendingSharedStartup(mainAuth = authFor("main")) {
let resolveStartup: (() => void) | undefined;
const mainClient = {
...createMockClient("main"),
start: vi.fn(
async () =>
await new Promise<void>((resolve) => {
resolveStartup = resolve;
}),
),
};
resolveMatrixAuthMock.mockResolvedValue(mainAuth);
createMatrixClientMock.mockResolvedValue(mainClient);
return { mainClient, resolveStartup: () => resolveStartup?.() };
}
describe("resolveSharedMatrixClient", () => {
beforeAll(async () => {
({
@@ -234,25 +252,11 @@ describe("resolveSharedMatrixClient", () => {
});
it("lets a later waiter abort while shared startup continues for the owner", async () => {
const mainAuth = authFor("main");
let resolveStartup: (() => void) | undefined;
const mainClient = {
...createMockClient("main"),
start: vi.fn(
async () =>
await new Promise<void>((resolve) => {
resolveStartup = resolve;
}),
),
};
resolveMatrixAuthMock.mockResolvedValue(mainAuth);
createMatrixClientMock.mockResolvedValue(mainClient);
const { mainClient, resolveStartup } = createPendingSharedStartup();
const ownerPromise = resolveSharedMatrixClient({ accountId: "main" });
await vi.waitFor(() => {
expect(mainClient.start).toHaveBeenCalledTimes(1);
expect(resolveStartup).toEqual(expect.any(Function));
});
const abortController = new AbortController();
@@ -267,30 +271,16 @@ describe("resolveSharedMatrixClient", () => {
name: "AbortError",
});
resolveStartup?.();
resolveStartup();
await expect(ownerPromise).resolves.toBe(mainClient);
});
it("keeps the shared startup lock while an aborted waiter exits early", async () => {
const mainAuth = authFor("main");
let resolveStartup: (() => void) | undefined;
const mainClient = {
...createMockClient("main"),
start: vi.fn(
async () =>
await new Promise<void>((resolve) => {
resolveStartup = resolve;
}),
),
};
resolveMatrixAuthMock.mockResolvedValue(mainAuth);
createMatrixClientMock.mockResolvedValue(mainClient);
const { mainClient, resolveStartup } = createPendingSharedStartup();
const ownerPromise = resolveSharedMatrixClient({ accountId: "main" });
await vi.waitFor(() => {
expect(mainClient.start).toHaveBeenCalledTimes(1);
expect(resolveStartup).toEqual(expect.any(Function));
});
const abortController = new AbortController();
@@ -307,7 +297,7 @@ describe("resolveSharedMatrixClient", () => {
const followerPromise = resolveSharedMatrixClient({ accountId: "main" });
expect(mainClient.start).toHaveBeenCalledTimes(1);
resolveStartup?.();
resolveStartup();
await expect(ownerPromise).resolves.toBe(mainClient);
await expect(followerPromise).resolves.toBe(mainClient);
expect(mainClient.start).toHaveBeenCalledTimes(1);

View File

@@ -129,6 +129,85 @@ describe("matrix client storage paths", () => {
});
}
function setupCurrentTokenBackfillScenario(params: {
currentRootFiles: "thread-bindings" | "startup-verification";
oldRootFiles: "crypto-only" | "thread-bindings";
}) {
const stateDir = setupStateDir();
const canonicalPaths = resolveMatrixAccountStorageRoot({
stateDir,
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accessToken: "secret-token-new",
});
fs.mkdirSync(canonicalPaths.rootDir, { recursive: true });
writeJson(canonicalPaths.rootDir, "storage-meta.json", {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: canonicalPaths.tokenHash,
deviceId: null,
});
if (params.currentRootFiles === "thread-bindings") {
writeJson(canonicalPaths.rootDir, "thread-bindings.json", {
version: 1,
bindings: [
{
accountId: "default",
conversationId: "$thread-new",
targetKind: "subagent",
targetSessionKey: "agent:ops:subagent:new",
boundAt: 1,
lastActivityAt: 1,
},
],
});
expect(
claimCurrentTokenStorageState({
rootDir: canonicalPaths.rootDir,
}),
).toBe(true);
} else {
writeJson(canonicalPaths.rootDir, "startup-verification.json", {
deviceId: "DEVICE123",
});
}
const oldStoragePaths = seedExistingStorageRoot({
accessToken: "secret-token-old",
deviceId: "DEVICE123",
storageMeta: {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash,
deviceId: "DEVICE123",
},
});
fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true });
if (params.oldRootFiles === "thread-bindings") {
writeJson(oldStoragePaths.rootDir, "thread-bindings.json", {
version: 1,
bindings: [
{
accountId: "default",
conversationId: "$thread-old",
targetKind: "subagent",
targetSessionKey: "agent:ops:subagent:old",
boundAt: 1,
lastActivityAt: 1,
},
],
});
} else {
writeJson(oldStoragePaths.rootDir, "startup-verification.json", {
deviceId: "DEVICE123",
});
}
return { stateDir, canonicalPaths, oldStoragePaths };
}
it("resolves state file paths inside the selected storage root", () => {
setupStateDir();
const filePath = resolveMatrixStateFilePath({
@@ -497,53 +576,9 @@ describe("matrix client storage paths", () => {
});
it("keeps the current-token storage root stable after deviceId backfill when startup claimed state there", () => {
const stateDir = setupStateDir();
const canonicalPaths = resolveMatrixAccountStorageRoot({
stateDir,
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accessToken: "secret-token-new",
});
fs.mkdirSync(canonicalPaths.rootDir, { recursive: true });
writeJson(canonicalPaths.rootDir, "storage-meta.json", {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: canonicalPaths.tokenHash,
deviceId: null,
});
writeJson(canonicalPaths.rootDir, "thread-bindings.json", {
version: 1,
bindings: [
{
accountId: "default",
conversationId: "$thread-new",
targetKind: "subagent",
targetSessionKey: "agent:ops:subagent:new",
boundAt: 1,
lastActivityAt: 1,
},
],
});
expect(
claimCurrentTokenStorageState({
rootDir: canonicalPaths.rootDir,
}),
).toBe(true);
const oldStoragePaths = seedExistingStorageRoot({
accessToken: "secret-token-old",
deviceId: "DEVICE123",
storageMeta: {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash,
deviceId: "DEVICE123",
},
});
fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true });
writeJson(oldStoragePaths.rootDir, "startup-verification.json", {
deviceId: "DEVICE123",
const { stateDir, canonicalPaths } = setupCurrentTokenBackfillScenario({
currentRootFiles: "thread-bindings",
oldRootFiles: "crypto-only",
});
repairCurrentTokenStorageMetaDeviceId({
@@ -572,48 +607,9 @@ describe("matrix client storage paths", () => {
});
it("does not keep the current-token storage root sticky when only marker files exist after backfill", () => {
const stateDir = setupStateDir();
const canonicalPaths = resolveMatrixAccountStorageRoot({
stateDir,
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accessToken: "secret-token-new",
});
fs.mkdirSync(canonicalPaths.rootDir, { recursive: true });
writeJson(canonicalPaths.rootDir, "storage-meta.json", {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: canonicalPaths.tokenHash,
deviceId: null,
});
writeJson(canonicalPaths.rootDir, "startup-verification.json", {
deviceId: "DEVICE123",
});
const oldStoragePaths = seedExistingStorageRoot({
accessToken: "secret-token-old",
deviceId: "DEVICE123",
storageMeta: {
homeserver: defaultStorageAuth.homeserver,
userId: defaultStorageAuth.userId,
accountId: "default",
accessTokenHash: resolveDefaultStoragePaths({ accessToken: "secret-token-old" }).tokenHash,
deviceId: "DEVICE123",
},
});
fs.mkdirSync(oldStoragePaths.cryptoPath, { recursive: true });
writeJson(oldStoragePaths.rootDir, "thread-bindings.json", {
version: 1,
bindings: [
{
accountId: "default",
conversationId: "$thread-old",
targetKind: "subagent",
targetSessionKey: "agent:ops:subagent:old",
boundAt: 1,
lastActivityAt: 1,
},
],
const { stateDir, oldStoragePaths } = setupCurrentTokenBackfillScenario({
currentRootFiles: "startup-verification",
oldRootFiles: "thread-bindings",
});
repairCurrentTokenStorageMetaDeviceId({