aboutsummaryrefslogtreecommitdiffstats
path: root/it/it-tests/src
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-07-26 14:40:09 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-07-29 10:31:31 +0200
commitf0b34e1199e974237c78870a4fca510c23addccd (patch)
treeee3610ec41d3cf3ef4f769dfb9b0fa66581b4c7e /it/it-tests/src
parent8259e91b4177a2e08a4ef72bef474db06da4e87b (diff)
downloadsonarqube-f0b34e1199e974237c78870a4fca510c23addccd.tar.gz
sonarqube-f0b34e1199e974237c78870a4fca510c23addccd.zip
SONAR-7899 configure container of "startup followers"
Diffstat (limited to 'it/it-tests/src')
-rw-r--r--it/it-tests/src/test/java/it/Category5Suite.java2
-rw-r--r--it/it-tests/src/test/java/it/serverSystem/ClusterTest.java125
2 files changed, 127 insertions, 0 deletions
diff --git a/it/it-tests/src/test/java/it/Category5Suite.java b/it/it-tests/src/test/java/it/Category5Suite.java
index 4f87a8880bc..1e3af4ff8c2 100644
--- a/it/it-tests/src/test/java/it/Category5Suite.java
+++ b/it/it-tests/src/test/java/it/Category5Suite.java
@@ -19,6 +19,7 @@
*/
package it;
+import it.serverSystem.ClusterTest;
import it.serverSystem.RestartTest;
import it.serverSystem.ServerSystemRestartingOrchestrator;
import it.settings.SettingsTestRestartingOrchestrator;
@@ -34,6 +35,7 @@ import org.junit.runners.Suite;
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({
+ ClusterTest.class,
ServerSystemRestartingOrchestrator.class,
RestartTest.class,
SettingsTestRestartingOrchestrator.class,
diff --git a/it/it-tests/src/test/java/it/serverSystem/ClusterTest.java b/it/it-tests/src/test/java/it/serverSystem/ClusterTest.java
new file mode 100644
index 00000000000..c0a9a887104
--- /dev/null
+++ b/it/it-tests/src/test/java/it/serverSystem/ClusterTest.java
@@ -0,0 +1,125 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 it.serverSystem;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.sonar.orchestrator.Orchestrator;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.io.FileUtils;
+import org.junit.Test;
+import org.sonarqube.ws.client.rule.SearchWsRequest;
+import util.ItUtils;
+
+import static org.apache.commons.lang3.StringUtils.containsIgnoreCase;
+import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.newWsClient;
+
+public class ClusterTest {
+
+ private static final String CONF_FILE_PATH = "conf/sonar.properties";
+
+ /**
+ * SONAR-7899
+ */
+ @Test
+ public void secondary_nodes_do_not_write_to_datastores_at_startup() throws Exception {
+ // start "startup leader", which creates and populates datastores
+ Orchestrator orchestrator = Orchestrator.builderEnv()
+ .setServerProperty("sonar.cluster.enabled", "true")
+ .setServerProperty("sonar.cluster.startupLeader", "true")
+ .setServerProperty("sonar.log.level", "TRACE")
+ .addPlugin(ItUtils.xooPlugin())
+ .build();
+ orchestrator.start();
+
+ expectLog(orchestrator, "Cluster enabled (startup leader)");
+ expectWriteOperations(orchestrator, true);
+ // verify that datastores are populated by requesting rules
+ assertThat(newWsClient(orchestrator).rules().search(new SearchWsRequest()).getTotal()).isGreaterThan(0);
+
+ FileUtils.write(orchestrator.getServer().getLogs(), "", false);
+ updateSonarPropertiesFile(orchestrator, ImmutableMap.of("sonar.cluster.startupLeader", "false"));
+ orchestrator.restartServer();
+
+ expectLog(orchestrator, "Cluster enabled (startup follower)");
+ expectWriteOperations(orchestrator, false);
+
+ orchestrator.stop();
+ }
+
+ private static void expectLog(Orchestrator orchestrator, String expectedLog) throws IOException {
+ File logFile = orchestrator.getServer().getLogs();
+ try (Stream<String> lines = Files.lines(logFile.toPath())) {
+ assertThat(lines.anyMatch(s -> containsIgnoreCase(s, expectedLog))).isTrue();
+ }
+ }
+
+ private static void expectWriteOperations(Orchestrator orchestrator, boolean expected) throws IOException {
+ try (Stream<String> lines = Files.lines(orchestrator.getServer().getLogs().toPath())) {
+ List<String> writeOperations = lines.filter(ClusterTest::isWriteOperation).collect(Collectors.toList());
+ if (expected) {
+ assertThat(writeOperations).isNotEmpty();
+ } else {
+ assertThat(writeOperations).as("Unexpected write operations: " + Joiner.on('\n').join(writeOperations)).isEmpty();
+
+ }
+ }
+ }
+
+ private static boolean isWriteOperation(String log) {
+ return isDbWriteOperation(log) || isEsWriteOperation(log);
+ }
+
+ private static boolean isDbWriteOperation(String log) {
+ return log.contains("web[sql]") && (containsIgnoreCase(log, "sql=insert") ||
+ containsIgnoreCase(log, "sql=update") ||
+ containsIgnoreCase(log, "sql=delete") ||
+ containsIgnoreCase(log, "sql=create"));
+ }
+
+ private static boolean isEsWriteOperation(String log) {
+ return log.contains("web[es]") && (containsIgnoreCase(log, "Create index") ||
+ containsIgnoreCase(log, "Create type") ||
+ containsIgnoreCase(log, "put mapping request") ||
+ containsIgnoreCase(log, "refresh request") ||
+ containsIgnoreCase(log, "index request"));
+ }
+
+ private static void updateSonarPropertiesFile(Orchestrator orchestrator, Map<String, String> props) throws IOException {
+ Properties propsFile = new Properties();
+ try (FileInputStream conf = FileUtils.openInputStream(new File(orchestrator.getServer().getHome(), CONF_FILE_PATH))) {
+ propsFile.load(conf);
+ propsFile.putAll(props);
+ }
+ try (FileOutputStream conf = FileUtils.openOutputStream(new File(orchestrator.getServer().getHome(), CONF_FILE_PATH))) {
+ propsFile.store(conf, "");
+ }
+ }
+}