Skip to content

Commit c36e809

Browse files
committed
Fix string chunking bug
1 parent 44269ba commit c36e809

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

Diff for: driver/src/main/java/org/neo4j/driver/internal/connector/socket/ChunkedOutput.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,13 @@ public class ChunkedOutput implements PackOutput
3333
public static final int CHUNK_HEADER_SIZE = 2;
3434

3535
private final ByteBuffer buffer;
36+
private final WritableByteChannel channel;
3637

3738
/** The chunk header */
3839
private int currentChunkHeaderOffset;
3940
/** Are currently in the middle of writing a chunk? */
4041
private boolean chunkOpen = false;
4142

42-
private final WritableByteChannel channel;
43-
4443

4544
public ChunkedOutput( WritableByteChannel ch )
4645
{
@@ -109,17 +108,16 @@ public PackOutput writeDouble( double value ) throws IOException
109108
@Override
110109
public PackOutput writeBytes( byte[] data, int offset, int length ) throws IOException
111110
{
112-
int index = 0;
113-
while ( index < length )
111+
while ( offset < length )
114112
{
115113
// Ensure there is an open chunk, and that it has at least one byte of space left
116114
ensure(1);
117115

118116
// Write as much as we can into the current chunk
119-
int amountToWrite = Math.min( buffer.remaining(), length - index );
117+
int amountToWrite = Math.min( buffer.remaining(), length - offset );
120118

121119
buffer.put( data, offset, amountToWrite );
122-
index += amountToWrite;
120+
offset += amountToWrite;
123121
}
124122
return this;
125123
}

Diff for: driver/src/test/java/org/neo4j/driver/internal/connector/socket/ChunkedOutputTest.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,20 @@ public void shouldReserveSpaceForChunkHeaderWhenWriteDataToNewChunk() throws Thr
7979
@Test
8080
public void shouldSendOutDataWhoseSizeIsGreaterThanOutputBufferCapacity() throws Throwable
8181
{
82-
out.writeBytes( new byte[16], 0, 16 ); // 2 + 16 is greater than the default max size 16
82+
// Given
83+
byte[] data = new byte[32];
84+
for ( int i = 0; i < data.length; i++ )
85+
{
86+
data[i] = (byte) (i % 128);
87+
}
88+
89+
// When
90+
out.writeBytes( data, 4, 16 );
8391
out.messageBoundaryHook().run();
8492
out.flush();
8593

94+
// Then
8695
assertThat( BytePrinter.hex( channel.getBytes() ),
87-
equalTo( "00 0e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 " ) );
96+
equalTo( "00 0c 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 00 00 " ) );
8897
}
8998
}

Diff for: driver/src/test/java/org/neo4j/driver/v1/integration/ParametersIT.java

+24-20
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,15 @@ public void shouldBeAbleToSetAndReturnDoubleArrayProperty()
261261
}
262262

263263
@Test
264-
public void shouldBeAbleToSetAndReturnSpecialStringArrayProperty()
264+
public void shouldBeAbleToSetAndReturnStringArrayProperty()
265265
{
266-
// When
267-
String[] arrayValue = new String[]{"Mjölnir", "Mjölnir", "Mjölnir"};
266+
testStringArrayContaining( "cat" );
267+
testStringArrayContaining( "Mjölnir" );
268+
}
269+
270+
private void testStringArrayContaining( String str )
271+
{
272+
String[] arrayValue = new String[]{str, str, str};
268273

269274
ResultCursor result = session.run(
270275
"CREATE (a {value:{value}}) RETURN a.value", parameters( "value", arrayValue ) );
@@ -278,32 +283,31 @@ public void shouldBeAbleToSetAndReturnSpecialStringArrayProperty()
278283
for ( Value item : value.asList() )
279284
{
280285
assertThat( item.hasType( session.typeSystem().STRING() ), equalTo( true ) );
281-
assertThat( item.asString(), equalTo( "Mjölnir" ) );
286+
assertThat( item.asString(), equalTo( str ) );
282287
}
283288
}
284289
}
285290

286291
@Test
287-
public void shouldBeAbleToSetAndReturnStringArrayProperty()
292+
public void shouldHandleLargeString() throws Throwable
288293
{
289-
// When
290-
String[] arrayValue = new String[]{"cat", "cat", "cat"};
291-
ResultCursor result = session.run(
292-
"CREATE (a {value:{value}}) RETURN a.value", parameters( "value", arrayValue ) );
293-
294-
// Then
295-
for ( Record record : result.list() )
294+
// Given
295+
char[] bigStr = new char[1024 * 10];
296+
for ( int i = 0; i < bigStr.length; i+=4 )
296297
{
297-
Value value = record.value( "a.value" );
298-
assertThat( value.hasType( session.typeSystem().LIST() ), equalTo( true ) );
299-
assertThat( value.size(), equalTo( 3 ) );
300-
for ( Value item : value.asList() )
301-
{
302-
assertThat( item.hasType( session.typeSystem().STRING() ), equalTo( true ) );
303-
assertThat( item.asString(), equalTo( "cat" ) );
304-
}
298+
bigStr[i] = 'a';
299+
bigStr[i+1] = 'b';
300+
bigStr[i+2] = 'c';
301+
bigStr[i+3] = 'd';
305302
}
306303

304+
String bigString = new String( bigStr );
305+
306+
// When
307+
Value val = session.run( "RETURN {p} AS p", parameters( "p", bigString ) ).peek().value( "p" );
308+
309+
// Then
310+
assertThat( val.asString(), equalTo( bigString ) );
307311
}
308312

309313
@Test

0 commit comments

Comments
 (0)