3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.application.cluster;
22 import com.hazelcast.core.HazelcastInstance;
23 import java.io.IOException;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.DisableOnDebug;
27 import org.junit.rules.ExpectedException;
28 import org.junit.rules.TestRule;
29 import org.junit.rules.Timeout;
30 import org.slf4j.Logger;
31 import org.sonar.application.AppStateListener;
32 import org.sonar.application.config.TestAppSettings;
33 import org.sonar.process.ProcessId;
34 import org.sonar.process.ProcessProperties;
36 import static org.assertj.core.api.Assertions.assertThat;
37 import static org.mockito.Matchers.anyString;
38 import static org.mockito.Matchers.eq;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.timeout;
41 import static org.mockito.Mockito.verify;
42 import static org.sonar.application.cluster.HazelcastTestHelper.createHazelcastClient;
43 import static org.sonar.application.cluster.HazelcastTestHelper.newClusterSettings;
44 import static org.sonar.process.cluster.ClusterObjectKeys.SONARQUBE_VERSION;
46 public class AppStateClusterImplTest {
49 public ExpectedException expectedException = ExpectedException.none();
52 public TestRule safeGuard = new DisableOnDebug(Timeout.seconds(10));
55 public void instantiation_throws_ISE_if_cluster_mode_is_disabled() throws Exception {
56 TestAppSettings settings = new TestAppSettings();
57 settings.set(ProcessProperties.CLUSTER_ENABLED, "false");
59 expectedException.expect(IllegalStateException.class);
60 expectedException.expectMessage("Cluster is not enabled on this instance");
62 new AppStateClusterImpl(settings);
66 public void tryToLockWebLeader_returns_true_only_for_the_first_call() throws Exception {
67 TestAppSettings settings = newClusterSettings();
69 try (AppStateClusterImpl underTest = new AppStateClusterImpl(settings)) {
70 assertThat(underTest.tryToLockWebLeader()).isEqualTo(true);
71 assertThat(underTest.tryToLockWebLeader()).isEqualTo(false);
76 public void log_when_sonarqube_is_joining_a_cluster () throws IOException, InterruptedException, IllegalAccessException, NoSuchFieldException {
77 // Now launch an instance that try to be part of the hzInstance cluster
78 TestAppSettings settings = newClusterSettings();
80 Logger logger = mock(Logger.class);
81 AppStateClusterImpl.setLogger(logger);
83 try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
85 eq("Joined the cluster [{}] that contains the following hosts : [{}]"),
93 public void test_listeners() throws InterruptedException {
94 AppStateListener listener = mock(AppStateListener.class);
95 try (AppStateClusterImpl underTest = new AppStateClusterImpl(newClusterSettings())) {
96 underTest.addListener(listener);
98 underTest.setOperational(ProcessId.ELASTICSEARCH);
99 verify(listener, timeout(20_000)).onAppStateOperational(ProcessId.ELASTICSEARCH);
101 assertThat(underTest.isOperational(ProcessId.ELASTICSEARCH, true)).isEqualTo(true);
102 assertThat(underTest.isOperational(ProcessId.APP, true)).isEqualTo(false);
103 assertThat(underTest.isOperational(ProcessId.WEB_SERVER, true)).isEqualTo(false);
104 assertThat(underTest.isOperational(ProcessId.COMPUTE_ENGINE, true)).isEqualTo(false);
109 public void registerSonarQubeVersion_publishes_version_on_first_call() {
110 TestAppSettings settings = newClusterSettings();
112 try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
113 appStateCluster.registerSonarQubeVersion("6.4.1.5");
115 HazelcastInstance hzInstance = createHazelcastClient(appStateCluster);
116 assertThat(hzInstance.getAtomicReference(SONARQUBE_VERSION).get())
118 .isInstanceOf(String.class)
119 .isEqualTo("6.4.1.5");
124 public void reset_throws_always_ISE() {
125 TestAppSettings settings = newClusterSettings();
127 try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
128 expectedException.expect(IllegalStateException.class);
129 expectedException.expectMessage("state reset is not supported in cluster mode");
130 appStateCluster.reset();
135 public void registerSonarQubeVersion_throws_ISE_if_initial_version_is_different() throws Exception {
136 // Now launch an instance that try to be part of the hzInstance cluster
137 TestAppSettings settings = newClusterSettings();
139 try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
140 // Register first version
141 appStateCluster.registerSonarQubeVersion("1.0.0");
143 expectedException.expect(IllegalStateException.class);
144 expectedException.expectMessage("The local version 2.0.0 is not the same as the cluster 1.0.0");
146 // Registering a second different version must trigger an exception
147 appStateCluster.registerSonarQubeVersion("2.0.0");