diff options
Diffstat (limited to 'server/sonar-process-monitor/src/test')
4 files changed, 278 insertions, 24 deletions
diff --git a/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java new file mode 100644 index 00000000000..594a921aac5 --- /dev/null +++ b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java @@ -0,0 +1,190 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.application.config; + +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Collections; +import java.util.Enumeration; +import org.junit.Before; +import org.junit.Rule; +import org.junit.experimental.theories.DataPoints; +import org.junit.experimental.theories.FromDataPoints; +import org.junit.experimental.theories.Theories; +import org.junit.experimental.theories.Theory; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.sonar.process.MessageException; + +import static java.lang.String.format; +import static org.sonar.process.ProcessProperties.CLUSTER_ENABLED; +import static org.sonar.process.ProcessProperties.CLUSTER_HOSTS; +import static org.sonar.process.ProcessProperties.CLUSTER_NETWORK_INTERFACES; +import static org.sonar.process.ProcessProperties.CLUSTER_SEARCH_HOSTS; +import static org.sonar.process.ProcessProperties.JDBC_URL; +import static org.sonar.process.ProcessProperties.SEARCH_HOST; + +@RunWith(Theories.class) +public class ClusterSettingsLoopbackTest { + + private TestAppSettings settings; + + @DataPoints("loopback_with_single_ip") + public static final String[] LOOPBACK_SINGLE_IP = { + "localhost", + "ip6-localhost", + "127.0.0.1", + "127.1.1.1", + "127.243.136.241", + "::1", + "0:0:0:0:0:0:0:1" + }; + + @DataPoints("loopback_with_multiple_ips") + public static final String[] LOOPBACK_IPS = { + "localhost", + "ip6-localhost", + "127.0.0.1", + "127.1.1.1", + "127.243.136.241", + "::1", + "0:0:0:0:0:0:0:1", + "127.0.0.1,192.168.11.25", + "192.168.11.25,127.1.1.1", + "2a01:e34:ef1f:dbb0:c2f6:a978:c5c0:9ccb,0:0:0:0:0:0:0:1", + "0:0:0:0:0:0:0:1,2a01:e34:ef1f:dbb0:c2f6:a978:c5c0:9ccb", + "2a01:e34:ef1f:dbb0:c3f6:a978:c5c0:9ccb,::1", + "::1,2a01:e34:ef1f:dbb0:c3f6:a978:c5c0:9ccb", + "::1,2a01:e34:ef1f:dbb0:c3f6:a978:c5c0:9ccb,2a01:e34:ef1f:dbb0:b3f6:a978:c5c0:9ccb" + }; + + @DataPoints("key_for_single_ip") + public static final String[] PROPERTY_KEYS_WITH_SINGLE_IP = { + SEARCH_HOST + }; + + @DataPoints("key_for_multiple_ips") + public static final String[] PROPERTY_KEYS_WITH_MULTIPLE_IPS = { + CLUSTER_NETWORK_INTERFACES, + CLUSTER_SEARCH_HOSTS, + CLUSTER_HOSTS + }; + + @DataPoints("key_with_local_ip") + public static final String[] PROPERTY_KEYS_ALL = { + CLUSTER_NETWORK_INTERFACES, + SEARCH_HOST + }; + + @DataPoints("not_local_address") + public static final String[] NOT_LOCAL_ADDRESS = { + "www.sonarqube.org", + "www.google.fr", + "www.google.com, www.sonarsource.com, wwww.sonarqube.org" + }; + + @DataPoints("unresolvable_hosts") + public static final String[] UNRESOLVABLE_HOSTS = { + "...", + "භඦආ\uD801\uDC8C\uD801\uDC8B" + }; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void resetSettings() { + settings = getClusterSettings(); + } + + @Theory + public void accept_throws_MessageException_if_not_local_address( + @FromDataPoints("key_with_local_ip") String propertyKey, + @FromDataPoints("not_local_address") String inet) { + settings.set(propertyKey, inet); + + expectedException.expect(MessageException.class); + expectedException.expectMessage(" is not a local address"); + + new ClusterSettings().accept(settings.getProps()); + } + + @Theory + public void accept_throws_MessageException_if_unresolvable_host( + @FromDataPoints("key_with_local_ip") String propertyKey, + @FromDataPoints("unresolvable_hosts") String inet) { + settings.set(propertyKey, inet); + + expectedException.expect(MessageException.class); + expectedException.expectMessage(" cannot be resolved"); + + new ClusterSettings().accept(settings.getProps()); + } + + @Theory + public void accept_throws_MessageException_if_loopback( + @FromDataPoints("key_for_single_ip") String propertyKey, + @FromDataPoints("loopback_with_single_ip") String inet) { + settings.set(propertyKey, inet); + checkLoopback(propertyKey); + } + + @Theory + public void accept_throws_MessageException_if_loopback_for_multiple_ips( + @FromDataPoints("key_for_multiple_ips") String propertyKey, + @FromDataPoints("loopback_with_multiple_ips") String inet) { + settings.set(propertyKey, inet); + checkLoopback(propertyKey); + } + + private void checkLoopback(String key) { + expectedException.expect(MessageException.class); + expectedException.expectMessage(format(" of [%s] must not be a loopback address", key)); + + new ClusterSettings().accept(settings.getProps()); + } + + private static TestAppSettings getClusterSettings() { + String localAddress = null; + try { + Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface networkInterface : Collections.list(nets)) { + if (!networkInterface.isLoopback() && networkInterface.isUp()) { + localAddress = networkInterface.getInetAddresses().nextElement().getHostAddress(); + } + } + if (localAddress == null) { + throw new RuntimeException("Cannot find a non loopback card required for tests"); + } + + } catch (SocketException e) { + throw new RuntimeException("Cannot find a non loopback card required for tests"); + } + + TestAppSettings testAppSettings = new TestAppSettings() + .set(CLUSTER_ENABLED, "true") + .set(CLUSTER_SEARCH_HOSTS, "192.168.233.1, 192.168.233.2,192.168.233.3") + .set(CLUSTER_HOSTS, "192.168.233.1, 192.168.233.2,192.168.233.3") + .set(SEARCH_HOST, localAddress) + .set(JDBC_URL, "jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance"); + return testAppSettings; + } +} diff --git a/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsTest.java b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsTest.java index 079cbf49b6a..3737f42ee22 100644 --- a/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsTest.java +++ b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/ClusterSettingsTest.java @@ -19,36 +19,49 @@ */ package org.sonar.application.config; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.process.MessageException; import org.sonar.process.ProcessProperties; +import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.process.ProcessId.COMPUTE_ENGINE; import static org.sonar.process.ProcessId.ELASTICSEARCH; import static org.sonar.process.ProcessId.WEB_SERVER; +import static org.sonar.process.ProcessProperties.CLUSTER_ENABLED; +import static org.sonar.process.ProcessProperties.CLUSTER_HOSTS; +import static org.sonar.process.ProcessProperties.CLUSTER_SEARCH_HOSTS; +import static org.sonar.process.ProcessProperties.JDBC_URL; +import static org.sonar.process.ProcessProperties.SEARCH_HOST; + public class ClusterSettingsTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - private TestAppSettings settings = new TestAppSettings(); + private TestAppSettings settings; + + @Before + public void resetSettings() { + settings = getClusterSettings(); + } @Test public void test_isClusterEnabled() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); assertThat(ClusterSettings.isClusterEnabled(settings)).isTrue(); - settings.set(ProcessProperties.CLUSTER_ENABLED, "false"); + settings.set(CLUSTER_ENABLED, "false"); assertThat(ClusterSettings.isClusterEnabled(settings)).isFalse(); } @Test public void isClusterEnabled_returns_false_by_default() { - assertThat(ClusterSettings.isClusterEnabled(settings)).isFalse(); + assertThat(ClusterSettings.isClusterEnabled(new TestAppSettings())).isFalse(); } @Test @@ -58,14 +71,14 @@ public class ClusterSettingsTest { @Test public void getEnabledProcesses_returns_all_processes_by_default_in_cluster_mode() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); assertThat(ClusterSettings.getEnabledProcesses(settings)).containsOnly(COMPUTE_ENGINE, ELASTICSEARCH, WEB_SERVER); } @Test public void getEnabledProcesses_returns_configured_processes_in_cluster_mode() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); settings.set(ProcessProperties.CLUSTER_SEARCH_DISABLED, "true"); assertThat(ClusterSettings.getEnabledProcesses(settings)).containsOnly(COMPUTE_ENGINE, WEB_SERVER); @@ -73,7 +86,7 @@ public class ClusterSettingsTest { @Test public void accept_throws_MessageException_if_internal_property_for_web_leader_is_configured() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); settings.set("sonar.cluster.web.startupLeader", "true"); expectedException.expect(MessageException.class); @@ -84,7 +97,7 @@ public class ClusterSettingsTest { @Test public void accept_does_nothing_if_cluster_is_disabled() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "false"); + settings.set(CLUSTER_ENABLED, "false"); // this property is supposed to fail if cluster is enabled settings.set("sonar.cluster.web.startupLeader", "true"); @@ -93,7 +106,7 @@ public class ClusterSettingsTest { @Test public void accept_throws_MessageException_if_h2() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); settings.set("sonar.jdbc.url", "jdbc:h2:mem"); expectedException.expect(MessageException.class); @@ -104,7 +117,7 @@ public class ClusterSettingsTest { @Test public void accept_throws_MessageException_if_default_jdbc_url() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.clearProperty(JDBC_URL); expectedException.expect(MessageException.class); expectedException.expectMessage("Embedded database is not supported in cluster mode"); @@ -119,16 +132,67 @@ public class ClusterSettingsTest { @Test public void isLocalElasticsearchEnabled_returns_true_by_default_in_cluster_mode() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); - assertThat(ClusterSettings.isLocalElasticsearchEnabled(settings)).isTrue(); } @Test public void isLocalElasticsearchEnabled_returns_false_if_local_es_node_is_disabled_in_cluster_mode() { - settings.set(ProcessProperties.CLUSTER_ENABLED, "true"); + settings.set(CLUSTER_ENABLED, "true"); settings.set(ProcessProperties.CLUSTER_SEARCH_DISABLED, "true"); assertThat(ClusterSettings.isLocalElasticsearchEnabled(settings)).isFalse(); } + + @Test + public void accept_throws_MessageException_if_searchHost_is_missing() { + settings.clearProperty(SEARCH_HOST); + checkMandatoryProperty(SEARCH_HOST); + } + + @Test + public void accept_throws_MessageException_if_searchHost_is_blank() { + settings.set(SEARCH_HOST, " "); + checkMandatoryProperty(SEARCH_HOST); + } + + @Test + public void accept_throws_MessageException_if_clusterHosts_is_missing() { + settings.clearProperty(CLUSTER_HOSTS); + checkMandatoryProperty(CLUSTER_HOSTS); + } + + @Test + public void accept_throws_MessageException_if_clusterHosts_is_blank() { + settings.set(CLUSTER_HOSTS, " "); + checkMandatoryProperty(CLUSTER_HOSTS); + } + + @Test + public void accept_throws_MessageException_if_clusterSearchHosts_is_missing() { + settings.clearProperty(CLUSTER_SEARCH_HOSTS); + checkMandatoryProperty(CLUSTER_SEARCH_HOSTS); + } + + @Test + public void accept_throws_MessageException_if_clusterSearchHosts_is_blank() { + settings.set(CLUSTER_SEARCH_HOSTS, " "); + checkMandatoryProperty(CLUSTER_SEARCH_HOSTS); + } + + private void checkMandatoryProperty(String key) { + expectedException.expect(MessageException.class); + expectedException.expectMessage(format("Property [%s] is mandatory", key)); + + new ClusterSettings().accept(settings.getProps()); + } + + private static TestAppSettings getClusterSettings() { + TestAppSettings testAppSettings = new TestAppSettings() + .set(CLUSTER_ENABLED, "true") + .set(CLUSTER_SEARCH_HOSTS, "localhost") + .set(CLUSTER_HOSTS, "192.168.233.1, 192.168.233.2,192.168.233.3") + .set(SEARCH_HOST, "192.168.233.1") + .set(JDBC_URL, "jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance"); + return testAppSettings; + } } diff --git a/server/sonar-process-monitor/src/test/java/org/sonar/application/config/TestAppSettings.java b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/TestAppSettings.java index 58971dd04b9..18f063f340b 100644 --- a/server/sonar-process-monitor/src/test/java/org/sonar/application/config/TestAppSettings.java +++ b/server/sonar-process-monitor/src/test/java/org/sonar/application/config/TestAppSettings.java @@ -31,30 +31,34 @@ import org.sonar.process.Props; */ public class TestAppSettings implements AppSettings { - private Props properties; + private Props props; public TestAppSettings() { - this.properties = new Props(new Properties()); - ProcessProperties.completeDefaults(this.properties); + this.props = new Props(new Properties()); + ProcessProperties.completeDefaults(this.props); } public TestAppSettings set(String key, String value) { - this.properties.set(key, value); + this.props.set(key, value); return this; } @Override public Props getProps() { - return properties; + return props; } @Override public Optional<String> getValue(String key) { - return Optional.ofNullable(properties.value(key)); + return Optional.ofNullable(props.value(key)); } @Override public void reload(Props copy) { - this.properties = copy; + this.props = copy; + } + + public void clearProperty(String key) { + this.props.rawProperties().remove(key); } } diff --git a/server/sonar-process-monitor/src/test/java/org/sonar/application/process/JavaProcessLauncherImplTest.java b/server/sonar-process-monitor/src/test/java/org/sonar/application/process/JavaProcessLauncherImplTest.java index 3beb208ec25..988d1b56e19 100644 --- a/server/sonar-process-monitor/src/test/java/org/sonar/application/process/JavaProcessLauncherImplTest.java +++ b/server/sonar-process-monitor/src/test/java/org/sonar/application/process/JavaProcessLauncherImplTest.java @@ -30,10 +30,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; -import org.sonar.application.process.JavaCommand; -import org.sonar.application.process.JavaProcessLauncher; -import org.sonar.application.process.JavaProcessLauncherImpl; -import org.sonar.application.process.ProcessMonitor; import org.sonar.process.AllProcessesCommands; import org.sonar.process.ProcessId; |