test(core): more transport tests
This commit is contained in:
parent
6ca430eb05
commit
08d3afadd8
6 changed files with 496 additions and 2 deletions
|
@ -421,7 +421,7 @@ async function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for await (const file of getFiles(path.join(__dirname, '../src/methods'))) {
|
for await (const file of getFiles(path.join(__dirname, '../src/methods'))) {
|
||||||
if (!file.startsWith('.') && file.endsWith('.ts') && !file.endsWith('.web.ts')) {
|
if (!file.startsWith('.') && file.endsWith('.ts') && !file.endsWith('.web.ts') && !file.endsWith('.test.ts')) {
|
||||||
await addSingleMethod(state, file)
|
await addSingleMethod(state, file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
197
packages/core/src/network/transports/obfuscated.test.ts
Normal file
197
packages/core/src/network/transports/obfuscated.test.ts
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
|
||||||
|
import { defaultTestCryptoProvider, u8HexDecode } from '../../utils/crypto/crypto.test-utils.js'
|
||||||
|
import { hexDecodeToBuffer, hexEncode, LogManager } from '../../utils/index.js'
|
||||||
|
import { IntermediatePacketCodec } from './intermediate.js'
|
||||||
|
import { MtProxyInfo, ObfuscatedPacketCodec } from './obfuscated.js'
|
||||||
|
|
||||||
|
describe('ObfuscatedPacketCodec', () => {
|
||||||
|
const create = async (randomSource?: string, proxy?: MtProxyInfo) => {
|
||||||
|
const codec = new ObfuscatedPacketCodec(new IntermediatePacketCodec(), proxy)
|
||||||
|
const crypto = await defaultTestCryptoProvider(randomSource)
|
||||||
|
codec.setup(crypto, new LogManager())
|
||||||
|
|
||||||
|
return [codec, crypto] as const
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('tag', () => {
|
||||||
|
it('should correctly generate random initial payload', async () => {
|
||||||
|
const random = 'ff'.repeat(64)
|
||||||
|
const [codec] = await create(random)
|
||||||
|
|
||||||
|
const tag = await codec.tag()
|
||||||
|
|
||||||
|
expect(hexEncode(tag)).toEqual(
|
||||||
|
'ff'.repeat(56) + 'fce8ab2203db2bff', // encrypted part
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mtproxy', () => {
|
||||||
|
it('should correctly generate random initial payload for prod dc', async () => {
|
||||||
|
const random = 'ff'.repeat(64)
|
||||||
|
const proxy: MtProxyInfo = {
|
||||||
|
dcId: 1,
|
||||||
|
secret: new Uint8Array(16),
|
||||||
|
test: false,
|
||||||
|
media: false,
|
||||||
|
}
|
||||||
|
const [codec] = await create(random, proxy)
|
||||||
|
|
||||||
|
const tag = await codec.tag()
|
||||||
|
|
||||||
|
expect(hexEncode(tag)).toEqual(
|
||||||
|
'ff'.repeat(56) + 'ecec4cbda8bb188b', // encrypted part with dcId = 1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly generate random initial payload for test dc', async () => {
|
||||||
|
const random = 'ff'.repeat(64)
|
||||||
|
const proxy: MtProxyInfo = {
|
||||||
|
dcId: 1,
|
||||||
|
secret: new Uint8Array(16),
|
||||||
|
test: true,
|
||||||
|
media: false,
|
||||||
|
}
|
||||||
|
const [codec] = await create(random, proxy)
|
||||||
|
|
||||||
|
const tag = await codec.tag()
|
||||||
|
|
||||||
|
expect(hexEncode(tag)).toEqual(
|
||||||
|
'ff'.repeat(56) + 'ecec4cbdb89c188b', // encrypted part with dcId = 10001
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly generate random initial payload for media dc', async () => {
|
||||||
|
const random = 'ff'.repeat(64)
|
||||||
|
const proxy: MtProxyInfo = {
|
||||||
|
dcId: 1,
|
||||||
|
secret: new Uint8Array(16),
|
||||||
|
test: false,
|
||||||
|
media: true,
|
||||||
|
}
|
||||||
|
const [codec] = await create(random, proxy)
|
||||||
|
|
||||||
|
const tag = await codec.tag()
|
||||||
|
|
||||||
|
expect(hexEncode(tag)).toEqual(
|
||||||
|
'ff'.repeat(56) + 'ecec4cbd5644188b', // encrypted part with dcId = -1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['ef'],
|
||||||
|
['48454144'],
|
||||||
|
['504f5354'],
|
||||||
|
['47455420'],
|
||||||
|
['4f505449'],
|
||||||
|
['dddddddd'],
|
||||||
|
['eeeeeeee'],
|
||||||
|
['16030102'],
|
||||||
|
])('should correctly retry for %s prefix', async (prefix) => {
|
||||||
|
const random = prefix + 'ff'.repeat(64 - prefix.length / 2)
|
||||||
|
const [codec] = await create(random)
|
||||||
|
|
||||||
|
// generating random payload requires 64 bytes of entropy, so
|
||||||
|
// if it asks for more, it means it tried to generate it again
|
||||||
|
await expect(() => codec.tag()).rejects.toThrow('not enough entropy')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly create aes ctr', async () => {
|
||||||
|
const [codec, crypto] = await create()
|
||||||
|
|
||||||
|
const spyCreateAesCtr = vi.spyOn(crypto, 'createAesCtr')
|
||||||
|
|
||||||
|
await codec.tag()
|
||||||
|
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenCalledTimes(2)
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
u8HexDecode('10b6b4ad6d56ef5df9453f88e6ee6adb6e0544ba635dc6a8a990c9b8b980c343'),
|
||||||
|
u8HexDecode('936b33fa7f97bae025102532233abb26'),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
u8HexDecode('26bb3a2332251025e0ba977ffa336b9343c380b9b8c990a9a8c65d63ba44056e'),
|
||||||
|
u8HexDecode('db6aeee6883f45f95def566dadb4b610'),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly create aes ctr for mtproxy', async () => {
|
||||||
|
const proxy: MtProxyInfo = {
|
||||||
|
dcId: 1,
|
||||||
|
secret: hexDecodeToBuffer('00112233445566778899aabbccddeeff'),
|
||||||
|
test: true,
|
||||||
|
media: false,
|
||||||
|
}
|
||||||
|
const [codec, crypto] = await create(undefined, proxy)
|
||||||
|
|
||||||
|
const spyCreateAesCtr = vi.spyOn(crypto, 'createAesCtr')
|
||||||
|
|
||||||
|
await codec.tag()
|
||||||
|
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenCalledTimes(2)
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
hexDecodeToBuffer('dd03188944590983e28dad14d97d0952389d118af4ffcbdb28d56a6a612ef7a6'),
|
||||||
|
u8HexDecode('936b33fa7f97bae025102532233abb26'),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
expect(spyCreateAesCtr).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
hexDecodeToBuffer('413b8e08021fbb08a2962b6d7187194fe46565c6b329d3bbdfcffd4870c16119'),
|
||||||
|
u8HexDecode('db6aeee6883f45f95def566dadb4b610'),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly encrypt the underlying codec', async () => {
|
||||||
|
const data = hexDecodeToBuffer('6cfeffff')
|
||||||
|
const msg1 = 'a1020630a410e940'
|
||||||
|
const msg2 = 'f53ff53f371db495'
|
||||||
|
|
||||||
|
const [codec] = await create()
|
||||||
|
|
||||||
|
await codec.tag()
|
||||||
|
|
||||||
|
expect(hexEncode(await codec.encode(data))).toEqual(msg1)
|
||||||
|
expect(hexEncode(await codec.encode(data))).toEqual(msg2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly decrypt the underlying codec', async () => {
|
||||||
|
const msg1 = 'e8027df708ab3b5c'
|
||||||
|
const msg2 = '1854be76d2df4949'
|
||||||
|
|
||||||
|
const [codec] = await create()
|
||||||
|
|
||||||
|
await codec.tag()
|
||||||
|
|
||||||
|
const log: string[] = []
|
||||||
|
|
||||||
|
codec.on('error', (e: Error) => {
|
||||||
|
log.push(e.toString())
|
||||||
|
})
|
||||||
|
|
||||||
|
codec.feed(hexDecodeToBuffer(msg1))
|
||||||
|
codec.feed(hexDecodeToBuffer(msg2))
|
||||||
|
|
||||||
|
await vi.waitFor(() => expect(log).toEqual(['Error: Transport error: 404', 'Error: Transport error: 404']))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly reset', async () => {
|
||||||
|
const inner = new IntermediatePacketCodec()
|
||||||
|
const spyInnerReset = vi.spyOn(inner, 'reset')
|
||||||
|
|
||||||
|
const codec = new ObfuscatedPacketCodec(inner)
|
||||||
|
codec.setup(await defaultTestCryptoProvider(), new LogManager())
|
||||||
|
|
||||||
|
await codec.tag()
|
||||||
|
|
||||||
|
codec.reset()
|
||||||
|
|
||||||
|
expect(spyInnerReset).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
})
|
|
@ -30,7 +30,7 @@ export class ObfuscatedPacketCodec extends WrappedCodec implements IPacketCodec
|
||||||
if (random[0] === 0xef) continue
|
if (random[0] === 0xef) continue
|
||||||
|
|
||||||
dv = dataViewFromBuffer(random)
|
dv = dataViewFromBuffer(random)
|
||||||
const firstInt = dv.getInt32(0, true)
|
const firstInt = dv.getUint32(0, true)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
firstInt === 0x44414548 || // HEAD
|
firstInt === 0x44414548 || // HEAD
|
||||||
|
|
149
packages/core/src/network/transports/tcp.test.ts
Normal file
149
packages/core/src/network/transports/tcp.test.ts
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
import { Socket } from 'net'
|
||||||
|
import { describe, expect, it, MockedObject, vi } from 'vitest'
|
||||||
|
|
||||||
|
import { defaultTestCryptoProvider, u8HexDecode } from '../../utils/crypto/crypto.test-utils.js'
|
||||||
|
import { defaultProductionDc, hexDecodeToBuffer, LogManager } from '../../utils/index.js'
|
||||||
|
import { TransportState } from './abstract.js'
|
||||||
|
import { TcpTransport } from './tcp.js'
|
||||||
|
|
||||||
|
vi.mock('net', () => ({
|
||||||
|
connect: vi.fn().mockImplementation((port: number, ip: string, cb: () => void) => {
|
||||||
|
cb()
|
||||||
|
|
||||||
|
return {
|
||||||
|
on: vi.fn(),
|
||||||
|
write: vi.fn().mockImplementation((data: Uint8Array, cb: () => void) => {
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
end: vi.fn(),
|
||||||
|
removeAllListeners: vi.fn(),
|
||||||
|
destroy: vi.fn(),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('TcpTransport', async () => {
|
||||||
|
const net = await import('net')
|
||||||
|
const connect = vi.mocked(net.connect)
|
||||||
|
|
||||||
|
const getLastSocket = () => {
|
||||||
|
return connect.mock.results[connect.mock.results.length - 1].value as MockedObject<Socket>
|
||||||
|
}
|
||||||
|
|
||||||
|
const create = async () => {
|
||||||
|
const transport = new TcpTransport()
|
||||||
|
const logger = new LogManager()
|
||||||
|
logger.level = 0
|
||||||
|
transport.setup(await defaultTestCryptoProvider(), logger)
|
||||||
|
|
||||||
|
return transport
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should initiate a tcp connection to the given dc', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
|
||||||
|
expect(connect).toHaveBeenCalledOnce()
|
||||||
|
expect(connect).toHaveBeenCalledWith(
|
||||||
|
defaultProductionDc.main.port,
|
||||||
|
defaultProductionDc.main.ipAddress,
|
||||||
|
expect.any(Function),
|
||||||
|
)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should set up event handlers', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
expect(socket.on).toHaveBeenCalledTimes(3)
|
||||||
|
expect(socket.on).toHaveBeenCalledWith('data', expect.any(Function))
|
||||||
|
expect(socket.on).toHaveBeenCalledWith('error', expect.any(Function))
|
||||||
|
expect(socket.on).toHaveBeenCalledWith('close', expect.any(Function))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should write packet codec tag once connected', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
await vi.waitFor(() =>
|
||||||
|
expect(socket.write).toHaveBeenCalledWith(
|
||||||
|
u8HexDecode('eeeeeeee'), // intermediate
|
||||||
|
expect.any(Function),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should write to the underlying socket', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
await t.send(hexDecodeToBuffer('00010203040506070809'))
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
expect(socket.write).toHaveBeenCalledWith(u8HexDecode('0a00000000010203040506070809'), expect.any(Function))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly close', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
t.close()
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
expect(socket.removeAllListeners).toHaveBeenCalledOnce()
|
||||||
|
expect(socket.destroy).toHaveBeenCalledOnce()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should feed data to the packet codec', async () => {
|
||||||
|
const t = await create()
|
||||||
|
const codec = t._packetCodec
|
||||||
|
|
||||||
|
const spyFeed = vi.spyOn(codec, 'feed')
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
const onDataCall = socket.on.mock.calls.find((c) => (c as string[])[0] === 'data') as unknown as [
|
||||||
|
string,
|
||||||
|
(data: Uint8Array) => void,
|
||||||
|
]
|
||||||
|
onDataCall[1](u8HexDecode('00010203040506070809'))
|
||||||
|
|
||||||
|
expect(spyFeed).toHaveBeenCalledWith(u8HexDecode('00010203040506070809'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should propagate errors', async () => {
|
||||||
|
const t = await create()
|
||||||
|
|
||||||
|
const spyEmit = vi.spyOn(t, 'emit').mockImplementation(() => true)
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
const socket = getLastSocket()
|
||||||
|
|
||||||
|
const onErrorCall = socket.on.mock.calls.find((c) => (c as string[])[0] === 'error') as unknown as [
|
||||||
|
string,
|
||||||
|
(error: Error) => void,
|
||||||
|
]
|
||||||
|
onErrorCall[1](new Error('test error'))
|
||||||
|
|
||||||
|
expect(spyEmit).toHaveBeenCalledWith('error', new Error('test error'))
|
||||||
|
})
|
||||||
|
})
|
133
packages/core/src/network/transports/websocket.test.ts
Normal file
133
packages/core/src/network/transports/websocket.test.ts
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
import { describe, expect, it, Mock, MockedObject, vi } from 'vitest'
|
||||||
|
|
||||||
|
import { defaultTestCryptoProvider, u8HexDecode } from '../../utils/crypto/crypto.test-utils.js'
|
||||||
|
import { defaultProductionDc, hexDecodeToBuffer, LogManager } from '../../utils/index.js'
|
||||||
|
import { TransportState } from './abstract.js'
|
||||||
|
import { WebSocketTransport } from './websocket.js'
|
||||||
|
|
||||||
|
describe('WebSocketTransport', () => {
|
||||||
|
const create = async () => {
|
||||||
|
const fakeWs = vi.fn().mockImplementation(() => ({
|
||||||
|
addEventListener: vi.fn().mockImplementation((event: string, cb: () => void) => {
|
||||||
|
if (event === 'open') {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
removeEventListener: vi.fn(),
|
||||||
|
close: vi.fn(),
|
||||||
|
send: vi.fn(),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const transport = new WebSocketTransport({ ws: fakeWs })
|
||||||
|
const logger = new LogManager()
|
||||||
|
logger.level = 0
|
||||||
|
transport.setup(await defaultTestCryptoProvider(), logger)
|
||||||
|
|
||||||
|
return [transport, fakeWs] as const
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLastSocket = (ws: Mock) => {
|
||||||
|
return ws.mock.results[ws.mock.results.length - 1].value as MockedObject<WebSocket>
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should initiate a websocket connection to the given dc', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
|
||||||
|
expect(ws).toHaveBeenCalledOnce()
|
||||||
|
expect(ws).toHaveBeenCalledWith('wss://venus.web.telegram.org/apiws', 'binary')
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should set up event handlers', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
|
||||||
|
expect(socket.addEventListener).toHaveBeenCalledWith('message', expect.any(Function))
|
||||||
|
expect(socket.addEventListener).toHaveBeenCalledWith('error', expect.any(Function))
|
||||||
|
expect(socket.addEventListener).toHaveBeenCalledWith('close', expect.any(Function))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should write packet codec tag to the socket', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
|
||||||
|
await vi.waitFor(() =>
|
||||||
|
expect(socket.send).toHaveBeenCalledWith(
|
||||||
|
u8HexDecode(
|
||||||
|
'29afd26df40fb8ed10b6b4ad6d56ef5df9453f88e6ee6adb6e0544ba635dc6a8a990c9b8b980c343936b33fa7f97bae025102532233abb26d4a1fe6d34f1ba08',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should write to the underlying socket', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
await t.send(hexDecodeToBuffer('00010203040506070809'))
|
||||||
|
|
||||||
|
expect(socket.send).toHaveBeenCalledWith(hexDecodeToBuffer('af020630c8ef14bcf53af33853ea'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly close', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
t.close()
|
||||||
|
|
||||||
|
expect(socket.removeEventListener).toHaveBeenCalled()
|
||||||
|
expect(socket.close).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should correctly handle incoming messages', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
const feedSpy = vi.spyOn(t._packetCodec, 'feed')
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
const data = hexDecodeToBuffer('00010203040506070809')
|
||||||
|
const message = new MessageEvent('message', { data })
|
||||||
|
|
||||||
|
const onMessageCall = socket.addEventListener.mock.calls.find(([event]) => event === 'message') as unknown as [
|
||||||
|
string,
|
||||||
|
(evt: MessageEvent) => void,
|
||||||
|
]
|
||||||
|
onMessageCall[1](message)
|
||||||
|
|
||||||
|
expect(feedSpy).toHaveBeenCalledWith(u8HexDecode('00010203040506070809'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should propagate errors', async () => {
|
||||||
|
const [t, ws] = await create()
|
||||||
|
|
||||||
|
const spyEmit = vi.spyOn(t, 'emit').mockImplementation(() => true)
|
||||||
|
|
||||||
|
t.connect(defaultProductionDc.main, false)
|
||||||
|
const socket = getLastSocket(ws)
|
||||||
|
await vi.waitFor(() => expect(t.state()).toEqual(TransportState.Ready))
|
||||||
|
|
||||||
|
const error = new Error('test')
|
||||||
|
const onErrorCall = socket.addEventListener.mock.calls.find(([event]) => event === 'error') as unknown as [
|
||||||
|
string,
|
||||||
|
(evt: { error: Error }) => void,
|
||||||
|
]
|
||||||
|
onErrorCall[1]({ error })
|
||||||
|
|
||||||
|
expect(spyEmit).toHaveBeenCalledWith('error', error)
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable no-restricted-globals */
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { gzipSync, inflateSync } from 'zlib'
|
import { gzipSync, inflateSync } from 'zlib'
|
||||||
|
|
||||||
|
@ -32,6 +33,10 @@ export function withFakeRandom(provider: ICryptoProvider, source = DEFAULT_ENTRO
|
||||||
let offset = 0
|
let offset = 0
|
||||||
|
|
||||||
function getRandomValues(buf: Uint8Array) {
|
function getRandomValues(buf: Uint8Array) {
|
||||||
|
if (offset + buf.length > sourceBytes.length) {
|
||||||
|
throw new Error('not enough entropy')
|
||||||
|
}
|
||||||
|
|
||||||
buf.set(sourceBytes.subarray(offset, offset + buf.length))
|
buf.set(sourceBytes.subarray(offset, offset + buf.length))
|
||||||
offset += buf.length
|
offset += buf.length
|
||||||
}
|
}
|
||||||
|
@ -216,3 +221,13 @@ export function testCryptoProvider(c: ICryptoProvider): void {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function u8HexDecode(hex: string) {
|
||||||
|
const buf = hexDecodeToBuffer(hex)
|
||||||
|
|
||||||
|
if (Buffer.isBuffer(buf)) {
|
||||||
|
return new Uint8Array(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue