Skip to content

Commit 4d56eec

Browse files
committed
Merge pull request #151 from neo4j/1.0-tck-tests
1.0 tck tests
2 parents 6a318ca + 4fb3bb8 commit 4d56eec

File tree

12 files changed

+831
-45
lines changed

12 files changed

+831
-45
lines changed

driver/src/main/java/org/neo4j/driver/internal/InternalRecord.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@
2525

2626
import org.neo4j.driver.internal.util.Extract;
2727
import org.neo4j.driver.internal.value.InternalValue;
28-
import org.neo4j.driver.v1.util.Function;
29-
import org.neo4j.driver.v1.util.Pair;
3028
import org.neo4j.driver.v1.Record;
3129
import org.neo4j.driver.v1.Value;
3230
import org.neo4j.driver.v1.Values;
31+
import org.neo4j.driver.v1.util.Function;
32+
import org.neo4j.driver.v1.util.Pair;
3333

3434
import static java.lang.String.format;
3535
import static org.neo4j.driver.internal.util.Format.formatPairs;
36-
import static org.neo4j.driver.v1.Values.ofValue;
3736
import static org.neo4j.driver.v1.Values.ofObject;
37+
import static org.neo4j.driver.v1.Values.ofValue;
3838

3939
public class InternalRecord implements Record
4040
{
@@ -54,6 +54,12 @@ public List<String> keys()
5454
return keys;
5555
}
5656

57+
@Override
58+
public List<Value> values()
59+
{
60+
return Arrays.asList( values );
61+
}
62+
5763
@Override
5864
public List<Pair<String, Value>> fields()
5965
{

driver/src/main/java/org/neo4j/driver/internal/InternalSession.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public StatementResult run( String statementText, Value statementParameters )
8989
@Override
9090
public StatementResult run( Statement statement )
9191
{
92-
ensureConnectionIsValid();
92+
ensureConnectionIsValidBeforeRunningSession();
9393
InternalStatementResult cursor = new InternalStatementResult( connection, statement );
9494
connection.run( statement.text(), statement.parameters().asMap( Values.ofValue() ), cursor.runResponseCollector() );
9595
connection.pullAll( cursor.pullAllResponseCollector() );
@@ -132,7 +132,7 @@ public void close()
132132
@Override
133133
public Transaction beginTransaction()
134134
{
135-
ensureConnectionIsValid();
135+
ensureConnectionIsValidBeforeOpeningTransaction();
136136
currentTransaction = new InternalTransaction( connection, txCleanup );
137137
connection.onError( new Runnable() {
138138
@Override
@@ -156,9 +156,15 @@ public TypeSystem typeSystem()
156156
return InternalTypeSystem.TYPE_SYSTEM;
157157
}
158158

159-
private void ensureConnectionIsValid()
159+
private void ensureConnectionIsValidBeforeRunningSession()
160160
{
161-
ensureNoOpenTransaction();
161+
ensureNoOpenTransactionBeforeRunningSession();
162+
ensureConnectionIsOpen();
163+
}
164+
165+
private void ensureConnectionIsValidBeforeOpeningTransaction()
166+
{
167+
ensureNoOpenTransactionBeforeOpeningTransaction();
162168
ensureConnectionIsOpen();
163169
}
164170

@@ -174,12 +180,21 @@ protected void finalize() throws Throwable
174180
super.finalize();
175181
}
176182

177-
private void ensureNoOpenTransaction()
183+
private void ensureNoOpenTransactionBeforeRunningSession()
184+
{
185+
if ( currentTransaction != null )
186+
{
187+
throw new ClientException( "Statements cannot be run directly on a session with an open transaction;" +
188+
" either run from within the transaction or use a different session." );
189+
}
190+
}
191+
192+
private void ensureNoOpenTransactionBeforeOpeningTransaction()
178193
{
179194
if ( currentTransaction != null )
180195
{
181-
throw new ClientException( "Please close the currently open transaction object before running " +
182-
"more statements/transactions in the current session." );
196+
throw new ClientException( "You cannot begin a transaction on a session with an open transaction;" +
197+
" either run from within the transaction or use a different session." );
183198
}
184199
}
185200

driver/src/main/java/org/neo4j/driver/internal/pool/InternalConnectionPool.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,18 @@
3838
import org.neo4j.driver.v1.exceptions.ClientException;
3939
import org.neo4j.driver.v1.exceptions.Neo4jException;
4040

41+
import static java.lang.String.format;
42+
4143
/**
4244
* A basic connection pool that optimizes for threads being long-lived, acquiring/releasing many connections.
4345
* It uses a global queue as a fallback pool, but tries to avoid coordination by storing connections in a ThreadLocal.
44-
* <p>
46+
*
4547
* Safety is achieved by tracking thread locals getting garbage collected, returning connections to the global pool
4648
* when this happens.
47-
* <p>
49+
*
4850
* If threads are long-lived, this pool will achieve linearly scalable performance with overhead equivalent to a
4951
* hash-map lookup per acquire.
50-
* <p>
52+
*
5153
* If threads are short-lived, this pool is not ideal.
5254
*/
5355
public class InternalConnectionPool implements ConnectionPool
@@ -105,11 +107,11 @@ public Connection acquire( URI sessionURI )
105107
try
106108
{
107109
Connection conn = pool( sessionURI ).acquire( acquireSessionTimeout, TimeUnit.MILLISECONDS );
108-
if( conn == null )
110+
if ( conn == null )
109111
{
110112
throw new ClientException(
111113
"Failed to acquire a session with Neo4j " +
112-
"as all the connections in the connection pool are already occupied by other sessions. "+
114+
"as all the connections in the connection pool are already occupied by other sessions. " +
113115
"Please close unused session and retry. " +
114116
"Current Pool size: " + config.connectionPoolSize() +
115117
". If your application requires running more sessions concurrently than the current pool " +
@@ -183,8 +185,8 @@ public PooledConnection allocate( Consumer<PooledConnection> release )
183185
if ( connector == null )
184186
{
185187
throw new ClientException(
186-
"'" + uri.getScheme() + "' is not a supported transport (in '" +
187-
uri + "', available transports are: " + connectorSchemes() + "." );
188+
format( "Unsupported URI scheme: '%s' in url: '%s'. Supported transports are: '%s'.",
189+
uri.getScheme(), uri, connectorSchemes() ) );
188190
}
189191
Connection conn = connector.connect( uri, config, authToken );
190192
return new PooledConnection( conn, release );

driver/src/main/java/org/neo4j/driver/v1/Record.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ public interface Record
4848
*/
4949
List<String> keys();
5050

51+
/**
52+
* Retrieve the values of the underlying map
53+
*
54+
* @return all field keys in order
55+
*/
56+
List<Value> values();
57+
5158
/**
5259
* Check if the list of keys contains the given key
5360
*

driver/src/test/java/org/neo4j/driver/internal/InternalRecordTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.junit.Test;
2222

2323
import java.util.Arrays;
24+
import java.util.Collections;
2425
import java.util.Iterator;
2526
import java.util.List;
2627
import java.util.Map;
@@ -183,6 +184,64 @@ public void testToString()
183184
assertThat( record.toString(), equalTo( "Record<{k1: 0, k2: 1}>" ) );
184185
}
185186

187+
@Test
188+
public void shouldHaveMethodToGetKeys()
189+
{
190+
//GIVEN
191+
List<String> keys = Arrays.asList( "k2", "k1" );
192+
InternalRecord record = new InternalRecord( keys, new Value[]{value( 0 ), value( 1 )} );
193+
194+
//WHEN
195+
List<String> appendedKeys = record.keys();
196+
197+
//THEN
198+
assertThat( appendedKeys, equalTo( keys ) );
199+
}
200+
201+
@Test
202+
public void emptyKeysShouldGiveEmptyList()
203+
{
204+
//GIVEN
205+
List<String> keys = Collections.emptyList();
206+
InternalRecord record = new InternalRecord( keys, new Value[]{} );
207+
208+
//WHEN
209+
List<String> appendedKeys = record.keys();
210+
211+
//THEN
212+
assertThat( appendedKeys, equalTo( keys ) );
213+
}
214+
215+
216+
@Test
217+
public void shouldHaveMethodToGetValues()
218+
{
219+
//GIVEN
220+
List<String> keys = Arrays.asList( "k2", "k1" );
221+
Value[] values = new Value[]{value( 0 ), value( 1 )};
222+
InternalRecord record = new InternalRecord( keys, values );
223+
224+
//WHEN
225+
List<Value> appendedValues = record.values();
226+
227+
//THEN
228+
assertThat( appendedValues, equalTo( Arrays.asList( values ) ) );
229+
}
230+
231+
@Test
232+
public void emptyValuesShouldGiveEmptyList()
233+
{
234+
//GIVEN
235+
List<String> keys = Collections.emptyList();
236+
Value[] values = new Value[]{};
237+
InternalRecord record = new InternalRecord( keys, values );
238+
239+
//WHEN
240+
List<Value> appendedValues = record.values();
241+
242+
//THEN
243+
assertThat( appendedValues, equalTo( Arrays.asList( values ) ) );
244+
}
186245

187246
private InternalRecord createRecord()
188247
{
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/**
2+
* Copyright (c) 2002-2016 "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.tck;
20+
21+
22+
import cucumber.api.java.After;
23+
import cucumber.api.java.Before;
24+
import cucumber.api.java.en.And;
25+
import cucumber.api.java.en.Given;
26+
import cucumber.api.java.en.Then;
27+
28+
import java.io.File;
29+
import java.io.IOException;
30+
import java.nio.file.Files;
31+
32+
import org.neo4j.driver.internal.auth.InternalAuthToken;
33+
import org.neo4j.driver.v1.Driver;
34+
import org.neo4j.driver.v1.GraphDatabase;
35+
import org.neo4j.driver.v1.Session;
36+
import org.neo4j.driver.v1.util.Neo4jSettings;
37+
38+
import static org.hamcrest.CoreMatchers.equalTo;
39+
import static org.hamcrest.MatcherAssert.assertThat;
40+
import static org.neo4j.driver.v1.Values.ofValue;
41+
import static org.neo4j.driver.v1.Values.parameters;
42+
import static org.neo4j.driver.v1.tck.DriverComplianceIT.neo4j;
43+
44+
public class DriverAuthSteps
45+
{
46+
Driver driver = null;
47+
File tempDir = null;
48+
49+
@Before( "@auth" )
50+
public void setUp() throws IOException
51+
{
52+
tempDir = Files.createTempDirectory("dbms").toFile();
53+
tempDir.deleteOnExit();
54+
}
55+
56+
@After( "@auth" )
57+
public void reset()
58+
{
59+
60+
try
61+
{
62+
if (driver != null)
63+
{
64+
driver.close();
65+
}
66+
neo4j.useDefaultEncryptionKeyAndCert();
67+
}
68+
catch ( Exception e )
69+
{
70+
e.printStackTrace();
71+
throw new RuntimeException( "Failed to reset database" );
72+
}
73+
}
74+
75+
@Given( "^a driver is configured with auth enabled and correct password is provided$" )
76+
public void aDriverIsConfiguredWithAuthEnabledAndCorrectPasswordIsProvided() throws Throwable
77+
{
78+
driver = configureCredentials( "neo4j", "neo4j", "password" );
79+
}
80+
81+
@Then( "^reading and writing to the database should be possible$" )
82+
public void readingAndWritingToTheDatabaseShouldBePossible() throws Throwable
83+
{
84+
Session session = driver.session();
85+
session.run( "CREATE (:label1)" ).consume();
86+
session.run( "MATCH (n:label1) RETURN n" ).single();
87+
session.close();
88+
}
89+
90+
@Given( "^a driver is configured with auth enabled and the wrong password is provided$" )
91+
public void aDriverIsConfiguredWithAuthEnabledAndTheWrongPasswordIsProvided() throws Throwable
92+
{
93+
driver = configureCredentials( "neo4j", "neo4j", "password" );
94+
driver.close();
95+
driver = GraphDatabase.driver( neo4j.address(), new InternalAuthToken(
96+
parameters(
97+
"scheme", "basic",
98+
"principal", "neo4j",
99+
"credentials", "wrong" ).asMap( ofValue() ) ) );
100+
}
101+
102+
@Then( "^reading and writing to the database should not be possible$" )
103+
public void readingAndWritingToTheDatabaseShouldNotBePossible() throws Throwable
104+
{
105+
try(Session session = driver.session())
106+
{
107+
session.run( "CREATE (:label1)" ).consume();
108+
}
109+
catch ( Exception e )
110+
{
111+
assertThat(e.getMessage().startsWith( "The client is unauthorized due to authentication failure" ),
112+
equalTo(true));
113+
return;
114+
}
115+
throw new RuntimeException( "Exception should have been thrown" );
116+
}
117+
118+
@And( "^a `Protocol Error` is raised$" )
119+
public void aProtocolErrorIsRaised() throws Throwable
120+
{}
121+
122+
private Driver configureCredentials( String name, String oldPassword, String newPassword ) throws Exception
123+
{
124+
neo4j.restartServerOnEmptyDatabase( Neo4jSettings.DEFAULT
125+
.updateWith( Neo4jSettings.AUTH_ENABLED, "true" )
126+
.updateWith( Neo4jSettings.DATA_DIR, tempDir.getAbsolutePath().replace("\\", "/") ));
127+
128+
Driver driver = GraphDatabase.driver( neo4j.address(), new InternalAuthToken(
129+
parameters(
130+
"scheme", "basic",
131+
"principal", name,
132+
"credentials", oldPassword,
133+
"new_credentials", newPassword ).asMap( ofValue() ) ) );
134+
try(Session session = driver.session())
135+
{
136+
session.run( "RETURN 1" );
137+
}
138+
return driver;
139+
}
140+
}

driver/src/test/java/org/neo4j/driver/v1/tck/DriverComplianceIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* The base class to run all cucumber tests
3333
*/
3434
@RunWith( DriverCucumberAdapter.class )
35-
@CucumberOptions( features = {"target/resources/features"}, strict=true, tags={"~@in_dev", "~@db"}, format = {"pretty"})
35+
@CucumberOptions( features = {"target/resources/features"}, strict=true, tags={"~@db"}, format = {"pretty"})
3636
public class DriverComplianceIT
3737
{
3838
@Rule

0 commit comments

Comments
 (0)