Adding chunked uploading test.

This commit is contained in:
ali.ibrahim 2016-10-07 16:34:36 +02:00
parent 9b94dfcbdc
commit 4eb9fc1bb6
2 changed files with 248 additions and 120 deletions

View file

@ -264,7 +264,7 @@ class ClientRequest extends EventEmitter {
// Since writing to the network is asynchronous, we conservatively // Since writing to the network is asynchronous, we conservatively
// assume that request headers are written after delivering the first // assume that request headers are written after delivering the first
// buffer to the network IO thread. // buffer to the network IO thread.
if (!this._url_request.notStarted) { if (this._url_request.notStarted) {
this._url_request.setChunkedUpload(this.chunkedEncoding) this._url_request.setChunkedUpload(this.chunkedEncoding)
} }

View file

@ -4,7 +4,27 @@ const http = require('http')
const url = require('url') const url = require('url')
const {net} = remote const {net} = remote
describe.only('net module', function() { function randomBuffer(size, start, end) {
start = start || 0
end = end || 255
let range = 1 + end - start
const buffer = Buffer.allocUnsafe(size)
for (let i = 0; i < size; ++i) {
buffer[i] = start + Math.floor(Math.random()*range)
}
return buffer;
}
function randomString(length) {
let buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0))
return buffer.toString();
}
const kOneKiloByte = 1024
const kOneMegaByte = kOneKiloByte * kOneKiloByte
describe('net module', function() {
this.timeout(0) this.timeout(0)
describe('HTTP basics', function() { describe('HTTP basics', function() {
@ -40,12 +60,13 @@ describe.only('net module', function() {
const urlRequest = net.request(`${server.url}${request_url}`) const urlRequest = net.request(`${server.url}${request_url}`)
urlRequest.on('response', function(response) { urlRequest.on('response', function(response) {
assert.equal(response.statusCode, 200) assert.equal(response.statusCode, 200)
response.pause()
response.on('data', function(chunk) {
})
response.on('end', function() { response.on('end', function() {
done() done()
}) })
response.on('data', function(chunk) { response.resume()
})
}) })
urlRequest.end(); urlRequest.end();
}) })
@ -70,12 +91,13 @@ describe.only('net module', function() {
}) })
urlRequest.on('response', function(response) { urlRequest.on('response', function(response) {
assert.equal(response.statusCode, 200) assert.equal(response.statusCode, 200)
response.pause()
response.on('data', function(chunk) {
})
response.on('end', function() { response.on('end', function() {
done() done()
}) })
response.on('data', function(chunk) { response.resume()
})
}) })
urlRequest.end(); urlRequest.end();
}) })
@ -100,13 +122,15 @@ describe.only('net module', function() {
urlRequest.on('response', function(response) { urlRequest.on('response', function(response) {
let expected_body_data = ''; let expected_body_data = '';
assert.equal(response.statusCode, 200) assert.equal(response.statusCode, 200)
response.pause()
response.on('data', function(chunk) {
expected_body_data += chunk.toString();
})
response.on('end', function() { response.on('end', function() {
assert.equal(expected_body_data, body_data) assert.equal(expected_body_data, body_data)
done() done()
}) })
response.on('data', function(chunk) { response.resume()
expected_body_data += chunk.toString();
})
}) })
urlRequest.end(); urlRequest.end();
}) })
@ -139,130 +163,237 @@ describe.only('net module', function() {
}) })
urlRequest.on('response', function(response) { urlRequest.on('response', function(response) {
assert.equal(response.statusCode, 200) assert.equal(response.statusCode, 200)
response.pause()
response.on('data', function(chunk) {
})
response.on('end', function() { response.on('end', function() {
done() done()
}) })
response.on('data', function(chunk) { response.resume()
})
}) })
urlRequest.write(body_data) urlRequest.write(body_data)
urlRequest.end(); urlRequest.end();
}) })
}) it.only('should support chunked encoding', function(done) {
describe('ClientRequest API', function() { const request_url = '/request_url'
it ('should emit ClientRequest events in a GET request', function(done) { server.on('request', function(request, response) {
this.timeout(30000); switch (request.url) {
let response_event_emitted = false; case request_url:
let data_event_emitted = false; response.statusCode = 200
let end_event_emitted = false; response.statusMessage = 'OK'
let finish_event_emitted = false; response.chunkedEncoding = true
const urlRequest = net.request({ assert.equal(request.method, 'POST')
method: 'GET', assert.equal(request.headers['transfer-encoding'], 'chunked')
url: 'https://www.google.com' assert(!request.headers['content-length'])
}) request.on('data', function(chunk) {
urlRequest.on('response', function(response) { response.write(chunk)
response_event_emitted = true; })
const statusCode = response.statusCode request.on('end', function(chunk) {
assert(typeof statusCode === 'number') response.end(chunk);
assert.equal(statusCode, 200) })
const statusMessage = response.statusMessage break;
const rawHeaders = response.rawHeaders default:
assert(typeof rawHeaders === 'object') response.statusCode = 501
const httpVersion = response.httpVersion; response.statusMessage = 'Not Implemented'
assert(typeof httpVersion === 'string') response.end()
assert(httpVersion.length > 0) }
const httpVersionMajor = response.httpVersionMajor; })
assert(typeof httpVersionMajor === 'number') const urlRequest = net.request({
assert(httpVersionMajor >= 1) method: 'POST',
const httpVersionMinor = response.httpVersionMinor; url: `${server.url}${request_url}`
assert(typeof httpVersionMinor === 'number') })
assert(httpVersionMinor >= 0)
let body = '';
response.on('data', function(buffer) {
data_event_emitted = true;
body += buffer.toString()
assert(typeof body === 'string')
assert(body.length > 0)
});
response.on('end', function() {
end_event_emitted = true;
})
});
urlRequest.on('finish', function() {
finish_event_emitted = true;
})
urlRequest.on('error', function(error) {
assert.ifError(error);
})
urlRequest.on('close', function() {
assert(response_event_emitted)
assert(data_event_emitted)
assert(end_event_emitted)
assert(finish_event_emitted)
done()
})
urlRequest.end();
})
it ('should emit ClientRequest events in a POST request', function(done) { let chunk_index = 0
this.timeout(20000); let chunk_count = 100
let response_event_emitted = false; let sent_chunks = [];
let data_event_emitted = false; let received_chunks = [];
let end_event_emitted = false;
let finish_event_emitted = false;
const urlRequest = net.request({
method: 'POST',
url: 'http://httpbin.org/post'
});
urlRequest.on('response', function(response) { urlRequest.on('response', function(response) {
response_event_emitted = true; assert.equal(response.statusCode, 200)
const statusCode = response.statusCode response.pause()
assert(typeof statusCode === 'number') response.on('data', function(chunk) {
assert.equal(statusCode, 200) received_chunks.push(chunk)
const statusMessage = response.statusMessage })
const rawHeaders = response.rawHeaders
assert(typeof rawHeaders === 'object')
const httpVersion = response.httpVersion;
assert(typeof httpVersion === 'string')
assert(httpVersion.length > 0)
const httpVersionMajor = response.httpVersionMajor;
assert(typeof httpVersionMajor === 'number')
assert(httpVersionMajor >= 1)
const httpVersionMinor = response.httpVersionMinor;
assert(typeof httpVersionMinor === 'number')
assert(httpVersionMinor >= 0)
let body = '';
response.on('end', function() { response.on('end', function() {
end_event_emitted = true; let sent_data = Buffer.concat(sent_chunks)
assert(response_event_emitted) let received_data = Buffer.concat(received_chunks)
assert(data_event_emitted) assert.equal(sent_data.toString(), received_data.toString())
assert(end_event_emitted) assert.equal(chunk_index, chunk_count)
assert(finish_event_emitted)
done() done()
})
response.resume()
})
urlRequest.chunkedEncoding = true
while (chunk_index < chunk_count) {
++chunk_index
let chunk = randomBuffer(kOneKiloByte)
sent_chunks.push(chunk)
assert(urlRequest.write(chunk))
}
urlRequest.end();
})
}) })
response.on('data', function(buffer) {
data_event_emitted = true;
body += buffer.toString()
assert(typeof body === 'string')
assert(body.length > 0)
});
}); describe('ClientRequest API', function() {
let server
beforeEach(function (done) {
server = http.createServer()
server.listen(0, '127.0.0.1', function () {
server.url = 'http://127.0.0.1:' + server.address().port
done()
})
})
afterEach(function () {
server.close(function() {
})
server = null
})
it ('response object should implement the IncomingMessage API', function(done) {
const request_url = '/request_url'
const custom_header_name = 'Some-Custom-Header-Name'
const custom_header_value = 'Some-Customer-Header-Value'
server.on('request', function(request, response) {
switch (request.url) {
case request_url:
response.statusCode = 200
response.statusMessage = 'OK'
response.setHeader(custom_header_name, custom_header_value)
response.end();
break;
default:
response.statusCode = 501
response.statusMessage = 'Not Implemented'
response.end()
}
})
let response_event_emitted = false;
let data_event_emitted = false;
let end_event_emitted = false;
let finish_event_emitted = false;
const urlRequest = net.request({
method: 'GET',
url: `${server.url}${request_url}`
})
urlRequest.on('response', function(response) {
response_event_emitted = true;
const statusCode = response.statusCode
assert(typeof statusCode === 'number')
assert.equal(statusCode, 200)
const statusMessage = response.statusMessage
assert(typeof statusMessage === 'string')
assert.equal(statusMessage, 'OK')
const rawHeaders = response.rawHeaders
assert(typeof rawHeaders === 'object')
assert(rawHeaders[custom_header_name] ===
custom_header_value)
const httpVersion = response.httpVersion;
assert(typeof httpVersion === 'string')
assert(httpVersion.length > 0)
const httpVersionMajor = response.httpVersionMajor;
assert(typeof httpVersionMajor === 'number')
assert(httpVersionMajor >= 1)
const httpVersionMinor = response.httpVersionMinor;
assert(typeof httpVersionMinor === 'number')
assert(httpVersionMinor >= 0)
response.pause()
response.on('data', function(chunk) {
});
response.on('end', function() {
done()
})
response.resume()
})
urlRequest.end();
})
it('request/response objects should emit expected events', function(done) {
const request_url = '/request_url'
let body_data = randomString(kOneMegaByte)
server.on('request', function(request, response) {
switch (request.url) {
case request_url:
response.statusCode = 200
response.statusMessage = 'OK'
response.write(body_data)
response.end();
break;
default:
response.statusCode = 501
response.statusMessage = 'Not Implemented'
response.end()
}
})
let request_response_event_emitted = false
let request_finish_event_emitted = false
let request_close_event_emitted = false
let response_data_event_emitted = false
let response_end_event_emitted = false
let response_close_event_emitted = false
function maybeDone(done) {
if (!request_close_event_emitted || !response_end_event_emitted) {
return
}
assert(request_response_event_emitted)
assert(request_finish_event_emitted)
assert(request_close_event_emitted)
assert(response_data_event_emitted)
assert(response_end_event_emitted)
done()
}
const urlRequest = net.request({
method: 'GET',
url: `${server.url}${request_url}`
})
urlRequest.on('response', function(response) {
request_response_event_emitted = true;
const statusCode = response.statusCode
assert.equal(statusCode, 200)
let buffers = [];
response.pause();
response.on('data', function(chunk) {
buffers.push(chunk)
response_data_event_emitted = true
})
response.on('end', function() {
let received_body_data = Buffer.concat(buffers);
assert(received_body_data.toString() === body_data)
response_end_event_emitted = true
maybeDone(done)
})
response.resume();
response.on('error', function(error) {
assert.ifError(error);
})
response.on('aborted', function() {
assert(false)
})
})
urlRequest.on('finish', function() { urlRequest.on('finish', function() {
finish_event_emitted = true; request_finish_event_emitted = true
}) })
urlRequest.on('error', function(error) { urlRequest.on('error', function(error) {
assert.ifError(error); assert.ifError(error);
}) })
urlRequest.on('abort', function() {
assert(false);
})
urlRequest.on('close', function() { urlRequest.on('close', function() {
request_close_event_emitted = true
}) maybeDone(done)
for (let i = 0; i < 100; ++i) { })
urlRequest.write('Hello World!');
}
urlRequest.end(); urlRequest.end();
}) })
it ('should be able to set a custom HTTP header', function() { it ('should be able to set a custom HTTP header', function() {
assert(false) assert(false)
@ -278,10 +409,7 @@ describe.only('net module', function() {
}) })
it ('should be able to specify a custom session', function() { it ('should be able to specify a custom session', function() {
assert(false) assert(false)
}) })
it ('should support chunked encoding', function() {
assert(false)
})
}) })
describe('IncomingMessage API', function() { describe('IncomingMessage API', function() {
it('should provide a Node.js-similar API', function() { it('should provide a Node.js-similar API', function() {