Java tutorial
/* * Copyright (c) 2002-2016 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.harness; import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.NoSuchElementException; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.io.FileUtils; import org.codehaus.jackson.JsonNode; import org.junit.Rule; import org.junit.Test; import org.neo4j.bolt.v1.transport.socket.client.SocketConnection; import org.neo4j.dbms.DatabaseManagementSystemSettings; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.ResourceIterable; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.harness.extensionpackage.MyUnmanagedExtension; import org.neo4j.helpers.HostnamePort; import org.neo4j.helpers.collection.Iterables; import org.neo4j.kernel.configuration.Config; import org.neo4j.server.ServerTestUtils; import org.neo4j.server.configuration.ServerSettings; import org.neo4j.server.rest.domain.JsonParseException; import org.neo4j.test.SuppressOutput; import org.neo4j.test.TargetDirectory; import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.server.HTTP; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.neo4j.harness.TestServerBuilders.newInProcessBuilder; import static org.neo4j.helpers.collection.MapUtil.stringMap; import static org.neo4j.server.configuration.ServerSettings.httpConnector; public class InProcessBuilderTest { @Rule public TargetDirectory.TestDirectory testDir = TargetDirectory.testDirForTest(InProcessBuilderTest.class); @Rule public SuppressOutput suppressOutput = SuppressOutput.suppressAll(); @Test public void shouldLaunchAServerInSpecifiedDirectory() throws Exception { // Given File workDir = new File(testDir.directory(), "specific"); workDir.mkdir(); // When try (ServerControls server = getTestServerBuilder(workDir).newServer()) { // Then assertThat(HTTP.GET(server.httpURI().toString()).status(), equalTo(200)); assertThat(workDir.list().length, equalTo(1)); } // And after it's been closed, it should've cleaned up after itself. assertThat(Arrays.toString(workDir.list()), workDir.list().length, equalTo(0)); } private TestServerBuilder getTestServerBuilder(File workDir) { return newInProcessBuilder(workDir); } @Test public void shouldAllowCustomServerAndDbConfig() throws Exception { // Given trustAllSSLCerts(); // When try (ServerControls server = getTestServerBuilder(testDir.directory()) .withConfig(httpConnector("0").type, "HTTP").withConfig(httpConnector("0").enabled, "true") .withConfig(httpConnector("1").type, "HTTP").withConfig(httpConnector("1").enabled, "true") .withConfig(httpConnector("1").encryption, "TLS") .withConfig(httpConnector("1").address, "localhost:7473") .withConfig(ServerSettings.certificates_directory.name(), testDir.directory("certificates").getAbsolutePath()) .withConfig(GraphDatabaseSettings.dense_node_threshold, "20").newServer()) { // Then assertThat(HTTP.GET(server.httpsURI().get().toString()).status(), equalTo(200)); assertDBConfig(server, "20", GraphDatabaseSettings.dense_node_threshold.name()); } } @Test public void shouldMountUnmanagedExtensionsByClass() throws Exception { // When try (ServerControls server = getTestServerBuilder(testDir.directory()) .withExtension("/path/to/my/extension", MyUnmanagedExtension.class).newServer()) { // Then assertThat(HTTP.GET(server.httpURI().toString() + "path/to/my/extension/myExtension").status(), equalTo(234)); } } @Test public void shouldMountUnmanagedExtensionsByPackage() throws Exception { // When try (ServerControls server = getTestServerBuilder(testDir.directory()) .withExtension("/path/to/my/extension", "org.neo4j.harness.extensionpackage").newServer()) { // Then assertThat(HTTP.GET(server.httpURI().toString() + "path/to/my/extension/myExtension").status(), equalTo(234)); } } @Test public void shouldFindFreePort() throws Exception { // Given one server is running try (ServerControls firstServer = getTestServerBuilder(testDir.directory()).newServer()) { // When I start a second server try (ServerControls secondServer = getTestServerBuilder(testDir.directory()).newServer()) { // Then assertThat(secondServer.httpURI().getPort(), not(firstServer.httpURI().getPort())); } } } @Test public void shouldRunBuilderOnExistingStoreDir() throws Exception { // When // create graph db with one node upfront Path dir = Files.createTempDirectory(getClass().getSimpleName() + "_shouldRunBuilderOnExistingStorageDir"); File storeDir = new Config( stringMap(DatabaseManagementSystemSettings.data_directory.name(), dir.toString())) .get(DatabaseManagementSystemSettings.database_path); try { GraphDatabaseService db = new TestGraphDatabaseFactory().newEmbeddedDatabase(storeDir); try { db.execute("create ()"); } finally { db.shutdown(); } try (ServerControls server = getTestServerBuilder(testDir.directory()).copyFrom(dir.toFile()) .newServer()) { // Then try (Transaction tx = server.graph().beginTx()) { ResourceIterable<Node> allNodes = Iterables.asResourceIterable(server.graph().getAllNodes()); assertTrue(Iterables.count(allNodes) > 0); // When: create another node server.graph().createNode(); tx.success(); } } // Then: we still only have one node since the server is supposed to work on a copy db = new TestGraphDatabaseFactory().newEmbeddedDatabase(storeDir); try { try (Transaction tx = db.beginTx()) { assertEquals(1, Iterables.count(db.getAllNodes())); tx.success(); } } finally { db.shutdown(); } } finally { FileUtils.forceDelete(dir.toFile()); } } @Test public void shouldOpenBoltPort() throws Throwable { // given try (ServerControls controls = newInProcessBuilder().newServer()) { URI uri = controls.boltURI(); // when new SocketConnection().connect(new HostnamePort(uri.getHost(), uri.getPort())); // then no exception } } @Test public void shouldFailWhenProvidingANonDirectoryAsSource() throws IOException { File notADirectory = File.createTempFile("prefix", "suffix"); assertFalse(notADirectory.isDirectory()); try (ServerControls ignored = newInProcessBuilder().copyFrom(notADirectory).newServer()) { fail("server should not start"); } catch (RuntimeException rte) { Throwable cause = rte.getCause(); assertTrue(cause instanceof IOException); assertTrue(cause.getMessage().contains("exists but is not a directory")); } } private void assertDBConfig(ServerControls server, String expected, String key) throws JsonParseException { JsonNode beans = HTTP.GET(server.httpURI().toString() + "db/manage/server/jmx/domain/org.neo4j/") .get("beans"); JsonNode configurationBean = findNamedBean(beans, "Configuration").get("attributes"); boolean foundKey = false; for (JsonNode attribute : configurationBean) { if (attribute.get("name").asText().equals(key)) { assertThat(attribute.get("value").asText(), equalTo(expected)); foundKey = true; break; } } if (!foundKey) { fail("No config key '" + key + "'."); } } private JsonNode findNamedBean(JsonNode beans, String beanName) { for (JsonNode bean : beans) { JsonNode name = bean.get("name"); if (name != null && name.asText().endsWith(",name=" + beanName)) { return bean; } } throw new NoSuchElementException(); } private void trustAllSSLCerts() throws NoSuchAlgorithmException, KeyManagementException { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return null; } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } }