fix(app-state) - missing key Blocked state, history sync status & 120s timeout
fix(app-state) - missing key Blocked state, history sync status & 120s timeout
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
decodeSyncdPatch,
|
||||
decodeSyncdSnapshot,
|
||||
isAppStateSyncIrrecoverable,
|
||||
isMissingKeyError,
|
||||
MAX_SYNC_ATTEMPTS,
|
||||
newLTHashState
|
||||
} from '../../Utils/chat-utils'
|
||||
@@ -12,8 +13,8 @@ import {
|
||||
const missingKeyFn = async () => null
|
||||
|
||||
describe('App State Sync', () => {
|
||||
describe('missing key errors throw with statusCode 404', () => {
|
||||
it('decodeSyncdPatch throws 404 on missing key', async () => {
|
||||
describe('missing key errors are marked with isMissingKey (Blocked in WA Web)', () => {
|
||||
it('decodeSyncdPatch throws with isMissingKey on missing key', async () => {
|
||||
const msg: proto.ISyncdPatch = {
|
||||
keyId: { id: Buffer.from('missing-key') },
|
||||
mutations: [],
|
||||
@@ -22,12 +23,15 @@ describe('App State Sync', () => {
|
||||
patchMac: Buffer.alloc(32)
|
||||
}
|
||||
|
||||
await expect(
|
||||
decodeSyncdPatch(msg, 'regular_low', newLTHashState(), missingKeyFn, () => {}, true)
|
||||
).rejects.toMatchObject({ output: { statusCode: 404 } })
|
||||
try {
|
||||
await decodeSyncdPatch(msg, 'regular_low', newLTHashState(), missingKeyFn, () => {}, true)
|
||||
fail('should have thrown')
|
||||
} catch (error: any) {
|
||||
expect(isMissingKeyError(error)).toBe(true)
|
||||
}
|
||||
})
|
||||
|
||||
it('decodeSyncdSnapshot throws 404 on missing snapshot key', async () => {
|
||||
it('decodeSyncdSnapshot throws with isMissingKey on missing snapshot key', async () => {
|
||||
const snapshot: proto.ISyncdSnapshot = {
|
||||
version: { version: 1 as any },
|
||||
records: [],
|
||||
@@ -35,12 +39,15 @@ describe('App State Sync', () => {
|
||||
mac: Buffer.alloc(32)
|
||||
}
|
||||
|
||||
await expect(decodeSyncdSnapshot('regular_low', snapshot, missingKeyFn, undefined, true)).rejects.toMatchObject({
|
||||
output: { statusCode: 404 }
|
||||
})
|
||||
try {
|
||||
await decodeSyncdSnapshot('regular_low', snapshot, missingKeyFn, undefined, true)
|
||||
fail('should have thrown')
|
||||
} catch (error: any) {
|
||||
expect(isMissingKeyError(error)).toBe(true)
|
||||
}
|
||||
})
|
||||
|
||||
it('decodeSyncdMutations throws 404 on missing mutation key', async () => {
|
||||
it('decodeSyncdMutations throws with isMissingKey on missing mutation key', async () => {
|
||||
const records: proto.ISyncdRecord[] = [
|
||||
{
|
||||
keyId: { id: Buffer.from('missing-key') },
|
||||
@@ -49,29 +56,36 @@ describe('App State Sync', () => {
|
||||
}
|
||||
]
|
||||
|
||||
await expect(decodeSyncdMutations(records, newLTHashState(), missingKeyFn, () => {}, true)).rejects.toMatchObject(
|
||||
{ output: { statusCode: 404 } }
|
||||
)
|
||||
try {
|
||||
await decodeSyncdMutations(records, newLTHashState(), missingKeyFn, () => {}, true)
|
||||
fail('should have thrown')
|
||||
} catch (error: any) {
|
||||
expect(isMissingKeyError(error)).toBe(true)
|
||||
}
|
||||
})
|
||||
|
||||
it('decodeSyncdMutations throws 404 even with validateMacs=false', async () => {
|
||||
const records: proto.ISyncdRecord[] = [
|
||||
{
|
||||
keyId: { id: Buffer.from('missing-key') },
|
||||
value: { blob: Buffer.alloc(64) },
|
||||
index: { blob: Buffer.alloc(32) }
|
||||
}
|
||||
]
|
||||
|
||||
await expect(
|
||||
decodeSyncdMutations(records, newLTHashState(), missingKeyFn, () => {}, false)
|
||||
).rejects.toMatchObject({ output: { statusCode: 404 } })
|
||||
it('missing key errors are NOT irrecoverable on first attempt', async () => {
|
||||
const error = new Boom('missing key', { data: { isMissingKey: true } })
|
||||
expect(isMissingKeyError(error)).toBe(true)
|
||||
expect(isAppStateSyncIrrecoverable(error, 1)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isAppStateSyncIrrecoverable', () => {
|
||||
it.each([400, 404, 405, 406])('should be irrecoverable for status %d on first attempt', statusCode => {
|
||||
expect(isAppStateSyncIrrecoverable(new Boom('test', { statusCode }), 1)).toBe(true)
|
||||
it('should NOT be irrecoverable for status 400 (dead code path removed)', () => {
|
||||
expect(isAppStateSyncIrrecoverable(new Boom('test', { statusCode: 400 }), 1)).toBe(false)
|
||||
})
|
||||
|
||||
it('should NOT be irrecoverable for status 404 (missing key is Blocked, not Fatal)', () => {
|
||||
expect(isAppStateSyncIrrecoverable(new Boom('test', { statusCode: 404 }), 1)).toBe(false)
|
||||
})
|
||||
|
||||
it('should NOT be irrecoverable for status 405', () => {
|
||||
expect(isAppStateSyncIrrecoverable(new Boom('test', { statusCode: 405 }), 1)).toBe(false)
|
||||
})
|
||||
|
||||
it('should NOT be irrecoverable for status 406', () => {
|
||||
expect(isAppStateSyncIrrecoverable(new Boom('test', { statusCode: 406 }), 1)).toBe(false)
|
||||
})
|
||||
|
||||
it('should be irrecoverable for TypeError', () => {
|
||||
|
||||
Reference in New Issue
Block a user