tutanota/test/tests/api/worker/crypto/OwnerEncSessionKeysUpdateQueueTest.ts

124 lines
5.2 KiB
TypeScript
Raw Normal View History

2023-06-29 18:26:45 +02:00
import o from "@tutao/otest"
2023-01-12 16:48:28 +01:00
import { IServiceExecutor } from "../../../../../src/api/common/ServiceRequest.js"
import { matchers, object, verify, when } from "testdouble"
import { UserFacade } from "../../../../../src/api/worker/facades/UserFacade.js"
import { OwnerEncSessionKeysUpdateQueue } from "../../../../../src/api/worker/crypto/OwnerEncSessionKeysUpdateQueue.js"
import { createInstanceSessionKey, createTypeInfo, InstanceSessionKeyTypeRef, TypeInfoTypeRef } from "../../../../../src/api/entities/sys/TypeRefs.js"
2023-01-12 16:48:28 +01:00
import { UpdateSessionKeysService } from "../../../../../src/api/entities/sys/Services.js"
import { delay } from "@tutao/tutanota-utils"
import { LockedError } from "../../../../../src/api/common/error/RestError.js"
import { createTestEntity } from "../../../TestUtils.js"
2023-01-12 16:48:28 +01:00
const { anything, captor } = matchers
o.spec("OwnerEncSessionKeysUpdateQueue", function () {
let serviceExecutor: IServiceExecutor
let ownerEncSessionKeysUpdateQueue: OwnerEncSessionKeysUpdateQueue
let userFacade: UserFacade
o.beforeEach(function () {
userFacade = object()
when(userFacade.isLeader()).thenReturn(true)
serviceExecutor = object()
ownerEncSessionKeysUpdateQueue = new OwnerEncSessionKeysUpdateQueue(userFacade, serviceExecutor, 0)
})
o.spec("updateInstanceSessionKeys", function () {
o("send updates from queue", async function () {
const updatableInstanceSessionKeys = [
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([4, 5, 6]),
}),
]
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys(updatableInstanceSessionKeys)
await delay(0)
const updatedPostCaptor = captor()
verify(serviceExecutor.post(UpdateSessionKeysService, updatedPostCaptor.capture()))
o(updatedPostCaptor.value.ownerEncSessionKeys).deepEquals(updatableInstanceSessionKeys)
})
o("no updates sent if not leader", async function () {
when(userFacade.isLeader()).thenReturn(false)
const updatableInstanceSessionKeys = [createTestEntity(InstanceSessionKeyTypeRef)]
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys(updatableInstanceSessionKeys)
await delay(0)
2023-01-12 16:48:28 +01:00
verify(serviceExecutor.post(anything(), anything()), { times: 0 })
})
o("retry after LockedError", async function () {
let throwError = true
when(serviceExecutor.post(UpdateSessionKeysService, anything())).thenDo(() => {
if (throwError) {
return Promise.reject(new LockedError("test lock"))
} else {
return undefined
}
})
const updatableInstanceSessionKeys = [
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([4, 5, 6]),
}),
]
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys(updatableInstanceSessionKeys)
await delay(0)
throwError = false
when(serviceExecutor.post(UpdateSessionKeysService, anything())).thenResolve(undefined)
await delay(0)
const updatedPostCaptor = captor()
2023-01-12 16:48:28 +01:00
verify(serviceExecutor.post(UpdateSessionKeysService, updatedPostCaptor.capture()), { times: 2 })
o(updatedPostCaptor.value.ownerEncSessionKeys).deepEquals(updatableInstanceSessionKeys)
if (!updatedPostCaptor.values) {
throw new Error("should have been invoked twice")
}
o(updatedPostCaptor.values[0]).deepEquals(updatedPostCaptor.values[1])
})
o("debounced request sends entire queue", async function () {
const updatableInstanceSessionKeys = [
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "mailInstanceId",
instanceList: "mailInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([1, 2, 3]),
}),
createTestEntity(InstanceSessionKeyTypeRef, {
instanceId: "fileInstanceId",
instanceList: "fileInstanceList",
typeInfo: createTestEntity(TypeInfoTypeRef),
2023-01-12 16:48:28 +01:00
symEncSessionKey: new Uint8Array([4, 5, 6]),
}),
]
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys([updatableInstanceSessionKeys[0]])
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys([updatableInstanceSessionKeys[1]])
await delay(0)
const updatedPostCaptor = captor()
verify(serviceExecutor.post(UpdateSessionKeysService, updatedPostCaptor.capture()))
o(updatedPostCaptor.value.ownerEncSessionKeys).deepEquals(updatableInstanceSessionKeys)
})
o("empty inputs do not trigger a call to the service", async function () {
ownerEncSessionKeysUpdateQueue.updateInstanceSessionKeys([])
await delay(0)
2023-01-12 16:48:28 +01:00
verify(serviceExecutor.post(UpdateSessionKeysService, anything()), { times: 0 })
})
})
})