/*
* 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.application.config;
import java.io.File;
import java.net.InetAddress;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.process.MessageException;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.application.config.JdbcSettings.Provider;
import static org.sonar.process.ProcessProperties.JDBC_URL;
public class JdbcSettingsTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
private JdbcSettings underTest = new JdbcSettings();
private File homeDir;
@Before
public void setUp() throws Exception {
homeDir = temp.newFolder();
}
@Test
public void resolve_H2_provider_when_props_is_empty_and_set_URL_to_default_H2() {
Props props = newProps();
assertThat(underTest.resolveProviderAndEnforceNonnullJdbcUrl(props))
.isEqualTo(Provider.H2);
assertThat(props.nonNullValue(JDBC_URL)).isEqualTo(String.format("jdbc:h2:tcp://%s:9092/sonar", InetAddress.getLoopbackAddress().getHostAddress()));
}
@Test
public void resolve_Oracle_when_jdbc_url_contains_oracle_in_any_case() {
checkProviderForUrlAndUnchangedUrl("jdbc:oracle:foo", Provider.ORACLE);
checkProviderForUrlAndUnchangedUrl("jdbc:OrAcLe:foo", Provider.ORACLE);
}
@Test
public void resolve_MySql_when_jdbc_url_contains_mysql_in_any_case() {
checkProviderForUrlAndUnchangedUrl("jdbc:mysql:foo", Provider.MYSQL);
checkProviderForUrlAndUnchangedUrl("jdbc:mYsQL:foo", Provider.MYSQL);
}
@Test
public void resolve_SqlServer_when_jdbc_url_contains_sqlserver_in_any_case() {
checkProviderForUrlAndUnchangedUrl("jdbc:sqlserver:foo", Provider.SQLSERVER);
checkProviderForUrlAndUnchangedUrl("jdbc:SQLSeRVeR:foo", Provider.SQLSERVER);
}
@Test
public void resolve_POSTGRESQL_when_jdbc_url_contains_POSTGRESQL_in_any_case() {
checkProviderForUrlAndUnchangedUrl("jdbc:postgresql:foo", Provider.POSTGRESQL);
checkProviderForUrlAndUnchangedUrl("jdbc:POSTGRESQL:foo", Provider.POSTGRESQL);
}
private void checkProviderForUrlAndUnchangedUrl(String url, Provider expected) {
Props props = newProps(JDBC_URL, url);
assertThat(underTest.resolveProviderAndEnforceNonnullJdbcUrl(props)).isEqualTo(expected);
assertThat(props.nonNullValue(JDBC_URL)).isEqualTo(url);
}
@Test
public void fail_with_MessageException_when_provider_is_not_supported() {
Props props = newProps(JDBC_URL, "jdbc:microsoft:sqlserver://localhost");
expectedException.expect(MessageException.class);
expectedException.expectMessage("Unsupported JDBC driver provider: microsoft");
underTest.resolveProviderAndEnforceNonnullJdbcUrl(props);
}
@Test
public void fail_with_MessageException_when_url_does_not_have_jdbc_prefix() {
Props props = newProps(JDBC_URL, "oracle:thin:@localhost/XE");
expectedException.expect(MessageException.class);
expectedException.expectMessage("Bad format of JDBC URL: oracle:thin:@localhost/XE");
underTest.resolveProviderAndEnforceNonnullJdbcUrl(props);
}
@Test
public void check_mysql_parameters() {
// minimal -> ok
underTest.checkUrlParameters(Provider.MYSQL,
"jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8");
// full -> ok
underTest.checkUrlParameters(Provider.MYSQL,
"jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance");
// missing required -> ko
expectedException.expect(MessageException.class);
expectedException.expectMessage("JDBC URL must have the property 'useUnicode=true'");
underTest.checkUrlParameters(Provider.MYSQL, "jdbc:mysql://localhost:3306/sonar?characterEncoding=utf8");
}
@Test
public void checkAndComplete_sets_driver_path_for_oracle() throws Exception {
File driverFile = new File(homeDir, "extensions/jdbc-driver/oracle/ojdbc6.jar");
FileUtils.touch(driverFile);
Props props = newProps(JDBC_URL, "jdbc:oracle:thin:@localhost/XE");
underTest.accept(props);
assertThat(props.nonNullValueAsFile(ProcessProperties.JDBC_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
public void sets_driver_path_for_h2() throws Exception {
File driverFile = new File(homeDir, "lib/jdbc/h2/h2.jar");
FileUtils.touch(driverFile);
Props props = newProps(JDBC_URL, "jdbc:h2:tcp://localhost:9092/sonar");
underTest.accept(props);
assertThat(props.nonNullValueAsFile(ProcessProperties.JDBC_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
public void checkAndComplete_sets_driver_path_for_postgresql() throws Exception {
File driverFile = new File(homeDir, "lib/jdbc/postgresql/pg.jar");
FileUtils.touch(driverFile);
Props props = newProps(JDBC_URL, "jdbc:postgresql://localhost/sonar");
underTest.accept(props);
assertThat(props.nonNullValueAsFile(ProcessProperties.JDBC_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
public void checkAndComplete_sets_driver_path_for_mssql() throws Exception {
File driverFile = new File(homeDir, "lib/jdbc/mssql/sqljdbc4.jar");
FileUtils.touch(driverFile);
Props props = newProps(JDBC_URL, "jdbc:sqlserver://localhost/sonar;SelectMethod=Cursor");
underTest.accept(props);
assertThat(props.nonNullValueAsFile(ProcessProperties.JDBC_DRIVER_PATH)).isEqualTo(driverFile);
}
@Test
public void driver_file() throws Exception {
File driverFile = new File(homeDir, "extensions/jdbc-driver/oracle/ojdbc6.jar");
FileUtils.touch(driverFile);
String path = underTest.driverPath(homeDir, Provider.ORACLE);
assertThat(path).isEqualTo(driverFile.getAbsolutePath());
}
@Test
public void driver_dir_does_not_exist() throws Exception {
expectedException.expect(MessageException.class);
expectedException.expectMessage("Directory does not exist: extensions/jdbc-driver/oracle");
underTest.driverPath(homeDir, Provider.ORACLE);
}
@Test
public void no_files_in_driver_dir() throws Exception {
FileUtils.forceMkdir(new File(homeDir, "extensions/jdbc-driver/oracle"));
expectedException.expect(MessageException.class);
expectedException.expectMessage("Directory does not contain JDBC driver: extensions/jdbc-driver/oracle");
underTest.driverPath(homeDir, Provider.ORACLE);
}
@Test
public void too_many_files_in_driver_dir() throws Exception {
FileUtils.touch(new File(homeDir, "extensions/jdbc-driver/oracle/ojdbc5.jar"));
FileUtils.touch(new File(homeDir, "extensions/jdbc-driver/oracle/ojdbc6.jar"));
expectedException.expect(MessageException.class);
expectedException.expectMessage("Directory must contain only one JAR file: extensions/jdbc-driver/oracle");
underTest.driverPath(homeDir, Provider.ORACLE);
}
private Props newProps(String... params) {
Properties properties = new Properties();
for (int i = 0; i < params.length; i++) {
properties.setProperty(params[i], params[i + 1]);
i++;
}
properties.setProperty(ProcessProperties.PATH_HOME, homeDir.getAbsolutePath());
return new Props(properties);
}
}