Skip to content

Commit a51a145

Browse files
authored
Additional Testkit support (#793)
1 parent 8d1e7a3 commit a51a145

15 files changed

+457
-40
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ community/server-plugin-test/neo4j-home
2626
enterprise/server-enterprise/neo4j-home
2727
integrationtests/data
2828
dependency-reduced-pom.xml
29+
venv

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/TestkitModule.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@
1919
package neo4j.org.testkit.backend.messages;
2020

2121
import com.fasterxml.jackson.databind.module.SimpleModule;
22+
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitListDeserializer;
23+
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitBookmarkSerializer;
2224
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitListValueSerializer;
2325
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitMapValueSerializer;
2426
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitNodeValueSerializer;
2527
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitRecordSerializer;
2628
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitValueSerializer;
2729

30+
import java.util.List;
31+
32+
import org.neo4j.driver.Bookmark;
2833
import org.neo4j.driver.Record;
2934
import org.neo4j.driver.Value;
3035
import org.neo4j.driver.internal.value.ListValue;
@@ -35,10 +40,13 @@ public class TestkitModule extends SimpleModule
3540
{
3641
public TestkitModule()
3742
{
43+
this.addDeserializer( List.class, new TestkitListDeserializer() );
44+
3845
this.addSerializer( Value.class, new TestkitValueSerializer() );
3946
this.addSerializer( NodeValue.class, new TestkitNodeValueSerializer() );
4047
this.addSerializer( ListValue.class, new TestkitListValueSerializer() );
4148
this.addSerializer( Record.class, new TestkitRecordSerializer() );
4249
this.addSerializer( MapValue.class, new TestkitMapValueSerializer() );
50+
this.addSerializer( Bookmark.class, new TestkitBookmarkSerializer() );
4351
}
4452
}

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/NewSession.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ public TestkitResponse process( TestkitState testkitState )
5656

5757
Optional.ofNullable( data.database ).ifPresent( builder::withDatabase );
5858

59+
if ( data.getFetchSize() != 0 )
60+
{
61+
builder.withFetchSize( data.getFetchSize() );
62+
}
63+
5964
org.neo4j.driver.Session session = driver.session( builder.build() );
6065
String newId = testkitState.newId();
6166
testkitState.getSessionStates().put( newId, new SessionState( session ) );

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionBeginTransaction.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
2727
import neo4j.org.testkit.backend.messages.responses.Transaction;
2828

29+
import java.time.Duration;
2930
import java.util.Map;
3031
import java.util.Optional;
3132

@@ -47,7 +48,12 @@ public TestkitResponse process( TestkitState testkitState )
4748
{
4849
TransactionConfig.Builder builder = TransactionConfig.builder();
4950
Optional.ofNullable( data.txMeta ).ifPresent( builder::withMetadata );
50-
// Optional.ofNullable( data.timeout ).ifPresent( builder::withTimeout );
51+
52+
if ( data.getTimeout() != null )
53+
{
54+
builder.withTimeout( Duration.ofMillis( data.getTimeout() ) );
55+
}
56+
5157
String txId = testkitState.newId();
5258
org.neo4j.driver.Transaction tx = session.beginTransaction( builder.build() );
5359
testkitState.getTransactions().put( txId, tx );
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2002-2020 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.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 neo4j.org.testkit.backend.messages.requests;
20+
21+
import lombok.Getter;
22+
import lombok.NoArgsConstructor;
23+
import lombok.Setter;
24+
import neo4j.org.testkit.backend.SessionState;
25+
import neo4j.org.testkit.backend.TestkitState;
26+
import neo4j.org.testkit.backend.messages.responses.Bookmarks;
27+
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
28+
29+
import java.util.Optional;
30+
31+
import org.neo4j.driver.Bookmark;
32+
33+
@Setter
34+
@Getter
35+
@NoArgsConstructor
36+
public class SessionLastBookmarks implements TestkitRequest
37+
{
38+
private SessionLastBookmarksBody data;
39+
40+
@Override
41+
public TestkitResponse process( TestkitState testkitState )
42+
{
43+
return Optional.ofNullable( testkitState.getSessionStates().getOrDefault( data.sessionId, null ) )
44+
.map( SessionState::getSession )
45+
.map( session ->
46+
{
47+
Bookmark bookmark = testkitState.getSessionStates().get( data.getSessionId() ).getSession().lastBookmark();
48+
return Bookmarks.builder().data( Bookmarks.BookmarksBody.builder().bookmarks( bookmark ).build() ).build();
49+
} )
50+
.orElseThrow( () -> new RuntimeException( "Could not find session" ) );
51+
}
52+
53+
@Setter
54+
@Getter
55+
@NoArgsConstructor
56+
public static class SessionLastBookmarksBody
57+
{
58+
private String sessionId;
59+
}
60+
}

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/SessionRun.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,17 @@
2323
import lombok.NoArgsConstructor;
2424
import lombok.Setter;
2525
import neo4j.org.testkit.backend.TestkitState;
26-
import neo4j.org.testkit.backend.messages.TestkitCypherTypeDeserializer;
26+
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitCypherParamDeserializer;
2727
import neo4j.org.testkit.backend.messages.responses.Result;
2828
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
2929

30+
import java.time.Duration;
3031
import java.util.Map;
3132
import java.util.Optional;
3233

3334
import org.neo4j.driver.Query;
3435
import org.neo4j.driver.Session;
36+
import org.neo4j.driver.TransactionConfig;
3537

3638
@Setter
3739
@Getter
@@ -47,7 +49,10 @@ public TestkitResponse process( TestkitState testkitState )
4749
Query query = Optional.ofNullable( data.params )
4850
.map( params -> new Query( data.cypher, data.params ) )
4951
.orElseGet( () -> new Query( data.cypher ) );
50-
org.neo4j.driver.Result result = session.run( query );
52+
TransactionConfig.Builder transactionConfig = TransactionConfig.builder();
53+
Optional.ofNullable( data.getTxMeta() ).ifPresent( transactionConfig::withMetadata );
54+
Optional.ofNullable( data.getTimeout() ).ifPresent( to -> transactionConfig.withTimeout( Duration.ofMillis( to ) ) );
55+
org.neo4j.driver.Result result = session.run( query, transactionConfig.build() );
5156
String newId = testkitState.newId();
5257
testkitState.getResults().put( newId, result );
5358

@@ -59,12 +64,13 @@ public TestkitResponse process( TestkitState testkitState )
5964
@NoArgsConstructor
6065
public static class SessionRunBody
6166
{
67+
@JsonDeserialize( using = TestkitCypherParamDeserializer.class )
68+
private Map<String,Object> params;
69+
6270
private String sessionId;
6371
private String cypher;
72+
private Map<String,Object> txMeta;
73+
private Integer timeout;
6474

65-
@JsonDeserialize( using = TestkitCypherTypeDeserializer.class )
66-
private Map<String,Object> params;
67-
private String txMeta;
68-
private int timeout;
6975
}
7076
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright (c) 2002-2020 "Neo4j,"
3+
* Neo4j Sweden AB [http://neo4j.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 neo4j.org.testkit.backend.messages.requests;
20+
21+
import lombok.Getter;
22+
import lombok.NoArgsConstructor;
23+
import lombok.Setter;
24+
import neo4j.org.testkit.backend.SessionState;
25+
import neo4j.org.testkit.backend.TestkitState;
26+
import neo4j.org.testkit.backend.messages.responses.RetryableDone;
27+
import neo4j.org.testkit.backend.messages.responses.RetryableTry;
28+
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
29+
30+
import java.util.Map;
31+
import java.util.Optional;
32+
33+
import org.neo4j.driver.Session;
34+
import org.neo4j.driver.TransactionWork;
35+
36+
@Setter
37+
@Getter
38+
@NoArgsConstructor
39+
public class SessionWriteTransaction implements TestkitRequest
40+
{
41+
private SessionWriteTransactionBody data;
42+
43+
@Override
44+
public TestkitResponse process( TestkitState testkitState )
45+
{
46+
return Optional.ofNullable( testkitState.getSessionStates().getOrDefault( data.getSessionId(), null ) )
47+
.map( sessionState ->
48+
{
49+
Session session = sessionState.getSession();
50+
session.writeTransaction( handle( testkitState, sessionState ) );
51+
return retryableDone();
52+
} ).orElseThrow( () -> new RuntimeException( "Could not find session" ) );
53+
}
54+
55+
private TransactionWork<Integer> handle( TestkitState testkitState, SessionState sessionState )
56+
{
57+
return tx ->
58+
{
59+
System.out.println( "Start" );
60+
sessionState.setRetryableState( 0 );
61+
String txId = testkitState.newId();
62+
testkitState.getTransactions().put( txId, tx );
63+
testkitState.getResponseWriter().accept( retryableTry( txId ) );
64+
65+
while ( true )
66+
{
67+
// Process commands as usual but blocking in here
68+
testkitState.getProcessor().get();
69+
70+
// Check if state changed on session
71+
switch ( sessionState.retryableState )
72+
{
73+
case 0:
74+
// Nothing happened to session state while processing command
75+
break;
76+
case 1:
77+
// Client is happy to commit
78+
return 0;
79+
case -1:
80+
// Client wants to rollback
81+
if ( !"".equals( sessionState.retryableErrorId ) )
82+
{
83+
throw testkitState.getErrors().get( sessionState.retryableErrorId );
84+
}
85+
else
86+
{
87+
throw new RuntimeException( "Error from client in retryable tx" );
88+
}
89+
}
90+
}
91+
};
92+
}
93+
94+
private RetryableTry retryableTry( String txId )
95+
{
96+
return RetryableTry.builder().data( RetryableTry.RetryableTryBody.builder().id( txId ).build() ).build();
97+
}
98+
99+
private RetryableDone retryableDone()
100+
{
101+
return RetryableDone.builder().build();
102+
}
103+
104+
@Setter
105+
@Getter
106+
@NoArgsConstructor
107+
public static class SessionWriteTransactionBody
108+
{
109+
private String sessionId;
110+
private Map<String,String> txMeta;
111+
private String timeout;
112+
}
113+
}

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TestkitRequest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
@JsonSubTypes.Type( SessionClose.class ), @JsonSubTypes.Type( DriverClose.class ),
3131
@JsonSubTypes.Type( RetryableNegative.class ), @JsonSubTypes.Type( SessionReadTransaction.class ),
3232
@JsonSubTypes.Type( TransactionRun.class ), @JsonSubTypes.Type( RetryablePositive.class ),
33-
@JsonSubTypes.Type( SessionBeginTransaction.class ), @JsonSubTypes.Type( TransactionCommit.class )
33+
@JsonSubTypes.Type( SessionBeginTransaction.class ), @JsonSubTypes.Type( TransactionCommit.class ),
34+
@JsonSubTypes.Type( SessionLastBookmarks.class ), @JsonSubTypes.Type( SessionWriteTransaction.class )
3435
} )
3536
public interface TestkitRequest
3637
{

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/TransactionRun.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818
*/
1919
package neo4j.org.testkit.backend.messages.requests;
2020

21+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
2122
import lombok.Getter;
2223
import lombok.NoArgsConstructor;
2324
import lombok.Setter;
2425
import neo4j.org.testkit.backend.TestkitState;
26+
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitCypherParamDeserializer;
2527
import neo4j.org.testkit.backend.messages.responses.Result;
2628
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
2729

30+
import java.util.Collections;
31+
import java.util.Map;
2832
import java.util.Optional;
2933

3034
@Setter
@@ -38,7 +42,8 @@ public class TransactionRun implements TestkitRequest
3842
public TestkitResponse process( TestkitState testkitState )
3943
{
4044
return Optional.ofNullable( testkitState.getTransactions().get( data.txId ) )
41-
.map( tx -> tx.run( data.cypher ) )
45+
.map( tx ->
46+
tx.run( data.cypher, data.getParams() != null ? data.getParams() : Collections.emptyMap() ) )
4247
.map( result ->
4348
{
4449
String resultId = testkitState.newId();
@@ -60,5 +65,7 @@ public static class TransactionRunBody
6065
{
6166
private String txId;
6267
private String cypher;
68+
@JsonDeserialize( using = TestkitCypherParamDeserializer.class )
69+
private Map<String,Object> params;
6370
}
6471
}

0 commit comments

Comments
 (0)