Skip to content

Migrate tests depending on Boltkit to use Docker #1256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,18 @@ To use the driver in a project, please use the released driver via Maven Central

#### Running Tests and Creating a Package

Our test setup requires a bit of infrastructure to run.
We rely mostly on [`testkit`](https://github.com/neo4j-drivers/testkit).
Testkit is a tooling that is used to run integration tests for all of the drivers we provide.

Some older tests still rely on [`boltkit`](https://github.com/neo4j-drivers/boltkit), the predecessor to Testkit.
If `boltkit` is not installed, then all tests that requires `boltkit` will be ignored and will not be executed.

In case you want or can verify contributions with unit tests alone, use the following command to skip all integration and Testkit tests:

The following command may be used to unit test and install artifacts without running integration tests:
```
mvn clean install -DskipITs -P skip-testkit
```

Integration tests have the following prerequisites:
- Docker
- [`Testkit`](https://github.com/neo4j-drivers/testkit)

Testkit that is a tooling that is used to run integration tests for all official Neo4j drivers.
It can be executed using Docker during Maven build and in such case does not require additional setup. See the instructions below for more details.

There are 2 ways of running Testkit tests:
1. Using the `testkit-tests` module of this project.
2. Manually cloning Testkit and running it directly.
Expand Down
4 changes: 4 additions & 0 deletions driver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams-tck</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ void shouldRecoverFromDownedServer() throws Throwable {
sessionGrabber.start();

// When
neo4j.forceRestartDb();
neo4j.stopProxy();
neo4j.startProxy();

// Then we accept a hump with failing sessions, but demand that failures stop as soon as the server is back up.
sessionGrabber.assertSessionsAvailableWithin(120);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,8 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.neo4j.driver.AuthTokens.basic;
import static org.neo4j.driver.AuthTokens.custom;
import static org.neo4j.driver.Values.ofValue;
import static org.neo4j.driver.Values.parameters;
import static org.neo4j.driver.internal.logging.DevNullLogging.DEV_NULL_LOGGING;
import static org.neo4j.driver.util.Neo4jRunner.PASSWORD;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -44,58 +39,18 @@
import org.neo4j.driver.Value;
import org.neo4j.driver.exceptions.AuthenticationException;
import org.neo4j.driver.exceptions.SecurityException;
import org.neo4j.driver.internal.security.InternalAuthToken;
import org.neo4j.driver.internal.util.DisabledOnNeo4jWith;
import org.neo4j.driver.internal.util.Neo4jFeature;
import org.neo4j.driver.util.DatabaseExtension;
import org.neo4j.driver.util.Neo4jSettings;
import org.neo4j.driver.util.ParallelizableIT;

@ParallelizableIT
class CredentialsIT {
@RegisterExtension
static final DatabaseExtension neo4j = new DatabaseExtension();

@Test
@DisabledOnNeo4jWith(Neo4jFeature.BOLT_V4)
// This feature is removed in 4.0
void shouldBePossibleToChangePassword() throws Exception {
String newPassword = "secret";
String tmpDataDir = Files.createTempDirectory(Paths.get("target"), "tmp")
.toAbsolutePath()
.toString()
.replace("\\", "/");

neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.DATA_DIR, tmpDataDir));

AuthToken authToken = new InternalAuthToken(parameters(
"scheme", "basic",
"principal", "neo4j",
"credentials", "neo4j",
"new_credentials", newPassword)
.asMap(ofValue()));

// change the password
try (Driver driver = GraphDatabase.driver(neo4j.uri(), authToken);
Session session = driver.session()) {
session.run("RETURN 1").consume();
}

// verify old password does not work
final Driver badDriver = GraphDatabase.driver(CredentialsIT.neo4j.uri(), basic("neo4j", PASSWORD));
assertThrows(AuthenticationException.class, badDriver::verifyConnectivity);

// verify new password works
try (Driver driver = GraphDatabase.driver(CredentialsIT.neo4j.uri(), AuthTokens.basic("neo4j", newPassword));
Session session = driver.session()) {
session.run("RETURN 2").consume();
}
}

@Test
void basicCredentialsShouldWork() {
// When & Then
try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", PASSWORD));
try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", neo4j.adminPassword()));
Session session = driver.session()) {
Value single = session.run("RETURN 1").single().get(0);
assertThat(single.asLong(), equalTo(1L));
Expand All @@ -105,7 +60,8 @@ void basicCredentialsShouldWork() {
@Test
void shouldGetHelpfulErrorOnInvalidCredentials() {
SecurityException e = assertThrows(SecurityException.class, () -> {
try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("thisisnotthepassword", PASSWORD));
try (Driver driver =
GraphDatabase.driver(neo4j.uri(), basic("thisisnotthepassword", neo4j.adminPassword()));
Session session = driver.session()) {
session.run("RETURN 1");
}
Expand All @@ -116,7 +72,7 @@ void shouldGetHelpfulErrorOnInvalidCredentials() {
@Test
void shouldBeAbleToProvideRealmWithBasicAuth() {
// When & Then
try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", PASSWORD, "native"));
try (Driver driver = GraphDatabase.driver(neo4j.uri(), basic("neo4j", neo4j.adminPassword(), "native"));
Session session = driver.session()) {
Value single = session.run("CREATE () RETURN 1").single().get(0);
assertThat(single.asLong(), equalTo(1L));
Expand All @@ -126,7 +82,8 @@ void shouldBeAbleToProvideRealmWithBasicAuth() {
@Test
void shouldBeAbleToConnectWithCustomToken() {
// When & Then
try (Driver driver = GraphDatabase.driver(neo4j.uri(), custom("neo4j", PASSWORD, "native", "basic"));
try (Driver driver =
GraphDatabase.driver(neo4j.uri(), custom("neo4j", neo4j.adminPassword(), "native", "basic"));
Session session = driver.session()) {
Value single = session.run("CREATE () RETURN 1").single().get(0);
assertThat(single.asLong(), equalTo(1L));
Expand All @@ -138,7 +95,8 @@ void shouldBeAbleToConnectWithCustomTokenWithAdditionalParameters() {
Map<String, Object> params = singletonMap("secret", 16);

// When & Then
try (Driver driver = GraphDatabase.driver(neo4j.uri(), custom("neo4j", PASSWORD, "native", "basic", params));
try (Driver driver = GraphDatabase.driver(
neo4j.uri(), custom("neo4j", neo4j.adminPassword(), "native", "basic", params));
Session session = driver.session()) {
Value single = session.run("CREATE () RETURN 1").single().get(0);
assertThat(single.asLong(), equalTo(1L));
Expand All @@ -147,12 +105,12 @@ void shouldBeAbleToConnectWithCustomTokenWithAdditionalParameters() {

@Test
void directDriverShouldFailEarlyOnWrongCredentials() {
testDriverFailureOnWrongCredentials("bolt://localhost:" + neo4j.boltPort());
testDriverFailureOnWrongCredentials(neo4j.uri().toString());
}

@Test
void routingDriverShouldFailEarlyOnWrongCredentials() {
testDriverFailureOnWrongCredentials("neo4j://localhost:" + neo4j.boltPort());
testDriverFailureOnWrongCredentials(neo4j.uri().toString());
}

private void testDriverFailureOnWrongCredentials(String uri) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@
import static org.neo4j.driver.internal.util.Matchers.directDriverWithAddress;

import java.net.URI;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.internal.BoltServerAddress;
import org.neo4j.driver.util.DatabaseExtension;
import org.neo4j.driver.util.ParallelizableIT;
Expand Down Expand Up @@ -87,17 +84,4 @@ void shouldRegisterSingleServer() {
// Then
assertThat(driver, is(directDriverWithAddress(address)));
}

@Test
void shouldConnectIPv6Uri() {
// Given
try (Driver driver = GraphDatabase.driver("bolt://[::1]:" + neo4j.boltPort(), neo4j.authToken());
Session session = driver.session()) {
// When
Result result = session.run("RETURN 1");

// Then
assertThat(result.single().get(0).asInt(), CoreMatchers.equalTo(1));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import static org.neo4j.driver.Config.TrustStrategy.trustAllCertificates;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.neo4j.driver.Config;
Expand Down Expand Up @@ -81,7 +83,9 @@ void shouldOperateWithoutEncryptionWhenItIsAlsoDisabledInTheDatabase() {
}

private void testMatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypted, String scheme) {
neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString()));
Map<String, String> tlsConfig = new HashMap<>();
tlsConfig.put(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString());
neo4j.deleteAndStartNeo4j(tlsConfig);
Config config;

if (scheme.equals(Scheme.BOLT_LOW_TRUST_URI_SCHEME)) {
Expand All @@ -107,7 +111,9 @@ private void testMatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypt
}

private void testMismatchingEncryption(BoltTlsLevel tlsLevel, boolean driverEncrypted) {
neo4j.restartDb(Neo4jSettings.TEST_SETTINGS.updateWith(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString()));
Map<String, String> tlsConfig = new HashMap<>();
tlsConfig.put(Neo4jSettings.BOLT_TLS_LEVEL, tlsLevel.toString());
neo4j.deleteAndStartNeo4j(tlsConfig);
Config config = newConfig(driverEncrypted);

ServiceUnavailableException e = assertThrows(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,12 @@ void shouldHandleFailureAtRunTime() {
}

@Test
void shouldGetHelpfulErrorWhenTryingToConnectToHttpPort() throws Throwable {
// the http server needs some time to start up
Thread.sleep(2000);

void shouldGetHelpfulErrorWhenTryingToConnectToHttpPort() {
Config config = Config.builder().withoutEncryption().build();

final Driver driver = GraphDatabase.driver("bolt://localhost:" + session.httpPort(), config);
URI boltUri = session.uri();
URI uri = URI.create(String.format("%s://%s:%d", boltUri.getScheme(), boltUri.getHost(), session.httpPort()));
final Driver driver = GraphDatabase.driver(uri, config);
ClientException e = assertThrows(ClientException.class, driver::verifyConnectivity);
assertEquals(
"Server responded HTTP. Make sure you are not trying to connect to the http endpoint "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.util.DatabaseExtension;
import org.neo4j.driver.util.Neo4jSettings;
import org.neo4j.driver.util.ParallelizableIT;

@ParallelizableIT
class LoadCSVIT {
@RegisterExtension
static final DatabaseExtension neo4j = new DatabaseExtension(
Neo4jSettings.TEST_SETTINGS.without(Neo4jSettings.IMPORT_DIR).without(Neo4jSettings.SERVER_IMPORT_DIR));
static final DatabaseExtension neo4j = new DatabaseExtension();

@Test
void shouldLoadCSV() throws Throwable {
Expand Down Expand Up @@ -74,7 +72,7 @@ private String createLocalIrisData(Session session) throws IOException {
session.run("CREATE (c:Class {name: $className}) RETURN c", parameters("className", className));
}

return neo4j.putTmpFile("iris", ".csv", IRIS_DATA).toExternalForm();
return neo4j.addImportFile("iris", ".csv", IRIS_DATA);
}

private static String[] IRIS_CLASS_NAMES = new String[] {"Iris-setosa", "Iris-versicolor", "Iris-virginica"};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import static org.neo4j.driver.Config.TrustStrategy.trustCustomCertificateSignedBy;
import static org.neo4j.driver.util.Neo4jRunner.DEFAULT_AUTH_TOKEN;

import java.util.List;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -69,11 +68,12 @@ private static Stream<Arguments> data() {
@MethodSource("data")
void shouldRecoverFromServerRestart(String name, Config.ConfigBuilder configBuilder) {
// Given config with sessionLivenessCheckTimeout not set, i.e. turned off
try (Driver driver = GraphDatabase.driver(neo4j.uri(), DEFAULT_AUTH_TOKEN, configBuilder.build())) {
try (Driver driver = GraphDatabase.driver(neo4j.uri(), neo4j.authToken(), configBuilder.build())) {
acquireAndReleaseConnections(4, driver);

// When
neo4j.forceRestartDb();
neo4j.stopProxy();
neo4j.startProxy();

// Then we should be able to start using sessions again, at most O(numSessions) session calls later
int toleratedFailures = 4;
Expand Down Expand Up @@ -102,8 +102,9 @@ void shouldDropBrokenOldSessions(String name, Config.ConfigBuilder configBuilder
try (Driver driver = createDriver(clock, configBuilder.build())) {
acquireAndReleaseConnections(5, driver);

// restart database to invalidate all idle connections in the pool
neo4j.forceRestartDb();
// restart database access to invalidate all idle connections in the pool
neo4j.stopProxy();
neo4j.startProxy();
// move clock forward more than configured liveness check timeout
clock.progress(TimeUnit.MINUTES.toMillis(livenessCheckTimeoutMinutes + 1));

Expand Down Expand Up @@ -131,6 +132,6 @@ private Driver createDriver(Clock clock, Config config) {
RoutingSettings routingSettings = RoutingSettings.DEFAULT;
RetrySettings retrySettings = RetrySettings.DEFAULT;
return factory.newInstance(
neo4j.uri(), DEFAULT_AUTH_TOKEN, routingSettings, retrySettings, config, SecurityPlanImpl.insecure());
neo4j.uri(), neo4j.authToken(), routingSettings, retrySettings, config, SecurityPlanImpl.insecure());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
import static org.neo4j.driver.internal.util.Matchers.connectionAcquisitionTimeoutError;
import static org.neo4j.driver.internal.util.Neo4jFeature.BOLT_V4;
import static org.neo4j.driver.util.DaemonThreadFactory.daemon;
import static org.neo4j.driver.util.Neo4jRunner.DEFAULT_AUTH_TOKEN;

import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -1247,10 +1246,9 @@ private Driver newDriverWithoutRetries() {

private Driver newDriverWithFixedRetries(int maxRetriesCount) {
DriverFactory driverFactory = new DriverFactoryWithFixedRetryLogic(maxRetriesCount);
AuthToken auth = DEFAULT_AUTH_TOKEN;
return driverFactory.newInstance(
neo4j.uri(),
auth,
neo4j.authToken(),
RoutingSettings.DEFAULT,
RetrySettings.DEFAULT,
noLoggingConfig(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.neo4j.driver.Config.TrustStrategy.trustCustomCertificateSignedBy;
import static org.neo4j.driver.util.CertificateUtil.createNewCertificateAndKey;
import static org.neo4j.driver.util.CertificateUtil.createNewCertificateAndKeySignedBy;
import static org.neo4j.driver.util.DatabaseExtension.getDockerHostGeneralName;

import java.io.File;
import java.util.function.Supplier;
Expand All @@ -35,31 +36,30 @@
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.neo4j.driver.exceptions.SecurityException;
import org.neo4j.driver.util.CertificateExtension;
import org.neo4j.driver.util.CertificateUtil.CertificateKeyPair;
import org.neo4j.driver.util.DatabaseExtension;
import org.neo4j.driver.util.ParallelizableIT;

@ParallelizableIT
class TrustCustomCertificateIT {
@RegisterExtension
static final DatabaseExtension neo4j = new CertificateExtension();
static final DatabaseExtension neo4j = new DatabaseExtension();

@Test
void shouldAcceptServerWithCertificateSignedByDriverCertificate() throws Throwable {
// Given root certificate
CertificateKeyPair<File, File> root = createNewCertificateAndKey();

// When
CertificateKeyPair<File, File> server = createNewCertificateAndKeySignedBy(root);
CertificateKeyPair<File, File> server = createNewCertificateAndKeySignedBy(root, getDockerHostGeneralName());
neo4j.updateEncryptionKeyAndCert(server.key(), server.cert());

// Then
shouldBeAbleToRunCypher(() -> createDriverWithCustomCertificate(root.cert()));
}

@Test
void shouldAcceptServerWithSameCertificate() throws Throwable {
void shouldAcceptServerWithSameCertificate() {
shouldBeAbleToRunCypher(() -> createDriverWithCustomCertificate(neo4j.tlsCertFile()));
}

Expand All @@ -70,7 +70,7 @@ void shouldRejectServerWithUntrustedCertificate() throws Throwable {

// When & Then
final Driver driver = createDriverWithCustomCertificate(certificateAndKey.cert());
SecurityException error = assertThrows(SecurityException.class, driver::verifyConnectivity);
assertThrows(SecurityException.class, driver::verifyConnectivity);
}

private void shouldBeAbleToRunCypher(Supplier<Driver> driverSupplier) {
Expand Down
Loading