/*
* Copyright (c) 2002-2017 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.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 org.neo4j.driver.v1.integration;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.util.HashSet;
import org.neo4j.driver.internal.util.ServerVersion;
import org.neo4j.driver.v1.AccessMode;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.driver.v1.Transaction;
import org.neo4j.driver.v1.exceptions.ClientException;
import org.neo4j.driver.v1.exceptions.TransientException;
import org.neo4j.driver.v1.util.TestNeo4jSession;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.neo4j.driver.internal.util.ServerVersion.v3_1_0;
import static org.neo4j.driver.v1.util.Neo4jRunner.DEFAULT_AUTH_TOKEN;
public class BookmarkIT
{
@Rule
public ExpectedException exception = ExpectedException.none();
@Rule
public TestNeo4jSession sessionRule = new TestNeo4jSession();
private Driver driver;
private Session session;
@Before
public void assumeBookmarkSupport()
{
driver = sessionRule.driver();
session = sessionRule;
ServerVersion serverVersion = ServerVersion.version( driver );
assumeTrue( "Server version `" + serverVersion + "` does not support bookmark",
serverVersion.greaterThanOrEqual( v3_1_0 ) );
}
@Test
public void shouldConnectIPv6Uri()
{
// Given
try(Driver driver = GraphDatabase.driver( "bolt://[::1]:7687", DEFAULT_AUTH_TOKEN );
Session session = driver.session() )
{
// When
StatementResult result = session.run( "RETURN 1" );
// Then
assertThat( result.single().get( 0 ).asInt(), equalTo( 1 ) );
}
}
@Test
public void shouldReceiveBookmarkOnSuccessfulCommit() throws Throwable
{
// Given
assertNull( session.lastBookmark() );
// When
createNodeInTx( session );
// Then
assertNotNull( session.lastBookmark() );
assertThat( session.lastBookmark(), startsWith( "neo4j:bookmark:v1:tx" ) );
}
@Test
public void shouldThrowForInvalidBookmark()
{
String invalidBookmark = "hi, this is an invalid bookmark";
try (Session session = driver.session( invalidBookmark )) {
try
{
session.beginTransaction();
fail( "Exception expected" );
}
catch ( Exception e )
{
assertThat( e, instanceOf( ClientException.class ) );
}
}
}
@SuppressWarnings( "deprecation" )
@Test
public void shouldThrowForUnreachableBookmark()
{
createNodeInTx( session );
try
{
// todo: configure bookmark wait timeout to be lower than default 30sec when neo4j supports this
session.beginTransaction( session.lastBookmark() + 42 );
fail( "Exception expected" );
}
catch ( Exception e )
{
assertThat( e, instanceOf( TransientException.class ) );
assertThat( e.getMessage(), startsWith( "Database not up to the requested version" ) );
}
}
@Test
public void bookmarkRemainsAfterRolledBackTx()
{
assertNull( session.lastBookmark() );
createNodeInTx( session );
String bookmark = session.lastBookmark();
assertNotNull( bookmark );
try ( Transaction tx = session.beginTransaction() )
{
tx.run( "CREATE (a:Person)" );
tx.failure();
}
assertEquals( bookmark, session.lastBookmark() );
}
@Test
public void bookmarkRemainsAfterTxFailure()
{
assertNull( session.lastBookmark() );
createNodeInTx( session );
String bookmark = session.lastBookmark();
assertNotNull( bookmark );
Transaction tx = session.beginTransaction();
tx.run( "RETURN" );
tx.success();
try
{
tx.close();
fail( "Exception expected" );
}
catch ( Exception e )
{
assertThat( e, instanceOf( ClientException.class ) );
}
assertEquals( bookmark, session.lastBookmark() );
}
@Test
public void bookmarkRemainsAfterSuccessfulSessionRun()
{
assertNull( session.lastBookmark() );
createNodeInTx( session );
String bookmark = session.lastBookmark();
assertNotNull( bookmark );
session.run( "RETURN 1" ).consume();
assertEquals( bookmark, session.lastBookmark() );
}
@Test
public void bookmarkRemainsAfterFailedSessionRun()
{
assertNull( session.lastBookmark() );
createNodeInTx( session );
String bookmark = session.lastBookmark();
assertNotNull( bookmark );
try
{
session.run( "RETURN" ).consume();
fail( "Exception expected" );
}
catch ( Exception e )
{
assertThat( e, instanceOf( ClientException.class ) );
}
assertEquals( bookmark, session.lastBookmark() );
}
@Test
public void bookmarkIsUpdatedOnEveryCommittedTx()
{
assertNull( session.lastBookmark() );
createNodeInTx( session );
String bookmark1 = session.lastBookmark();
assertNotNull( bookmark1 );
createNodeInTx( session );
String bookmark2 = session.lastBookmark();
assertNotNull( bookmark2 );
createNodeInTx( session );
String bookmark3 = session.lastBookmark();
assertNotNull( bookmark3 );
assertEquals( 3, new HashSet<>( asList( bookmark1, bookmark2, bookmark3 ) ).size() );
}
@Test
public void createSessionWithInitialBookmark()
{
String bookmark = "TheBookmark";
try ( Session session = driver.session( bookmark ) )
{
assertEquals( bookmark, session.lastBookmark() );
}
}
@Test
public void createSessionWithAccessModeAndInitialBookmark()
{
String bookmark = "TheBookmark";
try ( Session session = driver.session( AccessMode.WRITE, bookmark ) )
{
assertEquals( bookmark, session.lastBookmark() );
}
}
private static void createNodeInTx( Session session )
{
try ( Transaction tx = session.beginTransaction() )
{
tx.run( "CREATE (a:Person)" );
tx.success();
}
}
}