diff options
Diffstat (limited to 'test/client-connect.js')
-rw-r--r-- | test/client-connect.js | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/test/client-connect.js b/test/client-connect.js new file mode 100644 index 0000000..7c8ca5e --- /dev/null +++ b/test/client-connect.js @@ -0,0 +1,308 @@ +'use strict' + +const { test } = require('tap') +const { Client, errors } = require('..') +const http = require('http') +const EE = require('events') +const { kBusy } = require('../lib/core/symbols') + +test('basic connect', (t) => { + t.plan(3) + + const server = http.createServer((c) => { + t.fail() + }) + server.on('connect', (req, socket, firstBodyChunk) => { + socket.write('HTTP/1.1 200 Connection established\r\n\r\n') + + let data = firstBodyChunk.toString() + socket.on('data', (buf) => { + data += buf.toString() + }) + + socket.on('end', () => { + socket.end(data) + }) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.close.bind(client)) + + const signal = new EE() + const promise = client.connect({ + signal, + path: '/' + }) + t.equal(signal.listenerCount('abort'), 1) + const { socket } = await promise + t.equal(signal.listenerCount('abort'), 0) + + let recvData = '' + socket.on('data', (d) => { + recvData += d + }) + + socket.on('end', () => { + t.equal(recvData.toString(), 'Body') + }) + + socket.write('Body') + socket.end() + }) +}) + +test('connect error', (t) => { + t.plan(1) + + const server = http.createServer((c) => { + t.fail() + }) + server.on('connect', (req, socket, firstBodyChunk) => { + socket.destroy() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.close.bind(client)) + + try { + await client.connect({ + path: '/' + }) + } catch (err) { + t.ok(err) + } + }) +}) + +test('connect invalid opts', (t) => { + t.plan(6) + + const client = new Client('http://localhost:5432') + + client.connect(null, err => { + t.type(err, errors.InvalidArgumentError) + t.equal(err.message, 'invalid opts') + }) + + try { + client.connect(null, null) + t.fail() + } catch (err) { + t.type(err, errors.InvalidArgumentError) + t.equal(err.message, 'invalid opts') + } + + try { + client.connect({ path: '/' }, null) + t.fail() + } catch (err) { + t.type(err, errors.InvalidArgumentError) + t.equal(err.message, 'invalid callback') + } +}) + +test('connect wait for empty pipeline', (t) => { + t.plan(7) + + let canConnect = false + const server = http.createServer((req, res) => { + res.end() + canConnect = true + }) + server.on('connect', (req, socket, firstBodyChunk) => { + t.equal(canConnect, true) + socket.write('HTTP/1.1 200 Connection established\r\n\r\n') + + let data = firstBodyChunk.toString() + socket.on('data', (buf) => { + data += buf.toString() + }) + + socket.on('end', () => { + socket.end(data) + }) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 3 + }) + t.teardown(client.close.bind(client)) + + client.request({ + path: '/', + method: 'GET' + }, (err) => { + t.error(err) + }) + client.once('connect', () => { + process.nextTick(() => { + t.equal(client[kBusy], false) + + client.connect({ + path: '/' + }, (err, { socket }) => { + t.error(err) + let recvData = '' + socket.on('data', (d) => { + recvData += d + }) + + socket.on('end', () => { + t.equal(recvData.toString(), 'Body') + }) + + socket.write('Body') + socket.end() + }) + t.equal(client[kBusy], true) + + client.request({ + path: '/', + method: 'GET' + }, (err) => { + t.error(err) + }) + }) + }) + }) +}) + +test('connect aborted', (t) => { + t.plan(6) + + const server = http.createServer((req, res) => { + t.fail() + }) + server.on('connect', (req, c, firstBodyChunk) => { + t.fail() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 3 + }) + t.teardown(client.destroy.bind(client)) + + const signal = new EE() + client.connect({ + path: '/', + signal, + opaque: 'asd' + }, (err, { opaque }) => { + t.equal(opaque, 'asd') + t.equal(signal.listenerCount('abort'), 0) + t.type(err, errors.RequestAbortedError) + }) + t.equal(client[kBusy], true) + t.equal(signal.listenerCount('abort'), 1) + signal.emit('abort') + + client.close(() => { + t.pass() + }) + }) +}) + +test('basic connect error', (t) => { + t.plan(2) + + const server = http.createServer((c) => { + t.fail() + }) + server.on('connect', (req, socket, firstBodyChunk) => { + socket.write('HTTP/1.1 200 Connection established\r\n\r\n') + + let data = firstBodyChunk.toString() + socket.on('data', (buf) => { + data += buf.toString() + }) + + socket.on('end', () => { + socket.end(data) + }) + }) + t.teardown(server.close.bind(server)) + + server.listen(0, async () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.close.bind(client)) + + const _err = new Error() + client.connect({ + path: '/' + }, (err, { socket }) => { + t.error(err) + socket.on('error', (err) => { + t.equal(err, _err) + }) + throw _err + }) + }) +}) + +test('connect invalid signal', (t) => { + t.plan(2) + + const server = http.createServer((req, res) => { + t.fail() + }) + server.on('connect', (req, c, firstBodyChunk) => { + t.fail() + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.on('disconnect', () => { + t.fail() + }) + + client.connect({ + path: '/', + signal: 'error', + opaque: 'asd' + }, (err, { opaque }) => { + t.equal(opaque, 'asd') + t.type(err, errors.InvalidArgumentError) + }) + }) +}) + +test('connect aborted after connect', (t) => { + t.plan(3) + + const signal = new EE() + const server = http.createServer((req, res) => { + t.fail() + }) + server.on('connect', (req, c, firstBodyChunk) => { + signal.emit('abort') + }) + t.teardown(server.close.bind(server)) + + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 3 + }) + t.teardown(client.destroy.bind(client)) + + client.connect({ + path: '/', + signal, + opaque: 'asd' + }, (err, { opaque }) => { + t.equal(opaque, 'asd') + t.type(err, errors.RequestAbortedError) + }) + t.equal(client[kBusy], true) + }) +}) |