]> source.dussan.org Git - sonarqube.git/blob
a68c4121dea2c5051fea1e78d1dfc559fa11cc18
[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.server.common.health;
21
22 import java.util.Arrays;
23 import java.util.Random;
24 import java.util.Set;
25 import java.util.stream.IntStream;
26 import java.util.stream.Stream;
27 import org.junit.Test;
28 import org.sonar.process.cluster.health.NodeDetails;
29 import org.sonar.process.cluster.health.NodeHealth;
30 import org.sonar.server.health.Health;
31
32 import static java.util.stream.Collectors.toSet;
33 import static java.util.stream.Stream.of;
34 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
35 import static org.sonar.process.cluster.health.NodeHealth.Status.GREEN;
36 import static org.sonar.process.cluster.health.NodeHealth.Status.RED;
37 import static org.sonar.process.cluster.health.NodeHealth.Status.YELLOW;
38 import static org.sonar.server.common.health.HealthAssert.assertThat;
39
40 public class AppNodeClusterCheckTest {
41   private final Random random = new Random();
42
43   private AppNodeClusterCheck underTest = new AppNodeClusterCheck();
44
45   @Test
46   public void status_RED_when_no_application_node() {
47     Set<NodeHealth> nodeHealths = nodeHealths().collect(toSet());
48
49     Health check = underTest.check(nodeHealths);
50
51     assertThat(check)
52       .forInput(nodeHealths)
53       .hasStatus(Health.Status.RED)
54       .andCauses("No application node");
55   }
56
57   @Test
58   public void status_RED_when_single_RED_application_node() {
59     Set<NodeHealth> nodeHealths = nodeHealths(RED).collect(toSet());
60
61     Health check = underTest.check(nodeHealths);
62
63     assertThat(check)
64       .forInput(nodeHealths)
65       .hasStatus(Health.Status.RED)
66       .andCauses("Status of all application nodes is RED",
67         "There should be at least two application nodes");
68   }
69
70   @Test
71   public void status_YELLOW_when_single_YELLOW_application_node() {
72     Set<NodeHealth> nodeHealths = nodeHealths(YELLOW).collect(toSet());
73
74     Health check = underTest.check(nodeHealths);
75
76     assertThat(check)
77       .forInput(nodeHealths)
78       .hasStatus(Health.Status.YELLOW)
79       .andCauses(
80         "Status of all application nodes is YELLOW",
81         "There should be at least two application nodes");
82   }
83
84   @Test
85   public void status_YELLOW_when_single_GREEN_application_node() {
86     Set<NodeHealth> nodeHealths = nodeHealths(GREEN).collect(toSet());
87
88     Health check = underTest.check(nodeHealths);
89
90     assertThat(check)
91       .forInput(nodeHealths)
92       .hasStatus(Health.Status.YELLOW)
93       .andCauses("There should be at least two application nodes");
94   }
95
96   @Test
97   public void status_RED_when_two_RED_application_nodes() {
98     Set<NodeHealth> nodeHealths = nodeHealths(RED, RED).collect(toSet());
99
100     Health check = underTest.check(nodeHealths);
101
102     assertThat(check)
103       .forInput(nodeHealths)
104       .hasStatus(Health.Status.RED)
105       .andCauses("Status of all application nodes is RED");
106   }
107
108   @Test
109   public void status_YELLOW_when_two_YELLOW_application_nodes() {
110     Set<NodeHealth> nodeHealths = nodeHealths(YELLOW, YELLOW).collect(toSet());
111
112     Health check = underTest.check(nodeHealths);
113
114     assertThat(check)
115       .forInput(nodeHealths)
116       .hasStatus(Health.Status.YELLOW)
117       .andCauses("Status of all application nodes is YELLOW");
118   }
119
120   @Test
121   public void status_YELLOW_when_one_RED_node_and_one_YELLOW_application_node() {
122     Set<NodeHealth> nodeHealths = nodeHealths(RED, YELLOW).collect(toSet());
123
124     Health check = underTest.check(nodeHealths);
125
126     assertThat(check)
127       .forInput(nodeHealths)
128       .hasStatus(Health.Status.YELLOW)
129       .andCauses(
130         "At least one application node is RED",
131         "At least one application node is YELLOW");
132   }
133
134   @Test
135   public void status_YELLOW_when_one_RED_node_and_one_GREEN_application_node() {
136     Set<NodeHealth> nodeHealths = nodeHealths(RED, GREEN).collect(toSet());
137
138     Health check = underTest.check(nodeHealths);
139
140     assertThat(check)
141       .forInput(nodeHealths)
142       .hasStatus(Health.Status.YELLOW)
143       .andCauses("At least one application node is RED");
144   }
145
146   @Test
147   public void status_YELLOW_when_one_YELLOW_node_and_one_GREEN_application_node() {
148     Set<NodeHealth> nodeHealths = nodeHealths(YELLOW, GREEN).collect(toSet());
149
150     Health check = underTest.check(nodeHealths);
151
152     assertThat(check)
153       .forInput(nodeHealths)
154       .hasStatus(Health.Status.YELLOW)
155       .andCauses("At least one application node is YELLOW");
156   }
157
158   @Test
159   public void status_GREEN_when_two_GREEN_application_node() {
160     Set<NodeHealth> nodeHealths = nodeHealths(GREEN, GREEN).collect(toSet());
161
162     Health check = underTest.check(nodeHealths);
163
164     assertThat(check)
165       .forInput(nodeHealths)
166       .hasStatus(Health.Status.GREEN)
167       .andCauses();
168   }
169
170   @Test
171   public void status_GREEN_when_two_GREEN_application_node_and_any_number_of_other_is_GREEN() {
172     Set<NodeHealth> nodeHealths = of(
173       // at least 1 extra GREEN
174       of(appNodeHealth(GREEN)),
175       // 0 to 10 GREEN
176       randomNumberOfAppNodeHealthOfAnyStatus(GREEN),
177       // 2 GREEN
178       nodeHealths(GREEN, GREEN))
179       .flatMap(s -> s)
180       .collect(toSet());
181
182     Health check = underTest.check(nodeHealths);
183
184     assertThat(check)
185       .forInput(nodeHealths)
186       .hasStatus(Health.Status.GREEN)
187       .andCauses();
188   }
189
190   @Test
191   public void status_YELLOW_when_two_GREEN_application_node_and_any_number_of_other_is_YELLOW_or_GREEN() {
192     Set<NodeHealth> nodeHealths = of(
193       // at least 1 YELLOW
194       of(appNodeHealth(YELLOW)),
195       // 0 to 10 YELLOW/GREEN
196       randomNumberOfAppNodeHealthOfAnyStatus(GREEN, YELLOW),
197       // 2 GREEN
198       nodeHealths(GREEN, GREEN))
199       .flatMap(s -> s)
200       .collect(toSet());
201     Health check = underTest.check(nodeHealths);
202
203     assertThat(check)
204       .forInput(nodeHealths)
205       .hasStatus(Health.Status.YELLOW)
206       .andCauses("At least one application node is YELLOW");
207   }
208
209   @Test
210   public void status_YELLOW_when_two_GREEN_application_node_and_any_number_of_other_is_RED_or_GREEN() {
211     Set<NodeHealth> nodeHealths = of(
212       // at least 1 RED
213       of(appNodeHealth(RED)),
214       // 0 to 10 RED/GREEN
215       randomNumberOfAppNodeHealthOfAnyStatus(GREEN, RED),
216       // 2 GREEN
217       nodeHealths(GREEN, GREEN))
218       .flatMap(s -> s)
219       .collect(toSet());
220     Health check = underTest.check(nodeHealths);
221
222     assertThat(check)
223       .forInput(nodeHealths)
224       .hasStatus(Health.Status.YELLOW)
225       .andCauses("At least one application node is RED");
226   }
227
228   @Test
229   public void status_YELLOW_when_two_GREEN_application_node_and_any_number_of_other_is_either_RED_or_YELLOW() {
230     Set<NodeHealth> nodeHealths = of(
231       // at least 1 RED
232       of(appNodeHealth(RED)),
233       // at least 1 YELLOW
234       of(appNodeHealth(YELLOW)),
235       // 0 to 10 RED/YELLOW/GREEN
236       randomNumberOfAppNodeHealthOfAnyStatus(RED, YELLOW, GREEN),
237       // 2 GREEN
238       nodeHealths(GREEN, GREEN))
239       .flatMap(s -> s)
240       .collect(toSet());
241
242     Health check = underTest.check(nodeHealths);
243
244     assertThat(check)
245       .forInput(nodeHealths)
246       .hasStatus(Health.Status.YELLOW)
247       .andCauses(
248         "At least one application node is YELLOW",
249         "At least one application node is RED");
250   }
251
252   /**
253    * Between 0 and 10 NodeHealth of Application node with any of the specified statuses.
254    */
255   private Stream<NodeHealth> randomNumberOfAppNodeHealthOfAnyStatus(NodeHealth.Status... randomStatuses) {
256     return IntStream.range(0, random.nextInt(10))
257       .mapToObj(i -> appNodeHealth(randomStatuses[random.nextInt(randomStatuses.length)]));
258   }
259
260   private Stream<NodeHealth> nodeHealths(NodeHealth.Status... appNodeStatuses) {
261     return of(
262       // random number of Search nodes with random status
263       IntStream.range(0, random.nextInt(3))
264         .mapToObj(i -> appNodeHealth(NodeDetails.Type.SEARCH, NodeHealth.Status.values()[random.nextInt(NodeHealth.Status.values().length)])),
265       Arrays.stream(appNodeStatuses).map(this::appNodeHealth))
266       .flatMap(s -> s);
267   }
268
269   private NodeHealth appNodeHealth(NodeHealth.Status status) {
270     return appNodeHealth(NodeDetails.Type.APPLICATION, status);
271   }
272
273   private NodeHealth appNodeHealth(NodeDetails.Type type, NodeHealth.Status status) {
274     return NodeHealth.newNodeHealthBuilder()
275       .setStatus(status)
276       .setDetails(NodeDetails.newNodeDetailsBuilder()
277         .setType(type)
278         .setHost(randomAlphanumeric(32))
279         .setName(randomAlphanumeric(32))
280         .setPort(1 + random.nextInt(88))
281         .setStartedAt(1 + random.nextInt(54))
282         .build())
283       .build();
284   }
285
286 }