]> source.dussan.org Git - sonarqube.git/blob
0407f8a57f5f702b79172c6033433334b43b6f3b
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.application.cluster.health;
21
22 import java.util.Properties;
23 import java.util.Random;
24 import javax.annotation.Nullable;
25 import org.junit.Test;
26 import org.sonar.application.cluster.ClusterAppState;
27 import org.sonar.process.NetworkUtils;
28 import org.sonar.process.ProcessId;
29 import org.sonar.process.Props;
30 import org.sonar.process.cluster.health.NodeHealth;
31
32 import static java.lang.String.valueOf;
33 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
34 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
35 import static org.assertj.core.api.Assertions.assertThatThrownBy;
36 import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.when;
39 import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HOST;
40 import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HZ_PORT;
41 import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_NAME;
42
43 public class SearchNodeHealthProviderTest {
44
45   private final Random random = new Random();
46   private SearchNodeHealthProvider.Clock clock = mock(SearchNodeHealthProvider.Clock.class);
47   private NetworkUtils networkUtils = mock(NetworkUtils.class);
48   private ClusterAppState clusterAppState = mock(ClusterAppState.class);
49
50   @Test
51   public void constructor_throws_IAE_if_property_node_name_is_not_set() {
52     Props props = new Props(new Properties());
53
54     assertThatThrownBy(() -> new SearchNodeHealthProvider(props, clusterAppState, networkUtils))
55       .isInstanceOf(IllegalArgumentException.class)
56       .hasMessage("Missing property: sonar.cluster.node.name");
57   }
58
59   @Test
60   public void constructor_throws_NPE_if_NetworkUtils_getHostname_returns_null_and_property_is_not_set() {
61     Properties properties = new Properties();
62     properties.put(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
63     Props props = new Props(properties);
64
65     assertThatThrownBy(() -> new SearchNodeHealthProvider(props, clusterAppState, networkUtils, clock))
66       .isInstanceOf(NullPointerException.class);
67   }
68
69   @Test
70   public void constructor_throws_IAE_if_property_node_port_is_not_set() {
71     Properties properties = new Properties();
72     properties.put(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
73     when(networkUtils.getHostname()).thenReturn(randomAlphanumeric(34));
74     Props props = new Props(properties);
75
76     assertThatThrownBy(() -> new SearchNodeHealthProvider(props, clusterAppState, networkUtils, clock))
77       .isInstanceOf(IllegalArgumentException.class)
78       .hasMessage("Missing property: sonar.cluster.node.port");
79   }
80
81   @Test
82   public void constructor_throws_FormatException_if_property_node_port_is_not_an_integer() {
83     String port = randomAlphabetic(3);
84     Properties properties = new Properties();
85     properties.put(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
86     properties.put(CLUSTER_NODE_HZ_PORT.getKey(), port);
87     when(networkUtils.getHostname()).thenReturn(randomAlphanumeric(34));
88     Props props = new Props(properties);
89
90     assertThatThrownBy(() -> new SearchNodeHealthProvider(props, clusterAppState, networkUtils, clock))
91       .isInstanceOf(NumberFormatException.class)
92       .hasMessage("For input string: \"" + port + "\"");
93   }
94
95   @Test
96   public void get_returns_name_and_port_from_properties_at_constructor_time() {
97     String name = randomAlphanumeric(3);
98     int port = 1 + random.nextInt(4);
99     Properties properties = new Properties();
100     properties.setProperty(CLUSTER_NODE_NAME.getKey(), name);
101     properties.setProperty(CLUSTER_NODE_HZ_PORT.getKey(), valueOf(port));
102     when(networkUtils.getHostname()).thenReturn(randomAlphanumeric(34));
103     when(clock.now()).thenReturn(1L + random.nextInt(87));
104     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
105
106     NodeHealth nodeHealth = underTest.get();
107
108     assertThat(nodeHealth.getDetails().getName()).isEqualTo(name);
109     assertThat(nodeHealth.getDetails().getPort()).isEqualTo(port);
110
111     // change values in properties
112     properties.setProperty(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(6));
113     properties.setProperty(CLUSTER_NODE_HZ_PORT.getKey(), valueOf(1 + random.nextInt(99)));
114
115     NodeHealth newNodeHealth = underTest.get();
116
117     assertThat(newNodeHealth.getDetails().getName()).isEqualTo(name);
118     assertThat(newNodeHealth.getDetails().getPort()).isEqualTo(port);
119   }
120
121   @Test
122   public void get_returns_host_from_property_if_set_at_constructor_time() {
123     String host = randomAlphanumeric(55);
124     Properties properties = new Properties();
125     properties.setProperty(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
126     properties.setProperty(CLUSTER_NODE_HZ_PORT.getKey(), valueOf(1 + random.nextInt(4)));
127     properties.setProperty(CLUSTER_NODE_HOST.getKey(), host);
128     when(clock.now()).thenReturn(1L + random.nextInt(87));
129     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
130
131     NodeHealth nodeHealth = underTest.get();
132
133     assertThat(nodeHealth.getDetails().getHost()).isEqualTo(host);
134
135     // change now
136     properties.setProperty(CLUSTER_NODE_HOST.getKey(), randomAlphanumeric(96));
137
138     NodeHealth newNodeHealth = underTest.get();
139
140     assertThat(newNodeHealth.getDetails().getHost()).isEqualTo(host);
141   }
142
143   @Test
144   public void get_returns_host_from_NetworkUtils_getHostname_if_property_is_not_set_at_constructor_time() {
145     getReturnsHostFromNetworkUtils(null);
146   }
147
148   @Test
149   public void get_returns_host_from_NetworkUtils_getHostname_if_property_is_empty_at_constructor_time() {
150     getReturnsHostFromNetworkUtils(random.nextBoolean() ? "" : "   ");
151   }
152
153   private void getReturnsHostFromNetworkUtils(@Nullable String hostPropertyValue) {
154     String host = randomAlphanumeric(34);
155     Properties properties = new Properties();
156     properties.setProperty(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
157     properties.setProperty(CLUSTER_NODE_HZ_PORT.getKey(), valueOf(1 + random.nextInt(4)));
158     if (hostPropertyValue != null) {
159       properties.setProperty(CLUSTER_NODE_HOST.getKey(), hostPropertyValue);
160     }
161     when(clock.now()).thenReturn(1L + random.nextInt(87));
162     when(networkUtils.getHostname()).thenReturn(host);
163     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
164
165     NodeHealth nodeHealth = underTest.get();
166
167     assertThat(nodeHealth.getDetails().getHost()).isEqualTo(host);
168
169     // change now
170     when(networkUtils.getHostname()).thenReturn(randomAlphanumeric(96));
171
172     NodeHealth newNodeHealth = underTest.get();
173
174     assertThat(newNodeHealth.getDetails().getHost()).isEqualTo(host);
175   }
176
177   @Test
178   public void get_returns_started_from_System2_now_at_constructor_time() {
179     Properties properties = new Properties();
180     long now = setRequiredPropertiesAndMocks(properties);
181     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
182
183     NodeHealth nodeHealth = underTest.get();
184
185     assertThat(nodeHealth.getDetails().getStartedAt()).isEqualTo(now);
186
187     // change now
188     when(clock.now()).thenReturn(now);
189
190     NodeHealth newNodeHealth = underTest.get();
191
192     assertThat(newNodeHealth.getDetails().getStartedAt()).isEqualTo(now);
193   }
194
195   @Test
196   public void get_returns_status_GREEN_if_elasticsearch_process_is_operational_in_ClusterAppState() {
197     Properties properties = new Properties();
198     setRequiredPropertiesAndMocks(properties);
199     when(clusterAppState.isOperational(ProcessId.ELASTICSEARCH, true)).thenReturn(true);
200     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
201
202     NodeHealth nodeHealth = underTest.get();
203
204     assertThat(nodeHealth.getStatus()).isEqualTo(NodeHealth.Status.GREEN);
205   }
206
207   @Test
208   public void get_returns_status_RED_with_cause_if_elasticsearch_process_is_not_operational_in_ClusterAppState() {
209     Properties properties = new Properties();
210     setRequiredPropertiesAndMocks(properties);
211     when(clusterAppState.isOperational(ProcessId.ELASTICSEARCH, true)).thenReturn(false);
212     SearchNodeHealthProvider underTest = new SearchNodeHealthProvider(new Props(properties), clusterAppState, networkUtils, clock);
213
214     NodeHealth nodeHealth = underTest.get();
215
216     assertThat(nodeHealth.getStatus()).isEqualTo(NodeHealth.Status.RED);
217     assertThat(nodeHealth.getCauses()).containsOnly("Elasticsearch is not operational");
218   }
219
220   private long setRequiredPropertiesAndMocks(Properties properties) {
221     properties.setProperty(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(3));
222     properties.setProperty(CLUSTER_NODE_HZ_PORT.getKey(), valueOf(1 + random.nextInt(4)));
223     long now = 1L + random.nextInt(87);
224     when(clock.now()).thenReturn(now);
225     when(networkUtils.getHostname()).thenReturn(randomAlphanumeric(34));
226     return now;
227   }
228 }