From: Simon Brandhof Date: Thu, 21 Sep 2017 10:45:38 +0000 (+0200) Subject: SONAR-9802 add unit tests X-Git-Tag: 6.6-RC1~214 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a30d7540d9c3a262751c302aa00cdaba83461d15;p=sonarqube.git SONAR-9802 add unit tests --- diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/HazelcastTestHelper.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/HazelcastTestHelper.java deleted file mode 100644 index 07cb6f55d93..00000000000 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/HazelcastTestHelper.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.ce.container; - -import com.hazelcast.config.Config; -import com.hazelcast.config.JoinConfig; -import com.hazelcast.config.NetworkConfig; -import com.hazelcast.core.Hazelcast; -import com.hazelcast.core.HazelcastInstance; -import java.net.InetAddress; - -/** - * TODO move outside main sources - */ -public class HazelcastTestHelper { - private HazelcastTestHelper() { - // prevents instantiation - } - - public static HazelcastInstance createHazelcastCluster(String hostname, int port) { - Config hzConfig = new Config(); - hzConfig.getGroupConfig().setName("sonarqube"); - - // Configure the network instance - NetworkConfig netConfig = hzConfig.getNetworkConfig(); - netConfig - .setPort(port) - .setReuseAddress(true); - - netConfig.getInterfaces() - .setEnabled(true) - .addInterface(InetAddress.getLoopbackAddress().getHostAddress()); - - // Only allowing TCP/IP configuration - JoinConfig joinConfig = netConfig.getJoin(); - joinConfig.getAwsConfig().setEnabled(false); - joinConfig.getMulticastConfig().setEnabled(false); - joinConfig.getTcpIpConfig().setEnabled(true); - - // Tweak HazelCast configuration - hzConfig - // Increase the number of tries - .setProperty("hazelcast.tcp.join.port.try.count", "10") - // Don't bind on all interfaces - .setProperty("hazelcast.socket.bind.any", "false") - // Don't phone home - .setProperty("hazelcast.phone.home.enabled", "false") - // Use slf4j for logging - .setProperty("hazelcast.logging.type", "slf4j"); - - // Trying to resolve the hostname - hzConfig.getMemberAttributeConfig().setStringAttribute("HOSTNAME", hostname); - - // We are not using the partition group of Hazelcast, so disabling it - hzConfig.getPartitionGroupConfig().setEnabled(false); - HazelcastInstance hzInstance = Hazelcast.newHazelcastInstance(hzConfig); - return hzInstance; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoader.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoader.java index f3ffd959865..0999e401431 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoader.java @@ -23,5 +23,5 @@ import java.util.Collection; public interface AppNodesInfoLoader { - Collection load(); + Collection load() throws InterruptedException; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImpl.java index bb545a764eb..565178f40a8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImpl.java @@ -29,39 +29,35 @@ import org.sonar.api.server.ServerSide; import org.sonar.process.ProcessId; import org.sonar.process.cluster.hz.DistributedAnswer; import org.sonar.process.cluster.hz.HazelcastMember; +import org.sonar.process.cluster.hz.HazelcastMemberSelectors; import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; import static org.sonar.process.cluster.hz.HazelcastMember.Attribute.NODE_NAME; -import static org.sonar.process.cluster.hz.HazelcastMember.Attribute.PROCESS_KEY; @ServerSide public class AppNodesInfoLoaderImpl implements AppNodesInfoLoader { + /** + * Timeout to get information from all nodes + */ + private static final long DISTRIBUTED_TIMEOUT_MS = 15_000L; + private final HazelcastMember hzMember; public AppNodesInfoLoaderImpl(HazelcastMember hzMember) { this.hzMember = hzMember; } - public Collection load() { - try { - Map nodesByName = new HashMap<>(); - DistributedAnswer distributedAnswer = hzMember.call(ProcessInfoProvider::provide, new CeWebMemberSelector(), 15_000L); - for (Member member : distributedAnswer.getMembers()) { - String nodeName = member.getStringAttribute(NODE_NAME.getKey()); - NodeInfo nodeInfo = nodesByName.get(nodeName); - if (nodeInfo == null) { - nodeInfo = new NodeInfo(nodeName); - nodesByName.put(nodeName, nodeInfo); - } - completeNodeInfo(distributedAnswer, member, nodeInfo); - } - return nodesByName.values(); - - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException(e); + public Collection load() throws InterruptedException { + Map nodesByName = new HashMap<>(); + MemberSelector memberSelector = HazelcastMemberSelectors.selectorForProcessIds(ProcessId.WEB_SERVER, ProcessId.COMPUTE_ENGINE); + DistributedAnswer distributedAnswer = hzMember.call(ProcessInfoProvider::provide, memberSelector, DISTRIBUTED_TIMEOUT_MS); + for (Member member : distributedAnswer.getMembers()) { + String nodeName = member.getStringAttribute(NODE_NAME.getKey()); + NodeInfo nodeInfo = nodesByName.computeIfAbsent(nodeName, NodeInfo::new); + completeNodeInfo(distributedAnswer, member, nodeInfo); } + return nodesByName.values(); } private static void completeNodeInfo(DistributedAnswer distributedAnswer, Member member, NodeInfo nodeInfo) { @@ -75,12 +71,4 @@ public class AppNodesInfoLoaderImpl implements AppNodesInfoLoader { nodeAnswer.get().getSectionsList().forEach(nodeInfo::addSection); } } - - private static class CeWebMemberSelector implements MemberSelector { - @Override - public boolean select(Member member) { - String processKey = member.getStringAttribute(PROCESS_KEY.getKey()); - return processKey.equals(ProcessId.WEB_SERVER.getKey()) || processKey.equals(ProcessId.COMPUTE_ENGINE.getKey()); - } - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/BaseInfoWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/BaseInfoWsAction.java index 1af23c72a53..4f2607a96cc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/BaseInfoWsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/BaseInfoWsAction.java @@ -61,12 +61,12 @@ public abstract class BaseInfoWsAction implements SystemWsAction { } @Override - public void handle(Request request, Response response) { + public void handle(Request request, Response response) throws InterruptedException { userSession.checkIsSystemAdministrator(); doHandle(request, response); } - protected abstract void doHandle(Request request, Response response); + protected abstract void doHandle(Request request, Response response) throws InterruptedException; protected void writeSections(Collection sections, JsonWriter json) { SystemInfoUtils diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ClusterInfoAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ClusterInfoAction.java index f0208f2a84d..35c43865026 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ClusterInfoAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/ClusterInfoAction.java @@ -50,7 +50,7 @@ public class ClusterInfoAction extends BaseInfoWsAction { } @Override - protected void doHandle(Request request, Response response) { + protected void doHandle(Request request, Response response) throws InterruptedException { ClusterHealth clusterHealth = healthChecker.checkCluster(); try (JsonWriter json = response.newJsonWriter()) { json.beginObject(); @@ -69,7 +69,8 @@ public class ClusterInfoAction extends BaseInfoWsAction { writeSections(globalInfoLoader.load(), json); } - private void writeApplicationNodes(JsonWriter json, ClusterHealth clusterHealth) { + private void writeApplicationNodes(JsonWriter json, ClusterHealth clusterHealth) + throws InterruptedException { json.name("Application Nodes").beginArray(); Collection appNodes = appNodesInfoLoader.load(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImplTest.java new file mode 100644 index 00000000000..806e6712e0d --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/AppNodesInfoLoaderImplTest.java @@ -0,0 +1,91 @@ +/* + * 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.server.platform.monitoring.cluster; + +import com.hazelcast.core.Member; +import com.hazelcast.core.MemberSelector; +import java.io.IOException; +import java.util.Collection; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.sonar.process.cluster.hz.DistributedAnswer; +import org.sonar.process.cluster.hz.DistributedCall; +import org.sonar.process.cluster.hz.HazelcastMember; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo.Section; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo.SystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +public class AppNodesInfoLoaderImplTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private HazelcastMember hzMember = mock(HazelcastMember.class); + private AppNodesInfoLoaderImpl underTest = new AppNodesInfoLoaderImpl(hzMember); + + @Test + public void load_info_from_all_nodes() throws Exception { + DistributedAnswer answer = new DistributedAnswer<>(); + answer.setAnswer(newMember("foo"), SystemInfo.newBuilder().addSections(Section.newBuilder().build()).build()); + answer.setTimedOut(newMember("bar")); + answer.setFailed(newMember("baz"), new IOException("BOOM")); + when(hzMember.call(any(DistributedCall.class), any(MemberSelector.class), anyLong())).thenReturn(answer); + + Collection nodes = underTest.load(); + + assertThat(nodes).hasSize(3); + + NodeInfo successfulNodeInfo = findNode(nodes, "foo"); + assertThat(successfulNodeInfo.getName()).isEqualTo("foo"); + assertThat(successfulNodeInfo.getErrorMessage()).isEmpty(); + assertThat(successfulNodeInfo.getSections()).hasSize(1); + + NodeInfo timedOutNodeInfo = findNode(nodes, "bar"); + assertThat(timedOutNodeInfo.getName()).isEqualTo("bar"); + assertThat(timedOutNodeInfo.getErrorMessage()).hasValue("Failed to retrieve information on time"); + assertThat(timedOutNodeInfo.getSections()).isEmpty(); + + NodeInfo failedNodeInfo = findNode(nodes, "baz"); + assertThat(failedNodeInfo.getName()).isEqualTo("baz"); + assertThat(failedNodeInfo.getErrorMessage()).hasValue("Failed to retrieve information: BOOM"); + assertThat(failedNodeInfo.getSections()).isEmpty(); + } + + private NodeInfo findNode(Collection nodes, String name) { + return nodes.stream() + .filter(n -> n.getName().equals(name)) + .findFirst() + .orElseThrow(IllegalStateException::new); + } + + private Member newMember(String name) { + Member member = mock(Member.class, Mockito.RETURNS_DEEP_STUBS); + when(member.getStringAttribute(HazelcastMember.Attribute.NODE_NAME.getKey())).thenReturn(name); + return member; + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalInfoLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalInfoLoaderTest.java new file mode 100644 index 00000000000..df950be85dc --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalInfoLoaderTest.java @@ -0,0 +1,44 @@ +/* + * 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.server.platform.monitoring.cluster; + +import java.util.List; +import org.junit.Test; +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GlobalInfoLoaderTest { + + @Test + public void call_only_SystemInfoSection_that_inherit_Global() { + // two globals and one standard + SystemInfoSection[] sections = new SystemInfoSection[] { + new TestGlobalSystemInfoSection("foo"), new TestSystemInfoSection("bar"), new TestGlobalSystemInfoSection("baz")}; + + GlobalInfoLoader underTest = new GlobalInfoLoader(sections); + List loadedInfo = underTest.load(); + + assertThat(loadedInfo).extracting(ProtobufSystemInfo.Section::getName) + .containsExactlyInAnyOrder("foo", "baz"); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalSystemSectionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalSystemSectionTest.java new file mode 100644 index 00000000000..5d663f52a0e --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/GlobalSystemSectionTest.java @@ -0,0 +1,153 @@ +/* + * 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.server.platform.monitoring.cluster; + +import java.util.Optional; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.security.SecurityRealm; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; +import org.sonar.server.authentication.IdentityProviderRepositoryRule; +import org.sonar.server.authentication.TestIdentityProvider; +import org.sonar.server.platform.ServerId; +import org.sonar.server.platform.ServerIdLoader; +import org.sonar.server.user.SecurityRealmFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.process.systeminfo.SystemInfoUtils.attribute; +import static org.sonar.server.platform.monitoring.SystemInfoTesting.assertThatAttributeIs; + + +public class GlobalSystemSectionTest { + + private static final String SERVER_ID_PROPERTY = "Server ID"; + private static final String SERVER_ID_VALIDATED_PROPERTY = "Server ID validated"; + + @Rule + public IdentityProviderRepositoryRule identityProviderRepository = new IdentityProviderRepositoryRule(); + + private MapSettings settings = new MapSettings(); + private ServerIdLoader serverIdLoader = mock(ServerIdLoader.class); + private SecurityRealmFactory securityRealmFactory = mock(SecurityRealmFactory.class); + + private GlobalSystemSection underTest = new GlobalSystemSection(settings.asConfig(), + serverIdLoader, securityRealmFactory, identityProviderRepository); + + @Before + public void setUp() throws Exception { + when(serverIdLoader.getRaw()).thenReturn(Optional.empty()); + when(serverIdLoader.get()).thenReturn(Optional.empty()); + } + + @Test + public void name_is_not_empty() { + assertThat(underTest.toProtobuf().getName()).isEqualTo("System"); + } + + @Test + public void attributes_contain_information_about_valid_server_id() { + when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", true))); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThatAttributeIs(protobuf, SERVER_ID_PROPERTY, "ABC"); + assertThatAttributeIs(protobuf, SERVER_ID_VALIDATED_PROPERTY, true); + } + + @Test + public void attributes_contain_information_about_non_valid_server_id() { + when(serverIdLoader.get()).thenReturn(Optional.of(new ServerId("ABC", false))); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThatAttributeIs(protobuf, SERVER_ID_PROPERTY, "ABC"); + assertThatAttributeIs(protobuf, SERVER_ID_VALIDATED_PROPERTY, false); + } + + @Test + public void attributes_do_not_contain_information_about_server_id_if_absent() { + when(serverIdLoader.get()).thenReturn(Optional.empty()); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThat(attribute(protobuf, SERVER_ID_PROPERTY)).isNull(); + assertThat(attribute(protobuf, SERVER_ID_VALIDATED_PROPERTY)).isNull(); + } + + @Test + public void get_realm() throws Exception { + SecurityRealm realm = mock(SecurityRealm.class); + when(realm.getName()).thenReturn("LDAP"); + when(securityRealmFactory.getRealm()).thenReturn(realm); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThatAttributeIs(protobuf, "External User Authentication", "LDAP"); + } + + @Test + public void no_realm() throws Exception { + when(securityRealmFactory.getRealm()).thenReturn(null); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThat(attribute(protobuf, "External User Authentication")).isNull(); + } + + @Test + public void get_enabled_identity_providers() throws Exception { + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("github") + .setName("GitHub") + .setEnabled(true)); + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("bitbucket") + .setName("Bitbucket") + .setEnabled(true)); + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("disabled") + .setName("Disabled") + .setEnabled(false)); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThatAttributeIs(protobuf, "Accepted external identity providers", "Bitbucket, GitHub"); + } + + @Test + public void get_enabled_identity_providers_allowing_users_to_signup() throws Exception { + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("github") + .setName("GitHub") + .setEnabled(true) + .setAllowsUsersToSignUp(true)); + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("bitbucket") + .setName("Bitbucket") + .setEnabled(true) + .setAllowsUsersToSignUp(false)); + identityProviderRepository.addIdentityProvider(new TestIdentityProvider() + .setKey("disabled") + .setName("Disabled") + .setEnabled(false) + .setAllowsUsersToSignUp(true)); + + ProtobufSystemInfo.Section protobuf = underTest.toProtobuf(); + assertThatAttributeIs(protobuf, "External identity providers whose users are allowed to sign themselves up", "GitHub"); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/LoggingSectionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/LoggingSectionTest.java new file mode 100644 index 00000000000..91a704b542d --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/LoggingSectionTest.java @@ -0,0 +1,74 @@ +/* + * 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.server.platform.monitoring.cluster; + +import java.io.File; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; +import org.sonar.server.platform.ServerLogging; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.server.platform.monitoring.SystemInfoTesting.assertThatAttributeIs; + +public class LoggingSectionTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private SonarRuntime runtime = mock(SonarRuntime.class); + private ServerLogging logging = mock(ServerLogging.class); + private File logDir; + private LoggingSection underTest = new LoggingSection(runtime, logging); + + @Before + public void setUp() throws Exception { + logDir = temp.newFolder(); + when(logging.getLogsDir()).thenReturn(logDir); + when(logging.getRootLoggerLevel()).thenReturn(LoggerLevel.DEBUG); + } + + @Test + public void return_logging_attributes_of_compute_engine() { + when(runtime.getSonarQubeSide()).thenReturn(SonarQubeSide.COMPUTE_ENGINE); + + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + assertThat(section.getName()).isEqualTo("Compute Engine Logging"); + assertThatAttributeIs(section, "Logs Dir", logDir.getAbsolutePath()); + assertThatAttributeIs(section, "Logs Level", "DEBUG"); + } + + @Test + public void return_logging_attributes_of_web_server() { + when(runtime.getSonarQubeSide()).thenReturn(SonarQubeSide.SERVER); + + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + assertThat(section.getName()).isEqualTo("Web Logging"); + assertThatAttributeIs(section, "Logs Dir", logDir.getAbsolutePath()); + assertThatAttributeIs(section, "Logs Level", "DEBUG"); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/NodeSystemSectionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/NodeSystemSectionTest.java new file mode 100644 index 00000000000..8dd1ab55d41 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/NodeSystemSectionTest.java @@ -0,0 +1,102 @@ +/* + * 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.server.platform.monitoring.cluster; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.api.platform.Server; +import org.sonar.process.ProcessProperties; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; +import org.sonar.server.platform.monitoring.OfficialDistribution; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.process.systeminfo.SystemInfoUtils.attribute; +import static org.sonar.server.platform.monitoring.SystemInfoTesting.assertThatAttributeIs; + + +public class NodeSystemSectionTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private MapSettings settings = new MapSettings(); + private Server server = mock(Server.class, RETURNS_DEEP_STUBS); + private OfficialDistribution officialDistrib = mock(OfficialDistribution.class); + private NodeSystemSection underTest = new NodeSystemSection(settings.asConfig(), server, officialDistrib); + + @Test + public void test_section_name() { + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThat(section.getName()).isEqualTo("System"); + } + + @Test + public void return_server_version() { + when(server.getVersion()).thenReturn("6.6"); + + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThatAttributeIs(section, "Version", "6.6"); + } + + @Test + public void return_official_distribution_flag() { + when(officialDistrib.check()).thenReturn(true); + + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThatAttributeIs(section, "Official Distribution", true); + } + + @Test + public void return_nb_of_processors() { + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThat(attribute(section, "Processors").getLongValue()).isGreaterThan(0); + } + + @Test + public void return_dir_paths() { + settings.setProperty(ProcessProperties.PATH_HOME, "/home"); + settings.setProperty(ProcessProperties.PATH_DATA, "/data"); + settings.setProperty(ProcessProperties.PATH_TEMP, "/temp"); + settings.setProperty(ProcessProperties.PATH_LOGS, "/logs"); + settings.setProperty(ProcessProperties.PATH_WEB, "/web"); + + ProtobufSystemInfo.Section section = underTest.toProtobuf(); + + assertThatAttributeIs(section, "Home Dir", "/home"); + assertThatAttributeIs(section, "Data Dir", "/data"); + assertThatAttributeIs(section, "Temp Dir", "/temp"); + + // logs dir is part of LoggingSection + assertThat(attribute(section, "Logs Dir")).isNull(); + + // for internal usage + assertThat(attribute(section, "Web Dir")).isNull(); + + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/ProcessInfoProviderTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/ProcessInfoProviderTest.java new file mode 100644 index 00000000000..afc2ebcc4cb --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/ProcessInfoProviderTest.java @@ -0,0 +1,75 @@ +/* + * 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.server.platform.monitoring.cluster; + +import java.util.List; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProcessInfoProviderTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void set_self_as_statically_shared_instance() { + ProcessInfoProvider underTest = new ProcessInfoProvider(new SystemInfoSection[0]); + + underTest.start(); + assertThat(ProcessInfoProvider.provide()).isNotNull(); + + underTest.stop(); + + expectedException.expect(NullPointerException.class); + ProcessInfoProvider.provide(); + } + + @Test + public void remove_global_sections_from_results() { + ProcessInfoProvider underTest = new ProcessInfoProvider(new SystemInfoSection[]{ + new TestGlobalSystemInfoSection("foo"), + new TestSystemInfoSection("bar")}); + + underTest.start(); + List sections = ProcessInfoProvider.provide().getSectionsList(); + assertThat(sections).extracting(ProtobufSystemInfo.Section::getName).containsExactly("bar"); + + underTest.stop(); + } + + @Test + public void merge_sections() { + ProcessInfoProvider underTest = new ProcessInfoProvider(new SystemInfoSection[]{ + new TestSystemInfoSection("foo"), + new TestSystemInfoSection("bar")}); + + underTest.start(); + List sections = ProcessInfoProvider.provide().getSectionsList(); + assertThat(sections).extracting(ProtobufSystemInfo.Section::getName) + .containsExactlyInAnyOrder("foo", "bar"); + + underTest.stop(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/SearchNodesInfoLoaderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/SearchNodesInfoLoaderImplTest.java new file mode 100644 index 00000000000..ebb96e3f6ba --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/SearchNodesInfoLoaderImplTest.java @@ -0,0 +1,58 @@ +/* + * 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.server.platform.monitoring.cluster; + +import java.util.Collection; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; +import org.sonar.server.es.EsTester; +import org.sonar.server.es.FakeIndexDefinition; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SearchNodesInfoLoaderImplTest { + + @Rule + public EsTester es = new EsTester(new FakeIndexDefinition()); + + private SearchNodesInfoLoaderImpl underTest = new SearchNodesInfoLoaderImpl(es.client()); + + @Test + public void return_info_from_elasticsearch_api() { + Collection nodes = underTest.load(); + + assertThat(nodes).hasSize(1); + NodeInfo node = nodes.iterator().next(); + assertThat(node.getName()).isNotEmpty(); + assertThat(node.getSections()).hasSize(1); + ProtobufSystemInfo.Section stateSection = node.getSections().get(0); + + assertThat(stateSection.getAttributesList()) + .extracting(ProtobufSystemInfo.Attribute::getKey) + .contains( + "Disk Available", "Store Size", + "JVM Heap Usage", "JVM Heap Used", "JVM Heap Max", "JVM Non Heap Used", + "JVM Threads", + "Field Data Memory", "Field Data Circuit Breaker Limit", "Field Data Circuit Breaker Estimation", + "Request Circuit Breaker Limit", "Request Circuit Breaker Estimation", + "Query Cache Memory", "Request Cache Memory"); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java new file mode 100644 index 00000000000..1584360ce19 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestGlobalSystemInfoSection.java @@ -0,0 +1,37 @@ +/* + * 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.server.platform.monitoring.cluster; + +import org.sonar.process.systeminfo.Global; +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +class TestGlobalSystemInfoSection implements SystemInfoSection, Global { + private final String name; + + TestGlobalSystemInfoSection(String name) { + this.name = name; + } + + @Override + public ProtobufSystemInfo.Section toProtobuf() { + return ProtobufSystemInfo.Section.newBuilder().setName(name).build(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java new file mode 100644 index 00000000000..a682f43987d --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/cluster/TestSystemInfoSection.java @@ -0,0 +1,36 @@ +/* + * 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.server.platform.monitoring.cluster; + +import org.sonar.process.systeminfo.SystemInfoSection; +import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo; + +class TestSystemInfoSection implements SystemInfoSection { + private final String name; + + TestSystemInfoSection(String name) { + this.name = name; + } + + @Override + public ProtobufSystemInfo.Section toProtobuf() { + return ProtobufSystemInfo.Section.newBuilder().setName(name).build(); + } +}