Skip to content

Commit a26391c

Browse files
committed
Improve low-level dechunking tests, fix several bugs found
- Dechunking is now tested for a large set of permutations of chunks - Tests and fixes an off-by-one error when reading signed integers from CombinedBuffer - Removes specialized getSlice() from HeapBuffer, as the slice method is not available in all browsers. Fall back to default impl from BaseBuffer instead.
1 parent c269a31 commit a26391c

File tree

4 files changed

+78
-16
lines changed

4 files changed

+78
-16
lines changed

lib/internal/buf.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,6 @@ class HeapBuffer extends BaseBuffer {
389389
this._view.setFloat64( position, val );
390390
}
391391

392-
getSlice ( start, length ) {
393-
return new HeapBuffer( this._buffer.slice( start, start + length ) );
394-
}
395-
396392
/**
397393
* Specific to HeapBuffer, this gets a DataView from the
398394
* current position and of the specified length.
@@ -470,7 +466,7 @@ class CombinedBuffer extends BaseBuffer {
470466
for (let i = 0; i < this._buffers.length; i++) {
471467
let buffer = this._buffers[i];
472468
// If the position is not in the current buffer, skip the current buffer
473-
if( position > buffer.length ) {
469+
if( position >= buffer.length ) {
474470
position -= buffer.length;
475471
} else {
476472
return buffer.getInt8(position);

lib/internal/chunking.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,19 +156,14 @@ class Dechunker {
156156
}
157157

158158
IN_CHUNK ( buf ) {
159-
160-
if ( this._chunkSize < buf.remaining() ) {
161-
// Current packet is larger than current chunk, slice of the chunk
159+
if ( this._chunkSize <= buf.remaining() ) {
160+
// Current packet is larger than current chunk, or same size:
162161
this._currentMessage.push( buf.readSlice( this._chunkSize ) );
163162
return this.AWAITING_CHUNK;
164-
} else if ( this._chunkSize == buf.remaining() ) {
165-
// Current packet perfectly maps to current chunk
166-
this._currentMessage.push( buf.readSlice( buf.length ) );
167-
return this.AWAITING_CHUNK;
168163
} else {
169164
// Current packet is smaller than the chunk we're reading, split the current chunk itself up
170-
this._chunkSize -= data.remaining();
171-
this._currentMessage.push( buf.readSlice( buf.length ) );
165+
this._chunkSize -= buf.remaining();
166+
this._currentMessage.push( buf.readSlice( buf.remaining() ) );
172167
return this.IN_CHUNK;
173168
}
174169
}

test/internal/buf.test.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
var alloc = require('../../build/node/internal/buf').alloc;
21+
var CombinedBuffer = require('../../build/node/internal/buf').CombinedBuffer;
2122
var utf8 = require('../../build/node/internal/utf8');
2223
var Unpacker = require("../../build/node/internal/packstream.js").Unpacker;
2324

@@ -63,19 +64,41 @@ describe('buffers', function() {
6364
});
6465

6566
it('should decode list correctly', function() {
66-
//Given
67-
67+
// Given
6868
var b = alloc(5);
6969
b.writeUInt8(0x92);
7070
b.writeUInt8(0x81);
7171
b.writeUInt8(0x61);
7272
b.writeUInt8(0x81);
7373
b.writeUInt8(0x62);
7474
b.reset();
75+
76+
// When
7577
var data = new Unpacker().unpack( b );
78+
79+
// Then
7680
expect(data[0]).toBe('a');
7781
expect(data[1]).toBe('b');
82+
});
83+
});
84+
85+
describe('CombinedBuffer', function() {
86+
it('should read int8', function() {
87+
// Given
88+
var b1 = alloc(1);
89+
var b2 = alloc(1);
90+
b1.putInt8(0, 1);
91+
b2.putInt8(0, 2);
92+
93+
var b = new CombinedBuffer([b1,b2]);
7894

95+
// When
96+
var first = b.readInt8();
97+
var second = b.readInt8();
98+
99+
// Then
100+
expect(first).toBe(1);
101+
expect(second).toBe(2);
79102
});
80103
});
81104

test/internal/chunking.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
var Chunker = require('../../build/node/internal/chunking').Chunker;
2121
var Dechunker = require('../../build/node/internal/chunking').Dechunker;
2222
var alloc = require('../../build/node/internal/buf').alloc;
23+
var CombinedBuffer = require('../../build/node/internal/buf').CombinedBuffer;
2324

2425
describe('Chunker', function() {
2526
it('should chunk simple data', function() {
@@ -83,6 +84,41 @@ describe('Dechunker', function() {
8384
expect( messages.length ).toBe( 1 );
8485
expect( messages[0].toHex() ).toBe( "00 01 00 02 00 03 " );
8586
});
87+
88+
it('should handle message split at any point', function() {
89+
// Given
90+
var ch = new TestChannel();
91+
var chunker = new Chunker(ch);
92+
93+
// And given the following message
94+
chunker.writeInt8(1);
95+
chunker.writeInt16(2);
96+
chunker.writeInt32(3);
97+
chunker.writeUInt8(4);
98+
chunker.writeUInt32(5);
99+
chunker.messageBoundary();
100+
chunker.flush();
101+
102+
var chunked = ch.toBuffer();
103+
104+
// When I try splitting this chunked data at every possible position
105+
// into two separate buffers, and send those to the dechunker
106+
for (var i = 1; i < chunked.length; i++) {
107+
var slice1 = chunked.getSlice( 0, i );
108+
var slice2 = chunked.getSlice( i, chunked.length - i );
109+
110+
// Dechunk the slices
111+
var messages = [];
112+
var dechunker = new Dechunker();
113+
dechunker.onmessage = function(buffer) { messages.push(buffer); };
114+
dechunker.write( slice1 );
115+
dechunker.write( slice2 );
116+
117+
// Then, the output should be correct
118+
expect( messages.length ).toBe( 1 );
119+
expect( messages[0].toHex() ).toBe( "01 00 02 00 00 00 03 04 00 00 00 05 " );
120+
};
121+
});
86122
});
87123

88124
function TestChannel() {
@@ -101,6 +137,18 @@ TestChannel.prototype.toHex = function() {
101137
return out;
102138
};
103139

140+
TestChannel.prototype.toBuffer = function() {
141+
return new CombinedBuffer( this._written );
142+
};
143+
144+
TestChannel.prototype.toHex = function() {
145+
var out = "";
146+
for( var i=0; i<this._written.length; i++ ) {
147+
out += this._written[i].toHex();
148+
}
149+
return out;
150+
};
151+
104152
function bytes() {
105153
var b = alloc( arguments.length );
106154
for( var i=0; i<arguments.length; i++ ) {

0 commit comments

Comments
 (0)