/*
* 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.core.HazelcastInstance;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Date;
import java.util.Properties;
import java.util.stream.Collectors;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.MutablePicoContainer;
import org.sonar.api.CoreProperties;
import org.sonar.api.database.DatabaseProperties;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.ce.CeDistributedInformationImpl;
import org.sonar.ce.StandaloneCeDistributedInformation;
import org.sonar.ce.cluster.HazelcastClientWrapperImpl;
import org.sonar.ce.cluster.HazelcastTestHelper;
import org.sonar.db.DbTester;
import org.sonar.db.property.PropertyDto;
import org.sonar.process.NetworkUtils;
import org.sonar.process.ProcessId;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
import static java.lang.String.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
import static org.sonar.process.ProcessProperties.PATH_DATA;
import static org.sonar.process.ProcessProperties.PATH_HOME;
import static org.sonar.process.ProcessProperties.PATH_TEMP;
public class ComputeEngineContainerImplTest {
private static final int CONTAINER_ITSELF = 1;
private static final int COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION = CONTAINER_ITSELF + 1;
private static final String CLUSTER_NAME = "test";
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
private ComputeEngineContainerImpl underTest = new ComputeEngineContainerImpl();
@Test
public void constructor_does_not_create_container() {
assertThat(underTest.getComponentContainer()).isNull();
}
@Test
public void real_start_with_cluster() throws IOException {
int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
HazelcastInstance hzInstance = HazelcastTestHelper.createHazelcastCluster(CLUSTER_NAME, port);
Properties properties = getProperties();
properties.setProperty(ProcessProperties.CLUSTER_ENABLED, "true");
properties.setProperty(ProcessProperties.CLUSTER_LOCALENDPOINT, String.format("%s:%d", hzInstance.getCluster().getLocalMember().getAddress().getHost(), port));
properties.setProperty(ProcessProperties.CLUSTER_NAME, CLUSTER_NAME);
// required persisted properties
insertProperty(CoreProperties.SERVER_ID, "a_startup_id");
insertProperty(CoreProperties.SERVER_STARTTIME, DateUtils.formatDateTime(new Date()));
underTest
.start(new Props(properties));
MutablePicoContainer picoContainer = underTest.getComponentContainer().getPicoContainer();
assertThat(
picoContainer.getComponentAdapters().stream()
.map(ComponentAdapter::getComponentImplementation)
.collect(Collectors.toList())).contains((Class) HazelcastClientWrapperImpl.class,
(Class) CeDistributedInformationImpl.class);
underTest.stop();
}
@Test
public void real_start_without_cluster() throws IOException {
Properties properties = getProperties();
// required persisted properties
insertProperty(CoreProperties.SERVER_ID, "a_startup_id");
insertProperty(CoreProperties.SERVER_STARTTIME, DateUtils.formatDateTime(new Date()));
underTest
.start(new Props(properties));
MutablePicoContainer picoContainer = underTest.getComponentContainer().getPicoContainer();
assertThat(picoContainer.getComponentAdapters())
.hasSize(
CONTAINER_ITSELF
+ 73 // level 4
+ 4 // content of CeConfigurationModule
+ 4 // content of CeQueueModule
+ 3 // content of CeHttpModule
+ 3 // content of CeTaskCommonsModule
+ 4 // content of ProjectAnalysisTaskModule
+ 4 // content of CeTaskProcessorModule
+ 3 // CeCleaningModule + its content
+ 1 // CeDistributedInformation
);
assertThat(picoContainer.getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF
+ 5 // level 3
);
assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize(
CONTAINER_ITSELF
+ 10 // MigrationConfigurationModule
+ 17 // level 2
);
assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
+ 23 // level 1
+ 46 // content of DaoModule
+ 3 // content of EsSearchModule
+ 56 // content of CorePropertyDefinitions
);
assertThat(
picoContainer.getComponentAdapters().stream()
.map(ComponentAdapter::getComponentImplementation)
.collect(Collectors.toList())).doesNotContain((Class) HazelcastClientWrapperImpl.class,
(Class) CeDistributedInformationImpl.class).contains(
(Class) StandaloneCeDistributedInformation.class);
assertThat(picoContainer.getParent().getParent().getParent().getParent()).isNull();
underTest.stop();
assertThat(picoContainer.getLifecycleState().isStarted()).isFalse();
assertThat(picoContainer.getLifecycleState().isStopped()).isFalse();
assertThat(picoContainer.getLifecycleState().isDisposed()).isTrue();
}
private Properties getProperties() throws IOException {
Properties properties = ProcessProperties.defaults();
File homeDir = tempFolder.newFolder();
File dataDir = new File(homeDir, "data");
File tmpDir = new File(homeDir, "tmp");
properties.setProperty(PATH_HOME, homeDir.getAbsolutePath());
properties.setProperty(PATH_DATA, dataDir.getAbsolutePath());
properties.setProperty(PATH_TEMP, tmpDir.getAbsolutePath());
properties.setProperty(PROPERTY_PROCESS_INDEX, valueOf(ProcessId.COMPUTE_ENGINE.getIpcIndex()));
properties.setProperty(PROPERTY_SHARED_PATH, tmpDir.getAbsolutePath());
properties.setProperty(DatabaseProperties.PROP_URL, ((BasicDataSource) dbTester.database().getDataSource()).getUrl());
properties.setProperty(DatabaseProperties.PROP_USER, "sonar");
properties.setProperty(DatabaseProperties.PROP_PASSWORD, "sonar");
return properties;
}
private void insertProperty(String key, String value) {
PropertyDto dto = new PropertyDto().setKey(key).setValue(value);
dbTester.getDbClient().propertiesDao().saveProperty(dbTester.getSession(), dto);
dbTester.commit();
}
}