From 66911824a39a84ae376020973d9fa79070a982a3 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Vilain Date: Mon, 22 Jul 2013 12:18:03 +0200 Subject: [PATCH] Added unit tests to improve branch coverage --- .../org/sonar/server/db/DatabaseMigrator.java | 8 +- .../org/sonar/server/db/EmbeddedDatabase.java | 43 ++++++----- .../server/db/EmbeddedDatabaseFactory.java | 13 ++-- .../sonar/server/db/DatabaseMigratorTest.java | 24 ++++++ .../db/EmbeddedDatabaseFactoryTest.java | 76 +++++++++++++++++++ .../sonar/server/db/EmbeddedDatabaseTest.java | 68 ++++++++++++++++- .../org/sonar/server/db/invalid_db_data_file | 0 7 files changed, 205 insertions(+), 27 deletions(-) create mode 100644 sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseFactoryTest.java create mode 100644 sonar-server/src/test/resources/org/sonar/server/db/invalid_db_data_file diff --git a/sonar-server/src/main/java/org/sonar/server/db/DatabaseMigrator.java b/sonar-server/src/main/java/org/sonar/server/db/DatabaseMigrator.java index bff94ff0613..f805b2de492 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/DatabaseMigrator.java +++ b/sonar-server/src/main/java/org/sonar/server/db/DatabaseMigrator.java @@ -19,6 +19,7 @@ */ package org.sonar.server.db; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.dbutils.DbUtils; import org.apache.ibatis.session.SqlSession; import org.slf4j.LoggerFactory; @@ -59,7 +60,7 @@ public class DatabaseMigrator implements ServerComponent { try { session = myBatis.openSession(); connection = session.getConnection(); - DdlUtils.createSchema(connection, database.getDialect().getId()); + createSchema(connection, database.getDialect().getId()); return true; } finally { MyBatis.closeQuietly(session); @@ -82,4 +83,9 @@ public class DatabaseMigrator implements ServerComponent { throw new IllegalStateException("Fail to execute database migration: " + className, e); } } + + @VisibleForTesting + protected void createSchema(Connection connection, String dialectId) { + DdlUtils.createSchema(connection, dialectId); + } } diff --git a/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabase.java b/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabase.java index d8698347fc7..ab1ed6ad22f 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabase.java +++ b/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabase.java @@ -19,6 +19,7 @@ */ package org.sonar.server.db; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang.StringUtils; import org.h2.Driver; import org.h2.tools.Server; @@ -42,25 +43,8 @@ public class EmbeddedDatabase { this.settings = settings; } - private static File getDataDirectory(Settings settings) { - String dirName = settings.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR); - if (!StringUtils.isBlank(dirName)) { - return new File(dirName); - } - - File sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME)); - if (sonarHome.isDirectory() && sonarHome.exists()) { - return new File(sonarHome, "data"); - } - - throw new IllegalStateException("SonarQube home directory does not exist"); - } - public void start() { File dbHome = getDataDirectory(settings); - if (dbHome.exists() && !dbHome.isDirectory()) { - throw new SonarException("Database home " + dbHome.getPath() + " is not a directory"); - } if (!dbHome.exists()) { dbHome.mkdirs(); } @@ -95,6 +79,31 @@ public class EmbeddedDatabase { } } + @VisibleForTesting + File getDataDirectory(Settings settings) { + String dirName = settings.getString(DatabaseProperties.PROP_EMBEDDED_DATA_DIR); + if (!StringUtils.isBlank(dirName)) { + return getEmbeddedDataDirectory(dirName); + } + return getSonarHomeDataDirectory(settings); + } + + private File getEmbeddedDataDirectory(String directoryName) { + File embeddedDataDirectory = new File(directoryName); + if(embeddedDataDirectory.exists() && !embeddedDataDirectory.isDirectory()) { + throw new SonarException("Database home " + embeddedDataDirectory.getAbsolutePath() + " is not a directory"); + } + return embeddedDataDirectory; + } + + private File getSonarHomeDataDirectory(Settings settings) { + File sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME)); + if (!sonarHome.isDirectory()) { + throw new IllegalStateException("SonarQube home directory is not valid"); + } + return new File(sonarHome, "data"); + } + private String getSetting(String name, String defaultValue) { return StringUtils.defaultIfBlank(settings.getString(name), defaultValue); } diff --git a/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabaseFactory.java b/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabaseFactory.java index 6ab6122a3b2..81d98be52d5 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabaseFactory.java +++ b/sonar-server/src/main/java/org/sonar/server/db/EmbeddedDatabaseFactory.java @@ -19,25 +19,23 @@ */ package org.sonar.server.db; +import com.google.common.annotations.VisibleForTesting; import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; -import org.sonar.core.persistence.dialect.H2; public class EmbeddedDatabaseFactory { private final Settings settings; - private final H2 dialect; private EmbeddedDatabase embeddedDatabase; public EmbeddedDatabaseFactory(Settings settings) { this.settings = settings; - dialect = new H2(); } public void start() { if (embeddedDatabase == null) { String jdbcUrl = settings.getString(DatabaseProperties.PROP_URL); - if (dialect.matchesJdbcURL(jdbcUrl)) { - embeddedDatabase = new EmbeddedDatabase(settings); + if (jdbcUrl.startsWith("jdbc:h2:tcp:")) { + embeddedDatabase = getEmbeddedDatabase(settings); embeddedDatabase.start(); } } @@ -48,4 +46,9 @@ public class EmbeddedDatabaseFactory { embeddedDatabase.stop(); } } + + @VisibleForTesting + EmbeddedDatabase getEmbeddedDatabase(Settings settings) { + return new EmbeddedDatabase(settings); + } } diff --git a/sonar-server/src/test/java/org/sonar/server/db/DatabaseMigratorTest.java b/sonar-server/src/test/java/org/sonar/server/db/DatabaseMigratorTest.java index 7977ecfa717..2cc20b3c5e3 100644 --- a/sonar-server/src/test/java/org/sonar/server/db/DatabaseMigratorTest.java +++ b/sonar-server/src/test/java/org/sonar/server/db/DatabaseMigratorTest.java @@ -19,14 +19,19 @@ */ package org.sonar.server.db; +import org.apache.ibatis.session.SqlSession; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.Database; import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.dialect.Dialect; +import org.sonar.core.persistence.dialect.H2; import org.sonar.core.persistence.dialect.MySql; +import java.sql.Connection; + import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.*; @@ -74,6 +79,25 @@ public class DatabaseMigratorTest extends AbstractDaoTestCase { assertThat(FakeMigration.executed).isTrue(); } + @Test + public void should_create_schema_on_h2() throws Exception { + + Dialect supportedDialect = new H2(); + when(database.getDialect()).thenReturn(supportedDialect); + Connection connection = mock(Connection.class); + SqlSession session = mock(SqlSession.class); + when(session.getConnection()).thenReturn(connection); + when(mybatis.openSession()).thenReturn(session); + + DatabaseMigrator databaseMigrator = new DatabaseMigrator(mybatis, database) { + @Override + protected void createSchema(Connection connection, String dialectId) { + } + }; + + assertThat(databaseMigrator.createDatabase()).isTrue(); + } + public static class FakeMigration implements DatabaseMigration { static boolean executed = false; @Override diff --git a/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseFactoryTest.java b/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseFactoryTest.java new file mode 100644 index 00000000000..79ed485350d --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseFactoryTest.java @@ -0,0 +1,76 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.server.db; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.Settings; +import org.sonar.api.database.DatabaseProperties; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class EmbeddedDatabaseFactoryTest { + + private Settings settings; + + @Before + public void initSettings() { + settings = new Settings(); + } + + @Test + public void should_start_and_stop_tcp_h2_database() throws Exception { + settings.setProperty(DatabaseProperties.PROP_URL, "jdbc:h2:tcp:localhost"); + + final EmbeddedDatabase embeddedDatabase = mock(EmbeddedDatabase.class); + + EmbeddedDatabaseFactory databaseFactory = new EmbeddedDatabaseFactory(settings) { + @Override + EmbeddedDatabase getEmbeddedDatabase(Settings settings) { + return embeddedDatabase; + } + }; + databaseFactory.start(); + databaseFactory.stop(); + + verify(embeddedDatabase).start(); + verify(embeddedDatabase).stop(); + } + + @Test + public void should_not_start_mem_h2_database() throws Exception { + settings.setProperty(DatabaseProperties.PROP_URL, "jdbc:h2:mem"); + + final EmbeddedDatabase embeddedDatabase = mock(EmbeddedDatabase.class); + + EmbeddedDatabaseFactory databaseFactory = new EmbeddedDatabaseFactory(settings) { + @Override + EmbeddedDatabase getEmbeddedDatabase(Settings settings) { + return embeddedDatabase; + } + }; + databaseFactory.start(); + + verify(embeddedDatabase, never()).start(); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseTest.java b/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseTest.java index 89a8016095f..c49514395b0 100644 --- a/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseTest.java +++ b/sonar-server/src/test/java/org/sonar/server/db/EmbeddedDatabaseTest.java @@ -20,23 +20,32 @@ package org.sonar.server.db; import org.h2.Driver; - +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; +import org.sonar.api.utils.SonarException; +import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.sql.DriverManager; import static junit.framework.Assert.fail; +import static org.fest.assertions.Assertions.assertThat; public class EmbeddedDatabaseTest { + + @Rule + public ExpectedException throwable = ExpectedException.none(); + @Test(timeout = 10000) public void should_start_and_stop() throws IOException { int port = freeServerPort(); - EmbeddedDatabase database = new EmbeddedDatabase(settings(port)); + EmbeddedDatabase database = new EmbeddedDatabase(testSettings(port)); database.start(); try { @@ -54,7 +63,7 @@ public class EmbeddedDatabaseTest { public void should_support_memory_database() throws IOException { int port = freeServerPort(); - EmbeddedDatabase database = new EmbeddedDatabase(settings(port) + EmbeddedDatabase database = new EmbeddedDatabase(testSettings(port) .setProperty(DatabaseProperties.PROP_URL, "jdbc:h2:tcp://localhost:" + port + "/mem:sonarIT;USER=sonar;PASSWORD=sonar")); database.start(); @@ -69,7 +78,58 @@ public class EmbeddedDatabaseTest { database.stop(); } - static Settings settings(int port) { + @Test + public void should_return_sonar_home_directory() throws Exception { + Settings settings = testSettings(0); + settings.setProperty(CoreProperties.SONAR_HOME, "."); + settings.setProperty(DatabaseProperties.PROP_EMBEDDED_DATA_DIR, ""); + + EmbeddedDatabase database = new EmbeddedDatabase(settings); + + File dataDirectory = database.getDataDirectory(settings); + assertThat(dataDirectory).isNotNull(); + assertThat(dataDirectory.getPath()).endsWith("data"); + } + + @Test + public void should_fail_on_invalid_sonar_home_directory() throws Exception { + throwable.expect(IllegalStateException.class); + + String testPath = getClass().getResource(".").getPath(); + + Settings settings = testSettings(0); + settings.setProperty(CoreProperties.SONAR_HOME, testPath + "/unmatched_directory"); + settings.setProperty(DatabaseProperties.PROP_EMBEDDED_DATA_DIR, ""); + + EmbeddedDatabase database = new EmbeddedDatabase(settings); + database.getDataDirectory(settings); + } + + @Test + public void should_return_embedded_data_directory() throws Exception { + + Settings settings = testSettings(0); + EmbeddedDatabase database = new EmbeddedDatabase(settings); + + File dataDirectory = database.getDataDirectory(settings); + assertThat(dataDirectory).isNotNull(); + assertThat(dataDirectory.getPath()).endsWith("testDB"); + } + + @Test + public void should_fail_on_invalid_data_directory() throws Exception { + throwable.expect(SonarException.class); + + String testPath = getClass().getResource(".").getPath(); + + Settings settings = testSettings(0); + settings.setProperty(DatabaseProperties.PROP_EMBEDDED_DATA_DIR, testPath + "/invalid_db_data_file"); + + EmbeddedDatabase database = new EmbeddedDatabase(settings); + database.start(); + } + + static Settings testSettings(int port) { return new Settings() .setProperty(DatabaseProperties.PROP_USER, "login") .setProperty(DatabaseProperties.PROP_PASSWORD, "pwd") diff --git a/sonar-server/src/test/resources/org/sonar/server/db/invalid_db_data_file b/sonar-server/src/test/resources/org/sonar/server/db/invalid_db_data_file new file mode 100644 index 00000000000..e69de29bb2d -- 2.39.5