Skip to content

Commit b76960b

Browse files
committed
Added wrong and failing queries to stress test
Both blocking and async commands added to execute wrong query "RETURN" and query failing at runtime "UNWIND [10, 5, 0] AS x RETURN 10 / x". Queries are executed both through session and transaction. These commands are useful to verify that all resources (like netty channel) are correctly released on errors.
1 parent 9a2d07e commit b76960b

18 files changed

+570
-63
lines changed

driver/src/main/java/org/neo4j/driver/internal/async/inbound/InboundMessageHandler.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,14 @@ public void handlerAdded( ChannelHandlerContext ctx )
5656
protected void channelRead0( ChannelHandlerContext ctx, ByteBuf msg ) throws IOException
5757
{
5858
input.start( msg );
59-
reader.read( messageDispatcher );
60-
input.stop();
59+
try
60+
{
61+
reader.read( messageDispatcher );
62+
}
63+
finally
64+
{
65+
input.stop();
66+
}
6167
}
6268

6369
@Override

driver/src/main/java/org/neo4j/driver/internal/async/outbound/OutboundMessageHandler.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,14 @@ protected void encode( ChannelHandlerContext ctx, Message msg, List<Object> out
6060

6161
ByteBuf messageBuf = ctx.alloc().ioBuffer();
6262
output.start( messageBuf );
63-
writer.write( msg );
64-
output.stop();
63+
try
64+
{
65+
writer.write( msg );
66+
}
67+
finally
68+
{
69+
output.stop();
70+
}
6571

6672
out.add( messageBuf );
6773
out.add( messageBoundary() );

driver/src/test/java/org/neo4j/driver/internal/util/Matchers.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.neo4j.driver.internal.net.BoltServerAddress;
3636
import org.neo4j.driver.internal.spi.ConnectionProvider;
3737
import org.neo4j.driver.v1.Driver;
38+
import org.neo4j.driver.v1.exceptions.ClientException;
3839
import org.neo4j.driver.v1.summary.ResultSummary;
3940

4041
import static org.neo4j.driver.internal.util.ServerVersion.v3_1_0;
@@ -192,6 +193,49 @@ public void describeTo( Description description )
192193
};
193194
}
194195

196+
public static Matcher<Throwable> arithmeticError()
197+
{
198+
return new TypeSafeMatcher<Throwable>()
199+
{
200+
@Override
201+
protected boolean matchesSafely( Throwable error )
202+
{
203+
return error instanceof ClientException &&
204+
((ClientException) error).code().contains( "ArithmeticError" );
205+
}
206+
207+
@Override
208+
public void describeTo( Description description )
209+
{
210+
description.appendText( "client error with code 'ArithmeticError' " );
211+
}
212+
};
213+
}
214+
215+
public static Matcher<Throwable> syntaxError( String messagePrefix )
216+
{
217+
return new TypeSafeMatcher<Throwable>()
218+
{
219+
@Override
220+
protected boolean matchesSafely( Throwable error )
221+
{
222+
if ( error instanceof ClientException )
223+
{
224+
ClientException clientError = (ClientException) error;
225+
return clientError.code().contains( "SyntaxError" ) &&
226+
clientError.getMessage().startsWith( messagePrefix );
227+
}
228+
return false;
229+
}
230+
231+
@Override
232+
public void describeTo( Description description )
233+
{
234+
description.appendText( "client error with code 'SyntaxError' and prefix '" + messagePrefix + "' " );
235+
}
236+
};
237+
}
238+
195239
private static boolean contains( AddressSet set, BoltServerAddress address )
196240
{
197241
BoltServerAddress[] addresses = set.toArray();

driver/src/test/java/org/neo4j/driver/v1/integration/SessionAsyncIT.java

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
import static java.util.Collections.emptyIterator;
5454
import static org.hamcrest.Matchers.containsString;
5555
import static org.hamcrest.Matchers.instanceOf;
56-
import static org.hamcrest.Matchers.startsWith;
56+
import static org.hamcrest.Matchers.is;
5757
import static org.junit.Assert.assertEquals;
5858
import static org.junit.Assert.assertFalse;
5959
import static org.junit.Assert.assertNotNull;
@@ -62,7 +62,9 @@
6262
import static org.junit.Assert.assertTrue;
6363
import static org.junit.Assert.fail;
6464
import static org.neo4j.driver.internal.util.Iterables.single;
65+
import static org.neo4j.driver.internal.util.Matchers.arithmeticError;
6566
import static org.neo4j.driver.internal.util.Matchers.containsResultAvailableAfterAndResultConsumedAfter;
67+
import static org.neo4j.driver.internal.util.Matchers.syntaxError;
6668
import static org.neo4j.driver.v1.Values.parameters;
6769
import static org.neo4j.driver.v1.util.TestUtil.await;
6870
import static org.neo4j.driver.v1.util.TestUtil.awaitAll;
@@ -138,7 +140,7 @@ public void shouldFailForIncorrectQuery()
138140
}
139141
catch ( Exception e )
140142
{
141-
assertSyntaxError( e );
143+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
142144
}
143145
}
144146

@@ -162,7 +164,7 @@ public void shouldFailWhenQueryFailsAtRuntime()
162164
}
163165
catch ( Exception e )
164166
{
165-
assertArithmeticError( e );
167+
assertThat( e, is( arithmeticError() ) );
166168
}
167169
}
168170

@@ -576,19 +578,6 @@ private <T> void testList( String query, List<T> expectedList )
576578
assertEquals( expectedList, actualList );
577579
}
578580

579-
private static void assertSyntaxError( Exception e )
580-
{
581-
assertThat( e, instanceOf( ClientException.class ) );
582-
assertThat( ((ClientException) e).code(), containsString( "SyntaxError" ) );
583-
assertThat( e.getMessage(), startsWith( "Unexpected end of input" ) );
584-
}
585-
586-
private static void assertArithmeticError( Exception e )
587-
{
588-
assertThat( e, instanceOf( ClientException.class ) );
589-
assertThat( ((ClientException) e).code(), containsString( "ArithmeticError" ) );
590-
}
591-
592581
private static class InvocationTrackingWork implements TransactionWork<CompletionStage<Record>>
593582
{
594583
final String query;

driver/src/test/java/org/neo4j/driver/v1/integration/TransactionAsyncIT.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import static org.junit.Assume.assumeTrue;
6262
import static org.neo4j.driver.internal.util.Iterables.single;
6363
import static org.neo4j.driver.internal.util.Matchers.containsResultAvailableAfterAndResultConsumedAfter;
64+
import static org.neo4j.driver.internal.util.Matchers.syntaxError;
6465
import static org.neo4j.driver.internal.util.ServerVersion.v3_1_0;
6566
import static org.neo4j.driver.v1.Values.parameters;
6667
import static org.neo4j.driver.v1.util.TestUtil.await;
@@ -223,7 +224,7 @@ public void shouldFailToCommitAfterSingleWrongStatement()
223224
}
224225
catch ( Exception e )
225226
{
226-
assertSyntaxError( e );
227+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
227228
}
228229

229230
try
@@ -249,7 +250,7 @@ public void shouldAllowRollbackAfterSingleWrongStatement()
249250
}
250251
catch ( Exception e )
251252
{
252-
assertSyntaxError( e );
253+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
253254
}
254255

255256
assertThat( await( tx.rollbackAsync() ), is( nullValue() ) );
@@ -277,7 +278,7 @@ public void shouldFailToCommitAfterCoupleCorrectAndSingleWrongStatement()
277278
}
278279
catch ( Exception e )
279280
{
280-
assertSyntaxError( e );
281+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
281282
}
282283

283284
try
@@ -313,7 +314,7 @@ public void shouldAllowRollbackAfterCoupleCorrectAndSingleWrongStatement()
313314
}
314315
catch ( Exception e )
315316
{
316-
assertSyntaxError( e );
317+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
317318
}
318319

319320
assertThat( await( tx.rollbackAsync() ), is( nullValue() ) );
@@ -331,7 +332,7 @@ public void shouldNotAllowNewStatementsAfterAnIncorrectStatement()
331332
}
332333
catch ( Exception e )
333334
{
334-
assertSyntaxError( e );
335+
assertThat( e, is( syntaxError( "Unexpected end of input" ) ) );
335336
}
336337

337338
try
@@ -625,11 +626,4 @@ private <T> void testList( String query, List<T> expectedList )
625626
}
626627
assertEquals( expectedList, actualList );
627628
}
628-
629-
private static void assertSyntaxError( Exception e )
630-
{
631-
assertThat( e, instanceOf( ClientException.class ) );
632-
assertThat( ((ClientException) e).code(), containsString( "SyntaxError" ) );
633-
assertThat( e.getMessage(), startsWith( "Unexpected end of input" ) );
634-
}
635629
}

driver/src/test/java/org/neo4j/driver/v1/stress/AbstractStressIT.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ private List<BlockingCommand<C>> createBlockingCommands()
191191
commands.add( new BlockingWriteQueryInTx<>( this, driver, false ) );
192192
commands.add( new BlockingWriteQueryInTx<>( this, driver, true ) );
193193

194+
commands.add( new BlockingWrongQuery<>( driver ) );
195+
commands.add( new BlockingWrongQueryInTx<>( driver ) );
196+
197+
commands.add( new BlockingFailingQuery<>( driver ) );
198+
commands.add( new BlockingFailingQueryInTx<>( driver ) );
199+
194200
commands.add( new FailedAuth<>( databaseUri(), logging ) );
195201

196202
commands.addAll( createTestSpecificBlockingCommands() );
@@ -242,6 +248,12 @@ private List<AsyncCommand<C>> createAsyncCommands()
242248
commands.add( new AsyncWriteQueryInTx<>( this, driver, false ) );
243249
commands.add( new AsyncWriteQueryInTx<>( this, driver, true ) );
244250

251+
commands.add( new AsyncWrongQuery<>( driver ) );
252+
commands.add( new AsyncWrongQueryInTx<>( driver ) );
253+
254+
commands.add( new AsyncFailingQuery<>( driver ) );
255+
commands.add( new AsyncFailingQueryInTx<>( driver ) );
256+
245257
return commands;
246258
}
247259

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2002-2017 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.v1.stress;
20+
21+
import java.util.concurrent.CompletionStage;
22+
23+
import org.neo4j.driver.v1.AccessMode;
24+
import org.neo4j.driver.v1.Driver;
25+
import org.neo4j.driver.v1.Session;
26+
import org.neo4j.driver.v1.StatementResultCursor;
27+
28+
import static org.hamcrest.Matchers.is;
29+
import static org.junit.Assert.assertNull;
30+
import static org.junit.Assert.assertThat;
31+
import static org.neo4j.driver.internal.util.Matchers.arithmeticError;
32+
33+
public class AsyncFailingQuery<C extends AbstractContext> extends AbstractAsyncQuery<C>
34+
{
35+
public AsyncFailingQuery( Driver driver )
36+
{
37+
super( driver, false );
38+
}
39+
40+
@Override
41+
public CompletionStage<Void> execute( C context )
42+
{
43+
Session session = newSession( AccessMode.READ, context );
44+
45+
return session.runAsync( "UNWIND [10, 5, 0] AS x RETURN 10 / x" )
46+
.thenCompose( StatementResultCursor::listAsync )
47+
.handle( ( records, error ) ->
48+
{
49+
session.closeAsync();
50+
51+
assertNull( records );
52+
Throwable cause = error.getCause(); // unwrap CompletionException
53+
assertThat( cause, is( arithmeticError() ) );
54+
55+
return null;
56+
} );
57+
}
58+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2002-2017 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
package org.neo4j.driver.v1.stress;
20+
21+
import java.util.concurrent.CompletionStage;
22+
23+
import org.neo4j.driver.v1.AccessMode;
24+
import org.neo4j.driver.v1.Driver;
25+
import org.neo4j.driver.v1.Session;
26+
import org.neo4j.driver.v1.StatementResultCursor;
27+
import org.neo4j.driver.v1.Transaction;
28+
29+
import static org.hamcrest.Matchers.is;
30+
import static org.junit.Assert.assertNull;
31+
import static org.junit.Assert.assertThat;
32+
import static org.neo4j.driver.internal.util.Matchers.arithmeticError;
33+
34+
public class AsyncFailingQueryInTx<C extends AbstractContext> extends AbstractAsyncQuery<C>
35+
{
36+
public AsyncFailingQueryInTx( Driver driver )
37+
{
38+
super( driver, false );
39+
}
40+
41+
@Override
42+
public CompletionStage<Void> execute( C context )
43+
{
44+
Session session = newSession( AccessMode.READ, context );
45+
46+
return session.beginTransactionAsync()
47+
.thenCompose( tx -> tx.runAsync( "UNWIND [10, 5, 0] AS x RETURN 10 / x" )
48+
.thenCompose( StatementResultCursor::listAsync )
49+
.handle( ( records, error ) ->
50+
{
51+
assertNull( records );
52+
Throwable cause = error.getCause(); // unwrap CompletionException
53+
assertThat( cause, is( arithmeticError() ) );
54+
55+
return tx;
56+
} ) )
57+
.thenCompose( Transaction::rollbackAsync )
58+
.whenComplete( ( ignore, error ) -> session.closeAsync() );
59+
}
60+
}

driver/src/test/java/org/neo4j/driver/v1/stress/AsyncReadQuery.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,19 @@ public CompletionStage<Void> execute( C context )
4343
Session session = newSession( AccessMode.READ, context );
4444

4545
CompletionStage<ResultSummary> queryFinished = session.runAsync( "MATCH (n) RETURN n LIMIT 1" )
46-
.thenCompose( cursor -> cursor.nextAsync().thenCompose( record ->
47-
processAndGetSummary( record, cursor ) ) );
46+
.thenCompose( cursor -> cursor.nextAsync()
47+
.thenCompose( record -> processAndGetSummary( record, cursor ) ) );
4848

49-
return queryFinished.thenCompose( summary ->
49+
queryFinished.whenComplete( ( summary, error ) ->
5050
{
51-
context.readCompleted( summary );
52-
return session.closeAsync();
51+
if ( summary != null )
52+
{
53+
context.readCompleted( summary );
54+
}
55+
session.closeAsync();
5356
} );
57+
58+
return queryFinished.thenApply( summary -> null );
5459
}
5560

5661
private CompletionStage<ResultSummary> processAndGetSummary( Record record, StatementResultCursor cursor )

0 commit comments

Comments
 (0)