Skip to content

Commit

Permalink
chore: test receiving invalid invites
Browse files Browse the repository at this point in the history
We shouldn't choke on invalid messages, such as invites. This code
worked but was untested.

I needed to put up some additional scaffolding to make this testable.

Closes [#514].

[#514]: #514
  • Loading branch information
EvanHahn committed Apr 16, 2024
1 parent f7ff572 commit 9c31b99
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
25 changes: 24 additions & 1 deletion src/local-peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ class Peer {
this.#connected.reject(new PeerFailedConnectionError())
this.#log('disconnected')
}
/**
* Exposed for tests.
* @param {Buffer} buf
*/
__sendRawInvite(buf) {
this.#assertConnected()
const messageType = MESSAGE_TYPES.Invite
this.#channel.messages[messageType].send(buf)
}
/** @param {Invite} invite */
sendInvite(invite) {
this.#assertConnected()
Expand Down Expand Up @@ -213,6 +222,7 @@ class Peer {
* @property {(peerId: string, inviteResponse: InviteResponse) => void} invite-response Emitted when an invite response is received
* @property {(peerId: string, details: ProjectJoinDetails) => void} got-project-details Emitted when project details are received
* @property {(discoveryKey: Buffer, protomux: Protomux<import('@hyperswarm/secret-stream')>) => void} discovery-key Emitted when a new hypercore is replicated (by a peer) to a peer protomux instance (passed as the second parameter)
* @property {(messageType: string, errorMessage?: string) => void} failed-to-handle-message Emitted when we received a message we couldn't handle for some reason. Primarily useful for testing
*/

/** @extends {TypedEmitter<LocalPeersEvents>} */
Expand Down Expand Up @@ -301,6 +311,17 @@ export class LocalPeers extends TypedEmitter {
peer.sendDeviceInfo(deviceInfo)
}

/**
* Used for tests.
* @param {string} deviceId
* @param {Buffer} buf
*/
async __sendRawInvite(deviceId, buf) {
await this.#waitForPendingConnections()
const peer = await this.#getPeerByDeviceId(deviceId)
peer.__sendRawInvite(buf)
}

/**
* Connect to a peer over an existing NoiseSecretStream
*
Expand Down Expand Up @@ -391,7 +412,9 @@ export class LocalPeers extends TypedEmitter {
message
)
} catch (err) {
this.#l.log(`Error handling ${type} message: ${String(err)}`)
const errorMessage = String(err)
this.emit('failed-to-handle-message', type, errorMessage)
this.#l.log(`Error handling ${type} message: ${errorMessage}`)
}
},
}
Expand Down
22 changes: 22 additions & 0 deletions tests/local-peers.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,28 @@ test('messages to unknown peers', async (t) => {
)
})

test('handles invalid invites', async (t) => {
t.plan(1)

const r1 = new LocalPeers()
const r2 = new LocalPeers()

r1.once('peers', async ([peer]) => {
await r1.__sendRawInvite(peer.deviceId, Buffer.from([1, 2, 3]))
})

r2.on('invite', () => {
t.fail('should not receive invite')
})

r2.once('failed-to-handle-message', (messageType) => {
t.is(messageType, 'Invite')
})

const destroy = replicate(r1, r2)
t.teardown(destroy)
})

test('Disconnected peer shows in state', async (t) => {
t.plan(6)
const r1 = new LocalPeers()
Expand Down

0 comments on commit 9c31b99

Please sign in to comment.