Skip to content

Commit

Permalink
Additional Testkit support
Browse files Browse the repository at this point in the history
  • Loading branch information
gjmwoods committed Nov 13, 2020
1 parent 1494935 commit cdb3a46
Show file tree
Hide file tree
Showing 15 changed files with 457 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ community/server-plugin-test/neo4j-home
enterprise/server-enterprise/neo4j-home
integrationtests/data
dependency-reduced-pom.xml
venv
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@
package neo4j.org.testkit.backend.messages;

import com.fasterxml.jackson.databind.module.SimpleModule;
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitListDeserializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitBookmarkSerializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitListValueSerializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitMapValueSerializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitNodeValueSerializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitRecordSerializer;
import neo4j.org.testkit.backend.messages.responses.serializer.TestkitValueSerializer;

import java.util.List;

import org.neo4j.driver.Bookmark;
import org.neo4j.driver.Record;
import org.neo4j.driver.Value;
import org.neo4j.driver.internal.value.ListValue;
Expand All @@ -35,10 +40,13 @@ public class TestkitModule extends SimpleModule
{
public TestkitModule()
{
this.addDeserializer( List.class, new TestkitListDeserializer() );

this.addSerializer( Value.class, new TestkitValueSerializer() );
this.addSerializer( NodeValue.class, new TestkitNodeValueSerializer() );
this.addSerializer( ListValue.class, new TestkitListValueSerializer() );
this.addSerializer( Record.class, new TestkitRecordSerializer() );
this.addSerializer( MapValue.class, new TestkitMapValueSerializer() );
this.addSerializer( Bookmark.class, new TestkitBookmarkSerializer() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public TestkitResponse process( TestkitState testkitState )

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

if ( data.getFetchSize() != 0 )
{
builder.withFetchSize( data.getFetchSize() );
}

org.neo4j.driver.Session session = driver.session( builder.build() );
String newId = testkitState.newId();
testkitState.getSessionStates().put( newId, new SessionState( session ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;
import neo4j.org.testkit.backend.messages.responses.Transaction;

import java.time.Duration;
import java.util.Map;
import java.util.Optional;

Expand All @@ -47,7 +48,12 @@ public TestkitResponse process( TestkitState testkitState )
{
TransactionConfig.Builder builder = TransactionConfig.builder();
Optional.ofNullable( data.txMeta ).ifPresent( builder::withMetadata );
// Optional.ofNullable( data.timeout ).ifPresent( builder::withTimeout );

if ( data.getTimeout() != null )
{
builder.withTimeout( Duration.ofMillis( data.getTimeout() ) );
}

String txId = testkitState.newId();
org.neo4j.driver.Transaction tx = session.beginTransaction( builder.build() );
testkitState.getTransactions().put( txId, tx );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.requests;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import neo4j.org.testkit.backend.SessionState;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.responses.Bookmarks;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;

import java.util.Optional;

import org.neo4j.driver.Bookmark;

@Setter
@Getter
@NoArgsConstructor
public class SessionLastBookmarks implements TestkitRequest
{
private SessionLastBookmarksBody data;

@Override
public TestkitResponse process( TestkitState testkitState )
{
return Optional.ofNullable( testkitState.getSessionStates().getOrDefault( data.sessionId, null ) )
.map( SessionState::getSession )
.map( session ->
{
Bookmark bookmark = testkitState.getSessionStates().get( data.getSessionId() ).getSession().lastBookmark();
return Bookmarks.builder().data( Bookmarks.BookmarksBody.builder().bookmarks( bookmark ).build() ).build();
} )
.orElseThrow( () -> new RuntimeException( "Could not find session" ) );
}

@Setter
@Getter
@NoArgsConstructor
public static class SessionLastBookmarksBody
{
private String sessionId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,17 @@
import lombok.NoArgsConstructor;
import lombok.Setter;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.TestkitCypherTypeDeserializer;
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitCypherParamDeserializer;
import neo4j.org.testkit.backend.messages.responses.Result;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;

import java.time.Duration;
import java.util.Map;
import java.util.Optional;

import org.neo4j.driver.Query;
import org.neo4j.driver.Session;
import org.neo4j.driver.TransactionConfig;

@Setter
@Getter
Expand All @@ -47,7 +49,10 @@ public TestkitResponse process( TestkitState testkitState )
Query query = Optional.ofNullable( data.params )
.map( params -> new Query( data.cypher, data.params ) )
.orElseGet( () -> new Query( data.cypher ) );
org.neo4j.driver.Result result = session.run( query );
TransactionConfig.Builder transactionConfig = TransactionConfig.builder();
Optional.ofNullable( data.getTxMeta() ).ifPresent( transactionConfig::withMetadata );
Optional.ofNullable( data.getTimeout() ).ifPresent( to -> transactionConfig.withTimeout( Duration.ofMillis( to ) ) );
org.neo4j.driver.Result result = session.run( query, transactionConfig.build() );
String newId = testkitState.newId();
testkitState.getResults().put( newId, result );

Expand All @@ -59,12 +64,13 @@ public TestkitResponse process( TestkitState testkitState )
@NoArgsConstructor
public static class SessionRunBody
{
@JsonDeserialize( using = TestkitCypherParamDeserializer.class )
private Map<String,Object> params;

private String sessionId;
private String cypher;
private Map<String,Object> txMeta;
private Integer timeout;

@JsonDeserialize( using = TestkitCypherTypeDeserializer.class )
private Map<String,Object> params;
private String txMeta;
private int timeout;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2002-2020 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package neo4j.org.testkit.backend.messages.requests;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import neo4j.org.testkit.backend.SessionState;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.responses.RetryableDone;
import neo4j.org.testkit.backend.messages.responses.RetryableTry;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;

import java.util.Map;
import java.util.Optional;

import org.neo4j.driver.Session;
import org.neo4j.driver.TransactionWork;

@Setter
@Getter
@NoArgsConstructor
public class SessionWriteTransaction implements TestkitRequest
{
private SessionWriteTransactionBody data;

@Override
public TestkitResponse process( TestkitState testkitState )
{
return Optional.ofNullable( testkitState.getSessionStates().getOrDefault( data.getSessionId(), null ) )
.map( sessionState ->
{
Session session = sessionState.getSession();
session.writeTransaction( handle( testkitState, sessionState ) );
return retryableDone();
} ).orElseThrow( () -> new RuntimeException( "Could not find session" ) );
}

private TransactionWork<Integer> handle( TestkitState testkitState, SessionState sessionState )
{
return tx ->
{
System.out.println( "Start" );
sessionState.setRetryableState( 0 );
String txId = testkitState.newId();
testkitState.getTransactions().put( txId, tx );
testkitState.getResponseWriter().accept( retryableTry( txId ) );

while ( true )
{
// Process commands as usual but blocking in here
testkitState.getProcessor().get();

// Check if state changed on session
switch ( sessionState.retryableState )
{
case 0:
// Nothing happened to session state while processing command
break;
case 1:
// Client is happy to commit
return 0;
case -1:
// Client wants to rollback
if ( !"".equals( sessionState.retryableErrorId ) )
{
throw testkitState.getErrors().get( sessionState.retryableErrorId );
}
else
{
throw new RuntimeException( "Error from client in retryable tx" );
}
}
}
};
}

private RetryableTry retryableTry( String txId )
{
return RetryableTry.builder().data( RetryableTry.RetryableTryBody.builder().id( txId ).build() ).build();
}

private RetryableDone retryableDone()
{
return RetryableDone.builder().build();
}

@Setter
@Getter
@NoArgsConstructor
public static class SessionWriteTransactionBody
{
private String sessionId;
private Map<String,String> txMeta;
private String timeout;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
@JsonSubTypes.Type( SessionClose.class ), @JsonSubTypes.Type( DriverClose.class ),
@JsonSubTypes.Type( RetryableNegative.class ), @JsonSubTypes.Type( SessionReadTransaction.class ),
@JsonSubTypes.Type( TransactionRun.class ), @JsonSubTypes.Type( RetryablePositive.class ),
@JsonSubTypes.Type( SessionBeginTransaction.class ), @JsonSubTypes.Type( TransactionCommit.class )
@JsonSubTypes.Type( SessionBeginTransaction.class ), @JsonSubTypes.Type( TransactionCommit.class ),
@JsonSubTypes.Type( SessionLastBookmarks.class ), @JsonSubTypes.Type( SessionWriteTransaction.class )
} )
public interface TestkitRequest
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@
*/
package neo4j.org.testkit.backend.messages.requests;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import neo4j.org.testkit.backend.TestkitState;
import neo4j.org.testkit.backend.messages.requests.deserializer.TestkitCypherParamDeserializer;
import neo4j.org.testkit.backend.messages.responses.Result;
import neo4j.org.testkit.backend.messages.responses.TestkitResponse;

import java.util.Collections;
import java.util.Map;
import java.util.Optional;

@Setter
Expand All @@ -38,7 +42,8 @@ public class TransactionRun implements TestkitRequest
public TestkitResponse process( TestkitState testkitState )
{
return Optional.ofNullable( testkitState.getTransactions().get( data.txId ) )
.map( tx -> tx.run( data.cypher ) )
.map( tx ->
tx.run( data.cypher, data.getParams() != null ? data.getParams() : Collections.emptyMap() ) )
.map( result ->
{
String resultId = testkitState.newId();
Expand All @@ -60,5 +65,7 @@ public static class TransactionRunBody
{
private String txId;
private String cypher;
@JsonDeserialize( using = TestkitCypherParamDeserializer.class )
private Map<String,Object> params;
}
}
Loading

0 comments on commit cdb3a46

Please sign in to comment.