SAP-BTP-Spielwiese/app1/node_modules/request-stats/test.js
Markus Rettig 775ac7b58c completed step 3 from the tutorial
you must login with an BTP account in order to see the app
2024-02-08 16:13:36 +01:00

284 lines
8.7 KiB
JavaScript

'use strict'
var http = require('http')
var test = require('tape')
var EventEmitter = require('events').EventEmitter
var requestStats = require('./index')
var Request = require('./lib/request')
var StatsEmitter = require('./lib/stats_emitter')
var KeepAliveAgent = require('keep-alive-agent')
var assertStatsCommon = function (t, stats) {
t.ok(stats.req.bytes > 0, 'stats.req.bytes > 0') // different headers will result in different results
t.equal(typeof stats.req.headers.connection, 'string')
t.equal(stats.req.method, 'PUT')
t.equal(stats.req.path, '/')
t.equal(stats.res.status, 200)
}
// assertion helper for validating stats from HTTP requests that finished correctly
var assertStatsFinished = function (t, stats) {
t.ok(stats.ok, 'stats.ok should be truthy')
t.ok(stats.time >= 9, 'stats.time >= 9') // The reason we don't just do >= 10, is because setTimeout is not that precise
t.ok(stats.res.bytes > 0, 'stats.res.bytes > 0') // different headers will result in different results
t.equal(typeof stats.res.headers.connection, 'string')
assertStatsCommon(t, stats)
}
// assertion helper for validating stats from HTTP requests that are closed before finishing
var assertStatsClosed = function (t, stats) {
t.ok(!stats.ok)
t.ok(stats.time >= 0)
t.equal(stats.res.bytes, 0)
t.deepEqual(stats.res.headers, {})
assertStatsCommon(t, stats)
}
var _start = function (server, errorHandler) {
server.listen(0, function () {
var options = {
port: server.address().port,
method: 'PUT'
}
var req = http.request(options, function (res) {
res.resume()
res.once('end', function () {
server.close()
})
})
if (errorHandler) req.on('error', errorHandler)
req.end('42')
})
}
var _respond = function (req, res) {
req.on('end', function () {
setTimeout(function () {
res.end('Answer to the Ultimate Question of Life, The Universe, and Everything')
}, 10)
})
req.resume()
}
test('StatsEmitter', function (t) {
var statsEmitter = requestStats()
t.ok(statsEmitter instanceof StatsEmitter, 'should be returned from requestStats()')
t.ok(statsEmitter instanceof EventEmitter, 'should be an instance of EventEmitter')
t.test('should emit a "request" event', function (t) {
var server = http.createServer(_respond)
requestStats(server).on('request', function () {
t.end()
})
_start(server)
})
t.test('should emit a "complete" event', function (t) {
var server = http.createServer(_respond)
requestStats(server).on('complete', function () {
t.end()
})
_start(server)
})
})
test('requestStats(server, onStats)', function (t) {
t.test('should call the stats-listener on request end', function (t) {
var server = http.createServer(_respond)
requestStats(server, function (stats) {
assertStatsFinished(t, stats)
t.end()
})
_start(server)
})
t.test('should call the stats-listener when the request is destroyed', function (t) {
var server = http.createServer(function (req, res) {
req.destroy()
})
requestStats(server, function (stats) {
assertStatsClosed(t, stats)
})
_start(server, function (err) {
t.ok(err instanceof Error)
t.end()
})
})
t.test('should calculate correct bytes read/written on keep-alive connections', function (t) {
var agent = new http.Agent()
agent.maxSockets = 1 // force connection reuse for every connection
var server = http.createServer(function (req, res) {
req.on('end', function () {
res.end()
})
req.resume()
})
server.once('connection', function () {
server.once('connection', function () {
t.fail('Expected the TCP connection to be reused')
})
})
requestStats(server, function (stats) {
// assert req.bytes are around 1 million (we cannot know exactly since
// request headers will vary depending on the host system)
t.ok(stats.req.bytes > 1000000, 'req body size should be above 1MB')
t.ok(stats.req.bytes < 1000300, 'req body size should not be to much above 1MB')
})
var performRequest = function (port, callback) {
var req = http.request({ port: port, method: 'PUT', agent: agent }, function (res) {
res.on('end', callback)
res.resume()
})
for (var n = 0, s = ''; n < 100000; n++) s += '1234567890' // 1 million
req.end(s)
}
server.listen(0, function () {
var port = server.address().port
performRequest(port, function () {
performRequest(port, function () {
server.close()
t.end()
})
})
})
})
})
test('requestStats(req, res).once(...)', function (t) {
t.test('should call the stats-listener on request end', function (t) {
_start(http.createServer(function (req, res) {
requestStats(req, res).once('complete', function (stats) {
assertStatsFinished(t, stats)
t.end()
})
_respond(req, res)
}))
})
})
test('requestStats(server).once(...)', function (t) {
t.test('should call the stats-listener on request end', function (t) {
var server = http.createServer(_respond)
requestStats(server).once('complete', function (stats) {
assertStatsFinished(t, stats)
t.end()
})
_start(server)
})
})
test('requestStats(req, res, onStats)', function (t) {
t.test('should call the stats-listener on request end', function (t) {
_start(http.createServer(function (req, res) {
requestStats(req, res, function (stats) {
assertStatsFinished(t, stats)
t.end()
})
_respond(req, res)
}))
})
})
test('Request instance', function (t) {
t.test('should expose a .progress() function', function (t) {
_start(http.createServer(function (req, res) {
var request = new Request(req, res)
t.ok(typeof request.progress === 'function')
t.end()
}))
})
t.test('should be emitted on the "request" event', function (t) {
var server = http.createServer(_respond)
var statsEmitter = requestStats(server)
var request
statsEmitter.on('request', function (obj) {
request = obj
})
statsEmitter.on('complete', function (stats) {
t.ok(request instanceof Request)
t.end()
})
_start(server)
})
})
test('request.progress()', function (t) {
t.test('should return a progress object', function (t) {
var server = http.createServer(_respond)
var statsEmitter = requestStats(server)
statsEmitter.on('request', function (request) {
var progress = request.progress()
t.equal(progress.completed, false, 'should be completed')
t.ok(progress.time >= 0, 'progress.time >= 0')
t.ok(progress.timeDelta >= 0, 'progress.timeDelta >= 0')
t.ok(progress.req.bytes > 0, 'progress.req.bytes > 0')
t.ok(progress.req.bytesDelta > 0, 'progress.req.bytesDelta > 0')
t.ok(progress.req.speed > 0, 'progress.req.speed > 0')
t.equal(progress.res.bytes, 0, 'progress.res.bytes === 0')
t.equal(progress.res.bytesDelta, 0, 'progress.res.bytesDelta === 0')
t.equal(progress.res.speed, 0, 'progress.res.speed === 0')
t.end()
})
_start(server)
})
t.test('should not mix progress from two request', function (t) {
var server = http.createServer(_respond)
var statsEmitter = requestStats(server)
var requests = []
var progress = []
statsEmitter.on('request', function (request) {
requests.push(request)
t.equal(typeof request._connection, 'object')
})
statsEmitter.on('complete', function (stats) {
progress.push(requests[requests.length - 1].progress())
if (requests.length < 2) return
t.equal(requests[0]._connection, requests[1]._connection, 'should re-use the http connection')
t.equal(progress[0].req.bytes, progress[1].req.bytes, 'should receive the same amount of data')
t.equal(progress[0].res.bytes, progress[1].res.bytes, 'should send the same amount of data')
t.equal(progress[0].req.bytes + progress[1].req.bytes, requests[0]._connection.bytesRead, 'should not accumulate received data')
t.equal(progress[0].res.bytes + progress[1].res.bytes, requests[0]._connection.bytesWritten, 'should not accumulate sent data')
t.end()
})
server.listen(0, function () {
var options = {
port: server.address().port,
method: 'PUT',
headers: { Connection: 'keep-alive' },
agent: new KeepAliveAgent()
}
http.request(options, function (res) {
res.resume()
}).end('42')
setTimeout(function () {
http.request(options, function (res) {
res.resume()
res.once('end', function () {
server.close()
})
}).end('42')
}, 100)
})
})
})
test('end', function (t) {
t.end()
process.exit()
})