aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db/src/test
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2015-07-05 10:06:55 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-07-06 09:22:44 +0200
commit32af292b745b7226bacc3f34d612437664af0ba3 (patch)
tree538d0b9852eaeb08ad685d426ea61c8170210e40 /sonar-db/src/test
parent1df148803610cd54f182b8636f01c0e6ece92b19 (diff)
downloadsonarqube-32af292b745b7226bacc3f34d612437664af0ba3.tar.gz
sonarqube-32af292b745b7226bacc3f34d612437664af0ba3.zip
Move some classes from sonar-server to sonar-db
Diffstat (limited to 'sonar-db/src/test')
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java55
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java114
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java51
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DbTester.java196
-rw-r--r--sonar-db/src/test/java/org/sonar/db/MyBatisTest.java2
-rw-r--r--sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java176
-rw-r--r--sonar-db/src/test/java/org/sonar/db/TestDb.java175
-rw-r--r--sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java59
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java100
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java27
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java305
-rw-r--r--sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java212
-rw-r--r--sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java (renamed from sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java)64
-rw-r--r--sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java116
-rw-r--r--sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java17
-rw-r--r--sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java117
-rw-r--r--sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java333
-rw-r--r--sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java20
-rw-r--r--sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java8
-rw-r--r--sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java105
-rw-r--r--sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java175
-rw-r--r--sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java69
-rw-r--r--sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java229
-rw-r--r--sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql4
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml (renamed from sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml)0
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml7
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml32
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml90
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml48
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml64
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml65
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml26
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml24
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml12
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml27
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml37
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml26
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml36
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml35
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zipbin0 -> 578 bytes
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml27
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml59
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml22
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml32
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml21
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml10
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml14
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml14
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml19
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml19
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml22
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml12
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml8
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml17
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml9
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml9
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml16
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml8
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml7
92 files changed, 3376 insertions, 633 deletions
diff --git a/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
index 24987271dfb..fc7c4b1ef80 100644
--- a/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
@@ -19,67 +19,14 @@
*/
package org.sonar.db;
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import java.util.Collections;
-import java.util.List;
import org.junit.Test;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
public class DaoUtilsTest {
@Test
public void list_all_dao_classes() {
- List<Class> daoClasses = DaoUtils.getDaoClasses();
-
- assertThat(daoClasses).isNotEmpty();
- }
-
- @Test
- public void repeatCondition() {
- assertThat(DaoUtils.repeatCondition("uuid=?", 1, "or")).isEqualTo("uuid=?");
- assertThat(DaoUtils.repeatCondition("uuid=?", 3, "or")).isEqualTo("uuid=? or uuid=? or uuid=?");
- }
-
- @Test
- public void execute_large_inputs() {
- List<Integer> inputs = newArrayList();
- List<String> expectedOutputs = newArrayList();
- for (int i = 0; i < 2010; i++) {
- inputs.add(i);
- expectedOutputs.add(Integer.toString(i));
- }
-
- List<String> outputs = DaoUtils.executeLargeInputs(inputs, new Function<List<Integer>, List<String>>() {
- @Override
- public List<String> apply(List<Integer> input) {
- // Check that each partition is only done on 1000 elements max
- assertThat(input.size()).isLessThanOrEqualTo(1000);
- return newArrayList(Iterables.transform(input, new Function<Integer, String>() {
- @Override
- public String apply(Integer input) {
- return Integer.toString(input);
- }
- }));
- }
- });
-
- assertThat(outputs).isEqualTo(expectedOutputs);
- }
-
- @Test
- public void execute_large_inputs_on_empty_list() {
- List<String> outputs = DaoUtils.executeLargeInputs(Collections.<Integer>emptyList(), new Function<List<Integer>, List<String>>() {
- @Override
- public List<String> apply(List<Integer> input) {
- fail("No partition should be made on empty list");
- return Collections.emptyList();
- }
- });
-
- assertThat(outputs).isEmpty();
+ assertThat(DaoUtils.getDaoClasses()).isNotEmpty();
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java b/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java
new file mode 100644
index 00000000000..2902ac122f9
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java
@@ -0,0 +1,114 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db;
+
+import java.sql.SQLException;
+import org.apache.commons.lang.StringUtils;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.sonar.api.utils.MessageException;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DatabaseCheckerTest {
+
+ @Test
+ public void requires_oracle_driver_11_2() throws Exception {
+ Database db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "11.3.1");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "12.0.2");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "11.1.0.2");
+ try {
+ new DatabaseChecker(db).start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Unsupported Oracle JDBC driver version: 11.1.0.2. Minimal required version is 11.2.");
+ }
+ }
+
+ @Test
+ public void requires_oracle_11g_or_greater() throws Exception {
+ // oracle 11.0 is ok
+ Database db = mockDb(new Oracle(), "11.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.1 is ok
+ db = mockDb(new Oracle(), "11.1.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.2 is ok
+ db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 12 is ok
+ db = mockDb(new Oracle(), "12.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 10 is not supported
+ db = mockDb(new Oracle(), "10.2.1", "11.2.0.0.1");
+ try {
+ new DatabaseChecker(db).start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Unsupported Oracle version: 10.2.1. Minimal required version is 11.");
+ }
+ }
+
+ @Test
+ public void log_warning_if_h2() throws Exception {
+ Database db = mockDb(new H2(), "13.4", "13.4");
+ DatabaseChecker checker = new DatabaseChecker(db);
+ checker.start();
+ checker.stop();
+ // TODO test log
+ }
+
+ @Test
+ public void do_not_fail_if_mysql() throws Exception {
+ Database db = mockDb(new MySql(), "5.7", "5.7");
+ new DatabaseChecker(db).start();
+ // no error
+ }
+
+ private Database mockDb(Dialect dialect, String dbVersion, String driverVersion) throws SQLException {
+ Database db = mock(Database.class, Mockito.RETURNS_DEEP_STUBS);
+ when(db.getDialect()).thenReturn(dialect);
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(Integer.parseInt(StringUtils.substringBefore(dbVersion, ".")));
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseProductVersion()).thenReturn(dbVersion);
+ when(db.getDataSource().getConnection().getMetaData().getDriverVersion()).thenReturn(driverVersion);
+ return db;
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
index 933e931ac03..1b6acbb3eb2 100644
--- a/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
@@ -19,15 +19,21 @@
*/
package org.sonar.db;
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
import org.junit.Test;
import org.sonar.db.dialect.Oracle;
+import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -142,4 +148,49 @@ public class DatabaseUtilsTest extends AbstractDaoTestCase {
}
return sql;
}
+
+ @Test
+ public void repeatCondition() {
+ assertThat(DatabaseUtils.repeatCondition("uuid=?", 1, "or")).isEqualTo("uuid=?");
+ assertThat(DatabaseUtils.repeatCondition("uuid=?", 3, "or")).isEqualTo("uuid=? or uuid=? or uuid=?");
+ }
+
+ @Test
+ public void execute_large_inputs() {
+ List<Integer> inputs = newArrayList();
+ List<String> expectedOutputs = newArrayList();
+ for (int i = 0; i < 2010; i++) {
+ inputs.add(i);
+ expectedOutputs.add(Integer.toString(i));
+ }
+
+ List<String> outputs = DatabaseUtils.executeLargeInputs(inputs, new Function<List<Integer>, List<String>>() {
+ @Override
+ public List<String> apply(List<Integer> input) {
+ // Check that each partition is only done on 1000 elements max
+ assertThat(input.size()).isLessThanOrEqualTo(1000);
+ return newArrayList(Iterables.transform(input, new Function<Integer, String>() {
+ @Override
+ public String apply(Integer input) {
+ return Integer.toString(input);
+ }
+ }));
+ }
+ });
+
+ assertThat(outputs).isEqualTo(expectedOutputs);
+ }
+
+ @Test
+ public void execute_large_inputs_on_empty_list() {
+ List<String> outputs = DatabaseUtils.executeLargeInputs(Collections.<Integer>emptyList(), new Function<List<Integer>, List<String>>() {
+ @Override
+ public List<String> apply(List<Integer> input) {
+ fail("No partition should be made on empty list");
+ return Collections.emptyList();
+ }
+ });
+
+ assertThat(outputs).isEmpty();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/DbTester.java b/sonar-db/src/test/java/org/sonar/db/DbTester.java
index ba428c5cbe8..dfa4e9cfef0 100644
--- a/sonar-db/src/test/java/org/sonar/db/DbTester.java
+++ b/sonar-db/src/test/java/org/sonar/db/DbTester.java
@@ -20,14 +20,8 @@
package org.sonar.db;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -36,19 +30,13 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.dbutils.QueryRunner;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.text.StrSubstitutor;
import org.dbunit.Assertion;
-import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.DatabaseUnitException;
-import org.dbunit.IDatabaseTester;
import org.dbunit.assertion.DiffCollectingFailureHandler;
import org.dbunit.assertion.Difference;
import org.dbunit.database.DatabaseConfig;
@@ -61,13 +49,10 @@ import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.ext.mssql.InsertIdentityOperation;
import org.dbunit.operation.DatabaseOperation;
-import org.junit.AssumptionViolatedException;
+import org.junit.After;
import org.junit.rules.ExternalResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.config.Settings;
-import org.sonar.db.deprecated.NullQueue;
-import org.sonar.db.dialect.Dialect;
+import org.picocontainer.containers.TransientPicoContainer;
+import org.sonar.api.utils.System2;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
@@ -78,96 +63,77 @@ import static org.junit.Assert.fail;
* This class should be call using @ClassRule in order to create the schema once (ft @Rule is used
* the schema will be recreated before each test).
* Data will be truncated each time you call prepareDbUnit().
- * <p/>
+ * <p>
* File using {@link DbTester} must be annotated with {@link org.sonar.test.DbTests} so
* that they can be executed on all supported DBs (Oracle, MySQL, ...).
*/
public class DbTester extends ExternalResource {
- private static final Logger LOG = LoggerFactory.getLogger(DbTester.class);
+ private final System2 system2;
+ private final TestDb db;
+ private DbClient2 client;
+ private DbSession session = null;
- private Database db;
- private DatabaseCommands commands;
- private IDatabaseTester tester;
- private MyBatis myBatis;
- private String schemaPath = null;
-
- public DbTester schema(Class baseClass, String filename) {
- String path = StringUtils.replaceChars(baseClass.getCanonicalName(), '.', '/');
- schemaPath = path + "/" + filename;
- return this;
+ @Deprecated
+ public DbTester() {
+ this.system2 = System2.INSTANCE;
+ this.db = TestDb.create(null);
}
- @Override
- protected void before() throws Throwable {
- Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties()));
- if (settings.hasKey("orchestrator.configUrl")) {
- loadOrchestratorSettings(settings);
- }
- String login = settings.getString("sonar.jdbc.username");
- for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
- LOG.info(key + ": " + settings.getString(key));
- }
- String dialect = settings.getString("sonar.jdbc.dialect");
- if (dialect != null && !"h2".equals(dialect)) {
- db = new DefaultDatabase(settings);
- } else {
- db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
- }
- db.start();
- if (schemaPath != null) {
- // will fail if not H2
- if (db.getDialect().getId().equals("h2")) {
- ((H2Database) db).executeScript(schemaPath);
- } else {
- db.stop();
- throw new AssumptionViolatedException("Test disabled because it supports only H2");
- }
- }
- LOG.info("Test Database: " + db);
-
- commands = DatabaseCommands.forDialect(db.getDialect());
- tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
-
- myBatis = new MyBatis(db, new NullQueue());
- myBatis.start();
+ private DbTester(System2 system2, @Nullable String schemaPath) {
+ this.system2 = system2;
+ this.db = TestDb.create(schemaPath);
+ }
- truncateTables();
+ public static DbTester create(System2 system2) {
+ return new DbTester(system2, null);
}
- public void truncateTables() {
- try {
- commands.truncateDatabase(db.getDataSource());
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to truncate db tables", e);
- }
+ public static DbTester createForSchema(System2 system2, Class testClass, String filename) {
+ String path = StringUtils.replaceChars(testClass.getCanonicalName(), '.', '/');
+ String schemaPath = path + "/" + filename;
+ return new DbTester(system2, schemaPath);
}
@Override
- protected void after() {
- db.stop();
- db = null;
- myBatis = null;
+ protected void before() throws Throwable {
+ truncateTables();
}
- public Database database() {
- return db;
+ @After
+ public void closeSession() throws Exception {
+ if (session != null) {
+ MyBatis.closeQuietly(session);
+ }
}
- public Dialect dialect() {
- return db.getDialect();
+ public DbSession getSession() {
+ if (session == null) {
+ session = db.getMyBatis().openSession(false);
+ }
+ return session;
}
- public MyBatis myBatis() {
- return myBatis;
+ public void truncateTables() {
+ db.truncateTables();
}
- public Connection openConnection() throws SQLException {
- return db.getDataSource().getConnection();
+ public DbClient2 getDbClient() {
+ if (client == null) {
+ TransientPicoContainer ioc = new TransientPicoContainer();
+ ioc.addComponent(db.getMyBatis());
+ ioc.addComponent(system2);
+ for (Class daoClass : DaoUtils.getDaoClasses()) {
+ ioc.addComponent(daoClass);
+ }
+ List<Dao> daos = ioc.getComponents(Dao.class);
+ client = new DbClient2(db.getMyBatis(), daos.toArray(new Dao[daos.size()]));
+ }
+ return client;
}
public void executeUpdateSql(String sql) {
- try (Connection connection = openConnection()) {
+ try (Connection connection = db.getDatabase().getDataSource().getConnection()) {
new QueryRunner().update(connection, sql);
} catch (Exception e) {
throw new IllegalStateException("Fail to execute sql: " + sql);
@@ -191,7 +157,7 @@ public class DbTester extends ExternalResource {
Preconditions.checkArgument(StringUtils.contains(sql, "count("),
"Parameter must be a SQL request containing 'count(x)' function. Got " + sql);
try (
- Connection connection = openConnection();
+ Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
@@ -206,7 +172,7 @@ public class DbTester extends ExternalResource {
public List<Map<String, Object>> select(String selectSql) {
try (
- Connection connection = openConnection();
+ Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement(selectSql);
ResultSet rs = stmt.executeQuery()) {
return getHashMap(rs);
@@ -259,8 +225,7 @@ public class DbTester extends ExternalResource {
public void prepareDbUnit(Class testClass, String... testNames) {
InputStream[] streams = new InputStream[testNames.length];
try {
- // Purge previous data
- commands.truncateDatabase(db.getDataSource());
+ db.truncateTables();
for (int i = 0; i < testNames.length; i++) {
String path = "/" + testClass.getName().replace('.', '/') + "/" + testNames[i];
@@ -271,7 +236,7 @@ public class DbTester extends ExternalResource {
}
prepareDbUnit(streams);
- commands.resetPrimaryKeys(db.getDataSource());
+ db.getCommands().resetPrimaryKeys(db.getDatabase().getDataSource());
} catch (SQLException e) {
throw translateException("Could not setup DBUnit data", e);
} finally {
@@ -288,9 +253,9 @@ public class DbTester extends ExternalResource {
for (int i = 0; i < dataSetStream.length; i++) {
dataSets[i] = dbUnitDataSet(dataSetStream[i]);
}
- tester.setDataSet(new CompositeDataSet(dataSets));
+ db.getDbUnitTester().setDataSet(new CompositeDataSet(dataSets));
connection = dbUnitConnection();
- new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, tester.getDataSet());
+ new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, db.getDbUnitTester().getDataSet());
} catch (Exception e) {
throw translateException("Could not setup DBUnit data", e);
} finally {
@@ -339,7 +304,7 @@ public class DbTester extends ExternalResource {
}
public void assertColumnDefinition(String table, String column, int expectedType, @Nullable Integer expectedSize) {
- try (Connection connection = openConnection();
+ try (Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement("select * from " + table);
ResultSet res = stmt.executeQuery()) {
Integer columnIndex = getColumnIndex(res, column);
@@ -389,8 +354,8 @@ public class DbTester extends ExternalResource {
private IDatabaseConnection dbUnitConnection() {
try {
- IDatabaseConnection connection = tester.getConnection();
- connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, commands.getDbUnitFactory());
+ IDatabaseConnection connection = db.getDbUnitTester().getConnection();
+ connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, db.getDbUnitFactory());
return connection;
} catch (Exception e) {
throw translateException("Error while getting connection", e);
@@ -413,36 +378,6 @@ public class DbTester extends ExternalResource {
return runtimeException;
}
- private void loadOrchestratorSettings(Settings settings) throws URISyntaxException, IOException {
- String url = settings.getString("orchestrator.configUrl");
- URI uri = new URI(url);
- InputStream input = null;
- try {
- if (url.startsWith("file:")) {
- File file = new File(uri);
- input = FileUtils.openInputStream(file);
- } else {
- HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
- int responseCode = connection.getResponseCode();
- if (responseCode >= 400) {
- throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode);
- }
-
- input = connection.getInputStream();
-
- }
- Properties props = new Properties();
- props.load(input);
- settings.addProperties(props);
- for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) {
- String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}");
- settings.setProperty(entry.getKey(), interpolatedValue);
- }
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
-
private static void doClobFree(Clob clob) throws SQLException {
try {
clob.free();
@@ -450,4 +385,19 @@ public class DbTester extends ExternalResource {
// JTS driver do not implement free() as it's using JDBC 3.0
}
}
+
+ @Deprecated
+ public MyBatis myBatis() {
+ return db.getMyBatis();
+ }
+
+ @Deprecated
+ public Connection openConnection() throws Exception {
+ return db.getDatabase().getDataSource().getConnection();
+ }
+
+ @Deprecated
+ public Database database() {
+ return db.getDatabase();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
index 194346fe0a0..87922b13faf 100644
--- a/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
@@ -63,7 +63,7 @@ public class MyBatisTest {
MyBatis myBatis = new MyBatis(database, queue);
myBatis.start();
- SqlSession session = myBatis.openBatchSession();
+ SqlSession session = myBatis.openSession(false);
try {
assertThat(session.getConnection(), notNullValue());
assertThat(session.getMapper(RuleMapper.class), notNullValue());
diff --git a/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java b/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java
new file mode 100644
index 00000000000..970f9090fd1
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java
@@ -0,0 +1,176 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.NoSuchElementException;
+import org.apache.commons.dbutils.DbUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+@Category(DbTests.class)
+public class ResultSetIteratorTest {
+
+ @ClassRule
+ public static DbTester dbTester = DbTester.createForSchema(System2.INSTANCE, ResultSetIteratorTest.class, "schema.sql");
+
+ Connection connection = null;
+
+ @Before
+ public void setUp() throws Exception {
+ connection = dbTester.openConnection();
+ }
+
+ @After
+ public void tearDown() {
+ DbUtils.closeQuietly(connection);
+ }
+
+ @Test
+ public void create_iterator_from_statement() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ assertThat(iterator.hasNext()).isTrue();
+
+ // calling multiple times hasNext() is ok
+ assertThat(iterator.hasNext()).isTrue();
+
+ assertThat(iterator.next()).isEqualTo(10);
+ assertThat(iterator.hasNext()).isTrue();
+ assertThat(iterator.next()).isEqualTo(20);
+
+ // call next() without calling hasNext()
+ assertThat(iterator.next()).isEqualTo(30);
+ assertThat(iterator.hasNext()).isFalse();
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException e) {
+ // ok
+ }
+
+ iterator.close();
+ // statement is closed by ResultSetIterator
+ assertThat(stmt.isClosed()).isTrue();
+ }
+
+ @Test
+ public void iterate_empty_list() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues where id < 0");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ assertThat(iterator.hasNext()).isFalse();
+ }
+
+ @Test
+ public void create_iterator_from_result_set() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ ResultSet rs = stmt.executeQuery();
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(rs);
+
+ assertThat(iterator.next()).isEqualTo(10);
+ assertThat(iterator.next()).isEqualTo(20);
+ assertThat(iterator.next()).isEqualTo(30);
+
+ iterator.close();
+ assertThat(rs.isClosed()).isTrue();
+ stmt.close();
+ }
+
+ @Test
+ public void remove_row_is_not_supported() throws Exception {
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ try {
+ iterator.remove();
+ fail();
+ } catch (UnsupportedOperationException ok) {
+ // ok
+ }
+
+ iterator.close();
+ }
+
+ @Test
+ public void fail_to_read_row() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FailIterator iterator = new FailIterator(stmt);
+
+ assertThat(iterator.hasNext()).isTrue();
+ try {
+ iterator.next();
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e.getCause()).isInstanceOf(SQLException.class);
+ }
+ iterator.close();
+ }
+
+ private static class FirstIntColumnIterator extends ResultSetIterator<Integer> {
+
+ public FirstIntColumnIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ public FirstIntColumnIterator(ResultSet rs) {
+ super(rs);
+ }
+
+ @Override
+ protected Integer read(ResultSet rs) throws SQLException {
+ return rs.getInt(1);
+ }
+ }
+
+ private static class FailIterator extends ResultSetIterator<Integer> {
+
+ public FailIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ @Override
+ protected Integer read(ResultSet rs) throws SQLException {
+ // column does not exist
+ return rs.getInt(1234);
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/TestDb.java b/sonar-db/src/test/java/org/sonar/db/TestDb.java
new file mode 100644
index 00000000000..715ea17af6d
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/TestDb.java
@@ -0,0 +1,175 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db;
+
+import com.google.common.collect.Maps;
+import java.io.File;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.Nullable;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+import org.junit.AssumptionViolatedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.deprecated.NullQueue;
+
+/**
+ * This class should be call using @ClassRule in order to create the schema once (ft @Rule is used
+ * the schema will be recreated before each test).
+ * Data will be truncated each time you call prepareDbUnit().
+ * <p/>
+ * File using {@link TestDb} must be annotated with {@link org.sonar.test.DbTests} so
+ * that they can be executed on all supported DBs (Oracle, MySQL, ...).
+ */
+class TestDb {
+
+ private static TestDb DEFAULT;
+
+ private static final Logger LOG = Loggers.get(TestDb.class);
+
+ private Database db;
+ private DatabaseCommands commands;
+ private IDatabaseTester tester;
+ private MyBatis myBatis;
+
+ private TestDb(@Nullable String schemaPath) {
+ if (db == null) {
+ Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties()));
+ if (settings.hasKey("orchestrator.configUrl")) {
+ loadOrchestratorSettings(settings);
+ }
+ String login = settings.getString("sonar.jdbc.username");
+ for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
+ LOG.info(key + ": " + settings.getString(key));
+ }
+ String dialect = settings.getString("sonar.jdbc.dialect");
+ if (dialect != null && !"h2".equals(dialect)) {
+ db = new DefaultDatabase(settings);
+ } else {
+ db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
+ }
+ db.start();
+ if (schemaPath != null) {
+ // will fail if not H2
+ if (db.getDialect().getId().equals("h2")) {
+ ((H2Database) db).executeScript(schemaPath);
+ } else {
+ db.stop();
+ throw new AssumptionViolatedException("Test disabled because it supports only H2");
+ }
+ }
+ LOG.info("Test Database: " + db);
+
+ commands = DatabaseCommands.forDialect(db.getDialect());
+ tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
+
+ myBatis = new MyBatis(db, new NullQueue());
+ myBatis.start();
+ }
+ }
+
+ void truncateTables() {
+ try {
+ commands.truncateDatabase(db.getDataSource());
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to truncate db tables", e);
+ }
+ }
+
+ static TestDb create(@Nullable String schemaPath) {
+ if (schemaPath == null) {
+ if (DEFAULT == null) {
+ DEFAULT = new TestDb(null);
+ }
+ return DEFAULT;
+ }
+ return new TestDb(schemaPath);
+ }
+
+ void stop() {
+ db.stop();
+ db = null;
+ myBatis = null;
+ }
+
+ Database getDatabase() {
+ return db;
+ }
+
+ DatabaseCommands getCommands() {
+ return commands;
+ }
+
+ MyBatis getMyBatis() {
+ return myBatis;
+ }
+
+ IDatabaseTester getDbUnitTester() {
+ return tester;
+ }
+
+ IDataTypeFactory getDbUnitFactory() {
+ return commands.getDbUnitFactory();
+ }
+
+ private void loadOrchestratorSettings(Settings settings) {
+ String url = settings.getString("orchestrator.configUrl");
+ InputStream input = null;
+ try {
+ URI uri = new URI(url);
+ if (url.startsWith("file:")) {
+ File file = new File(uri);
+ input = FileUtils.openInputStream(file);
+ } else {
+ HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
+ int responseCode = connection.getResponseCode();
+ if (responseCode >= 400) {
+ throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode);
+ }
+
+ input = connection.getInputStream();
+
+ }
+ Properties props = new Properties();
+ props.load(input);
+ settings.addProperties(props);
+ for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) {
+ String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}");
+ settings.setProperty(entry.getKey(), interpolatedValue);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java b/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java
new file mode 100644
index 00000000000..c2135f6e3ac
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java
@@ -0,0 +1,59 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.activity;
+
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Category(DbTests.class)
+public class ActivityDaoTest {
+
+ System2 system = mock(System2.class);
+
+ @Rule
+ public DbTester dbTester = DbTester.create(system);
+
+ ActivityDao sut = dbTester.getDbClient().activityDao();
+
+ @Test
+ public void insert() {
+ when(system.now()).thenReturn(1_500_000_000_000L);
+ ActivityDto dto = new ActivityDto()
+ .setKey("UUID_1").setAction("THE_ACTION").setType("THE_TYPE")
+ .setAuthor("THE_AUTHOR").setData("THE_DATA");
+ sut.insert(dto);
+
+ Map<String, Object> map = dbTester.selectFirst("select created_at as \"createdAt\", log_action as \"action\", data_field as \"data\" from activities where log_key='UUID_1'");
+ assertThat(map.get("action")).isEqualTo("THE_ACTION");
+ // not possible to check exact date yet. dbTester#selectFirst() uses ResultSet#getObject(), which returns
+ // non-JDBC interface in Oracle driver.
+ assertThat(map.get("createdAt")).isNotNull();
+ assertThat(map.get("data")).isEqualTo("THE_DATA");
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
new file mode 100644
index 00000000000..931d4f0c508
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
@@ -0,0 +1,100 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.component;
+
+import java.util.List;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class ComponentLinkDaoTest {
+
+ @ClassRule
+ public static DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ ComponentLinkDao dao = dbTester.getDbClient().componentLinkDao();
+
+ @Test
+ public void select_by_component_uuid() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<ComponentLinkDto> links = dao.selectByComponentUuid(dbTester.getSession(), "ABCD");
+ assertThat(links).hasSize(2);
+
+ links = dao.selectByComponentUuid(dbTester.getSession(), "BCDE");
+ assertThat(links).hasSize(1);
+
+ ComponentLinkDto link = links.get(0);
+ assertThat(link.getId()).isEqualTo(3L);
+ assertThat(link.getComponentUuid()).isEqualTo("BCDE");
+ assertThat(link.getType()).isEqualTo("homepage");
+ assertThat(link.getName()).isEqualTo("Home");
+ assertThat(link.getHref()).isEqualTo("http://www.struts.org");
+ }
+
+ @Test
+ public void insert() {
+ dbTester.prepareDbUnit(getClass(), "empty.xml");
+
+ dao.insert(dbTester.getSession(), new ComponentLinkDto()
+ .setComponentUuid("ABCD")
+ .setType("homepage")
+ .setName("Home")
+ .setHref("http://www.sonarqube.org")
+ );
+ dbTester.getSession().commit();
+
+ dbTester.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "project_links");
+ }
+
+ @Test
+ public void update() {
+ dbTester.prepareDbUnit(getClass(), "update.xml");
+
+ dao.update(dbTester.getSession(), new ComponentLinkDto()
+ .setId(1L)
+ .setComponentUuid("ABCD")
+ .setType("homepage")
+ .setName("Home")
+ .setHref("http://www.sonarqube.org")
+ );
+ dbTester.getSession().commit();
+
+ dbTester.assertDbUnit(getClass(), "update-result.xml", "project_links");
+ }
+
+ @Test
+ public void delete() {
+ dbTester.prepareDbUnit(getClass(), "delete.xml");
+
+ dao.delete(dbTester.getSession(), 1L);
+ dbTester.getSession().commit();
+
+ assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
index 90329d5842b..deb992be365 100644
--- a/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
@@ -22,14 +22,15 @@ package org.sonar.db.component;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
-import org.hamcrest.core.Is;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.System2;
import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.db.DbSession;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
@@ -37,7 +38,7 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
@Before
public void createDao() {
- dao = new ResourceIndexerDao(getMyBatis());
+ dao = new ResourceIndexerDao(getMyBatis(), mock(System2.class));
}
@Test
@@ -88,17 +89,17 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
// project
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=1");
rs.next();
- assertThat(rs.getInt(1), greaterThan(0));
+ assertThat(rs.getInt(1)).isGreaterThan(0);
// directory
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=2");
rs.next();
- assertThat(rs.getInt(1), Is.is(0));
+ assertThat(rs.getInt(1)).isEqualTo(0);
// file
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=3");
rs.next();
- assertThat(rs.getInt(1), greaterThan(0));
+ assertThat(rs.getInt(1)).isGreaterThan(0);
} finally {
if (null != rs) {
rs.close();
@@ -150,4 +151,16 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
checkTables("shouldNotReindexUnchangedResource", new String[] {"id"}, "resource_index");
}
+
+ @Test
+ public void select_project_ids_from_query_and_view_or_sub_view_uuid() {
+ setupData("select_project_ids_from_query_and_view_or_sub_view_uuid");
+ String viewUuid = "EFGH";
+
+ DbSession session = getMyBatis().openSession(false);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "project", viewUuid)).containsOnly(1L, 2L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "one", viewUuid)).containsOnly(1L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "two", viewUuid)).containsOnly(2L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "unknown", viewUuid)).isEmpty();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
new file mode 100644
index 00000000000..21ec3e349a9
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
@@ -0,0 +1,305 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.component;
+
+import java.util.Date;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
+
+@Category(DbTests.class)
+public class SnapshotDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ DbSession session;
+
+ SnapshotDao sut;
+
+ @Before
+ public void createDao() {
+ session = db.myBatis().openSession(false);
+ sut = new SnapshotDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void get_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ SnapshotDto result = sut.selectNullableById(session, 3L);
+ assertThat(result).isNotNull();
+ assertThat(result.getId()).isEqualTo(3L);
+ assertThat(result.getComponentId()).isEqualTo(3L);
+ assertThat(result.getRootProjectId()).isEqualTo(1L);
+ assertThat(result.getParentId()).isEqualTo(2L);
+ assertThat(result.getRootId()).isEqualTo(1L);
+ assertThat(result.getStatus()).isEqualTo("P");
+ assertThat(result.getLast()).isTrue();
+ assertThat(result.getPurgeStatus()).isEqualTo(1);
+ assertThat(result.getDepth()).isEqualTo(1);
+ assertThat(result.getScope()).isEqualTo("DIR");
+ assertThat(result.getQualifier()).isEqualTo("PAC");
+ assertThat(result.getVersion()).isEqualTo("2.1-SNAPSHOT");
+ assertThat(result.getPath()).isEqualTo("1.2.");
+
+ assertThat(result.getPeriodMode(1)).isEqualTo("days1");
+ assertThat(result.getPeriodModeParameter(1)).isEqualTo("30");
+ assertThat(result.getPeriodDate(1)).isEqualTo(1316815200000L);
+ assertThat(result.getPeriodMode(2)).isEqualTo("days2");
+ assertThat(result.getPeriodModeParameter(2)).isEqualTo("31");
+ assertThat(result.getPeriodDate(2)).isEqualTo(1316901600000L);
+ assertThat(result.getPeriodMode(3)).isEqualTo("days3");
+ assertThat(result.getPeriodModeParameter(3)).isEqualTo("32");
+ assertThat(result.getPeriodDate(3)).isEqualTo(1316988000000L);
+ assertThat(result.getPeriodMode(4)).isEqualTo("days4");
+ assertThat(result.getPeriodModeParameter(4)).isEqualTo("33");
+ assertThat(result.getPeriodDate(4)).isEqualTo(1317074400000L);
+ assertThat(result.getPeriodMode(5)).isEqualTo("days5");
+ assertThat(result.getPeriodModeParameter(5)).isEqualTo("34");
+ assertThat(result.getPeriodDate(5)).isEqualTo(1317160800000L);
+
+ assertThat(result.getCreatedAt()).isEqualTo(1228172400000L);
+ assertThat(result.getBuildDate()).isEqualTo(1317247200000L);
+
+ assertThat(sut.selectNullableById(session, 999L)).isNull();
+ }
+
+ @Test
+ public void lastSnapshot_returns_null_when_no_last_snapshot() {
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 123L);
+
+ assertThat(snapshot).isNull();
+ }
+
+ @Test
+ public void lastSnapshot_from_one_resource() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 2L);
+
+ assertThat(snapshot).isNotNull();
+ assertThat(snapshot.getId()).isEqualTo(4L);
+ }
+
+ @Test
+ public void lastSnapshot_from_one_resource_without_last_is_null() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 5L);
+
+ assertThat(snapshot).isNull();
+ }
+
+ @Test
+ public void snapshot_and_child_retrieved() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+
+ assertThat(snapshots).isNotEmpty();
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ }
+
+ @Test
+ public void select_snapshots_by_component_id() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotsByComponentId(session, 1L);
+
+ assertThat(snapshots).hasSize(3);
+ }
+
+ @Test
+ public void select_snapshots_by_query() {
+ db.prepareDbUnit(getClass(), "select_snapshots_by_query.xml");
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery())).hasSize(6);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L))).hasSize(3);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setVersion("2.2-SNAPSHOT"))).extracting("id").containsOnly(3L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setIsLast(true))).extracting("id").containsOnly(1L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setIsLast(false))).extracting("id").containsOnly(2L, 3L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setCreatedAfter(1228172400002L))).extracting("id").containsOnly(2L, 3L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setCreatedBefore(1228172400002L))).extracting("id").containsOnly(1L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(2L).setStatus("P"))).hasSize(1);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(2L).setStatus("U"))).hasSize(1);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setSort(BY_DATE, ASC)).get(0).getId()).isEqualTo(1L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setSort(BY_DATE, DESC)).get(0).getId()).isEqualTo(3L);
+ }
+
+ @Test
+ public void select_previous_version_snapshots() throws Exception {
+ db.prepareDbUnit(getClass(), "select_previous_version_snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectPreviousVersionSnapshots(session, 1L, "1.2-SNAPSHOT");
+ assertThat(snapshots).hasSize(2);
+
+ SnapshotDto firstSnapshot = snapshots.get(0);
+ assertThat(firstSnapshot.getVersion()).isEqualTo("1.1");
+
+ // All snapshots are returned on an unknown version
+ assertThat(sut.selectPreviousVersionSnapshots(session, 1L, "UNKNOWN")).hasSize(3);
+ }
+
+ @Test
+ public void insert() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ SnapshotDto dto = defaultSnapshot().setCreatedAt(1403042400000L);
+
+ sut.insert(session, dto);
+ session.commit();
+
+ assertThat(dto.getId()).isNotNull();
+ db.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "snapshots");
+ }
+
+ @Test
+ public void insert_snapshots() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session,
+ new SnapshotDto().setComponentId(1L).setLast(false),
+ new SnapshotDto().setComponentId(2L).setLast(false));
+ session.commit();
+
+ assertThat(db.countRowsOfTable("snapshots")).isEqualTo(2);
+ }
+
+ @Test
+ public void set_snapshot_and_children_to_false_and_status_processed() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+ SnapshotDto snapshot = defaultSnapshot().setId(1L);
+
+ sut.updateSnapshotAndChildrenLastFlagAndStatus(session, snapshot, false, SnapshotDto.STATUS_PROCESSED);
+ session.commit();
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+ assertThat(snapshots).hasSize(2);
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ assertThat(snapshots).extracting("last").containsOnly(false);
+ assertThat(snapshots).extracting("status").containsOnly(SnapshotDto.STATUS_PROCESSED);
+ }
+
+ @Test
+ public void set_snapshot_and_children_isLast_flag_to_false() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+ SnapshotDto snapshot = defaultSnapshot().setId(1L);
+
+ sut.updateSnapshotAndChildrenLastFlag(session, snapshot, false);
+ session.commit();
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+ assertThat(snapshots).hasSize(2);
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ assertThat(snapshots).extracting("last").containsOnly(false);
+ }
+
+ @Test
+ public void is_last_snapshot_when_no_previous_snapshot() {
+ SnapshotDto snapshot = defaultSnapshot();
+
+ boolean isLast = SnapshotDao.isLast(snapshot, null);
+
+ assertThat(isLast).isTrue();
+ }
+
+ @Test
+ public void is_last_snapshot_when_previous_snapshot_is_older() {
+ Date today = new Date();
+ Date yesterday = DateUtils.addDays(today, -1);
+
+ SnapshotDto snapshot = defaultSnapshot().setCreatedAt(today.getTime());
+ SnapshotDto previousLastSnapshot = defaultSnapshot().setCreatedAt(yesterday.getTime());
+
+ boolean isLast = SnapshotDao.isLast(snapshot, previousLastSnapshot);
+
+ assertThat(isLast).isTrue();
+ }
+
+ @Test
+ public void is_not_last_snapshot_when_previous_snapshot_is_newer() {
+ Date today = new Date();
+ Date yesterday = DateUtils.addDays(today, -1);
+
+ SnapshotDto snapshot = defaultSnapshot().setCreatedAt(yesterday.getTime());
+ SnapshotDto previousLastSnapshot = defaultSnapshot().setCreatedAt(today.getTime());
+
+ boolean isLast = SnapshotDao.isLast(snapshot, previousLastSnapshot);
+
+ assertThat(isLast).isFalse();
+ }
+
+ private static SnapshotDto defaultSnapshot() {
+ return new SnapshotDto()
+ .setComponentId(3L)
+ .setRootProjectId(1L)
+ .setParentId(2L)
+ .setRootId(1L)
+ .setStatus("P")
+ .setLast(true)
+ .setPurgeStatus(1)
+ .setDepth(1)
+ .setScope("DIR")
+ .setQualifier("PAC")
+ .setVersion("2.1-SNAPSHOT")
+ .setPath("1.2.")
+ .setPeriodMode(1, "days1")
+ .setPeriodMode(2, "days2")
+ .setPeriodMode(3, "days3")
+ .setPeriodMode(4, "days4")
+ .setPeriodMode(5, "days5")
+ .setPeriodParam(1, "30")
+ .setPeriodParam(2, "31")
+ .setPeriodParam(3, "32")
+ .setPeriodParam(4, "33")
+ .setPeriodParam(5, "34")
+ .setPeriodDate(1, 1_500_000_000_001L)
+ .setPeriodDate(2, 1_500_000_000_002L)
+ .setPeriodDate(3, 1_500_000_000_003L)
+ .setPeriodDate(4, 1_500_000_000_004L)
+ .setPeriodDate(5, 1_500_000_000_005L)
+ .setBuildDate(1_500_000_000_006L);
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java b/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java
new file mode 100644
index 00000000000..17bb66813b7
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java
@@ -0,0 +1,212 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.compute;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.utils.System2;
+import org.sonar.db.compute.AnalysisReportDao;
+import org.sonar.db.compute.AnalysisReportDto;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.MyBatis;
+import org.sonar.test.DbTests;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
+import static org.sonar.db.compute.AnalysisReportDto.Status.WORKING;
+
+@Category(DbTests.class)
+public class AnalysisReportDaoTest {
+
+ private static final String DEFAULT_PROJECT_KEY = "123456789-987654321";
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ AnalysisReportDao sut;
+ DbSession session;
+ System2 system2;
+
+ @Before
+ public void before() {
+ this.session = db.myBatis().openSession(false);
+ this.system2 = mock(System2.class);
+ this.sut = new AnalysisReportDao(system2);
+
+ when(system2.now()).thenReturn(1_500_000_000_000L);
+ }
+
+ @After
+ public void after() {
+ MyBatis.closeQuietly(session);
+ }
+
+ @Test
+ public void insert_multiple_reports() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ AnalysisReportDto report1 = new AnalysisReportDto().setProjectKey("ProjectKey1").setProjectName("Project 1").setUuid("UUID_1").setStatus(PENDING);
+ AnalysisReportDto report2 = new AnalysisReportDto().setProjectKey("ProjectKey2").setProjectName("Project 2").setUuid("UUID_2").setStatus(PENDING);
+
+ sut.insert(session, report1);
+ sut.insert(session, report2);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void resetAllToPendingStatus() {
+ db.prepareDbUnit(getClass(), "update-all-to-status-pending.xml");
+
+ sut.resetAllToPendingStatus(session);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "update-all-to-status-pending-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void truncate() {
+ db.prepareDbUnit(getClass(), "any-analysis-reports.xml");
+
+ sut.truncate(session);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "truncate-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void find_one_report_by_project_key() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ final String projectKey = "123456789-987654321";
+ List<AnalysisReportDto> reports = sut.selectByProjectKey(session, projectKey);
+ AnalysisReportDto report = reports.get(0);
+
+ assertThat(reports).hasSize(1);
+ assertThat(report.getProjectKey()).isEqualTo(projectKey);
+ assertThat(report.getProjectName()).isEqualTo("Project 1");
+ assertThat(report.getStatus()).isEqualTo(AnalysisReportDto.Status.WORKING);
+ assertThat(report.getId()).isEqualTo(1);
+ }
+
+ @Test
+ public void find_several_reports_by_project_key() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ final String projectKey = "987654321-123456789";
+ List<AnalysisReportDto> reports = sut.selectByProjectKey(session, projectKey);
+
+ assertThat(reports).hasSize(2);
+ }
+
+ @Test
+ public void pop_oldest_pending() {
+ db.prepareDbUnit(getClass(), "pop_oldest_pending.xml");
+
+ AnalysisReportDto nextAvailableReport = sut.pop(session);
+
+ assertThat(nextAvailableReport.getId()).isEqualTo(3);
+ assertThat(nextAvailableReport.getProjectKey()).isEqualTo("P2");
+ }
+
+ @Test
+ public void pop_null_if_no_pending_reports() {
+ db.prepareDbUnit(getClass(), "pop_null_if_no_pending_reports.xml");
+
+ AnalysisReportDto nextAvailableReport = sut.pop(session);
+
+ assertThat(nextAvailableReport).isNull();
+ }
+
+ @Test
+ public void getById_maps_all_the_fields_except_the_data() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ AnalysisReportDto report = sut.selectById(session, 1L);
+
+ assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
+ assertThat(report.getCreatedAt()).isEqualTo(1_500_000_000_001L);
+ assertThat(report.getUpdatedAt()).isEqualTo(1_500_000_000_002L);
+ assertThat(report.getStartedAt()).isEqualTo(1_500_000_000_003L);
+ assertThat(report.getFinishedAt()).isEqualTo(1_500_000_000_004L);
+ assertThat(report.getStatus()).isEqualTo(WORKING);
+ }
+
+ @Test
+ public void getById_returns_null_when_id_not_found() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ AnalysisReportDto report = sut.selectById(session, 4L);
+
+ assertThat(report).isNull();
+ }
+
+ @Test
+ public void delete_one_analysis_report() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ sut.delete(session, 1);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "truncate-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void findAll_one_analysis_report() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).hasSize(1);
+ }
+
+ @Test
+ public void findAll_empty_table() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).isEmpty();
+ }
+
+ @Test
+ public void findAll_three_analysis_reports() {
+ db.prepareDbUnit(getClass(), "three_analysis_reports.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).hasSize(3);
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java
index 7c3eeaa1d08..aa5afd5af14 100644
--- a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java
@@ -17,55 +17,53 @@
* 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.db.dashboard;
-package org.sonar.db.qualityprofile;
-
-import java.util.List;
+import java.util.Collection;
+import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.db.AbstractDaoTestCase;
+import org.junit.experimental.categories.Category;
import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.MyBatis;
+import org.sonar.test.DbTests;
import static org.assertj.core.api.Assertions.assertThat;
-public class ActiveRuleDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class WidgetDaoTest {
- ActiveRuleDao dao;
+ WidgetDao dao;
- @Before
- public void before() {
- dao = new ActiveRuleDao(getMyBatis());
- }
+ @Rule
+ public DbTester dbTester = new DbTester();
- @Test
- public void select_by_profile() {
- setupData("shared");
+ private DbSession session;
- List<ActiveRuleDto> result = dao.selectByProfileKey("parent");
- assertThat(result).hasSize(2);
+ @Before
+ public void setUp() {
+ dao = new WidgetDao(dbTester.myBatis());
+ session = dbTester.myBatis().openSession(false);
}
- @Test
- public void insert_parameter() {
- setupData("empty");
-
- DbSession session = getMyBatis().openSession(false);
- ActiveRuleParamDto dto = new ActiveRuleParamDto()
- .setActiveRuleId(1)
- .setRulesParameterId(1)
- .setKey("max")
- .setValue("20");
- dao.insert(dto, session);
- session.commit();
- session.close();
-
- checkTables("insert_parameter", "active_rule_parameters");
+ @After
+ public void tearDown() {
+ MyBatis.closeQuietly(session);
}
@Test
- public void select_params_by_profile_id() {
- setupData("shared");
+ public void should_select_all() {
+ dbTester.prepareDbUnit(this.getClass(), "before.xml");
+ session.commit();
- assertThat(dao.selectParamsByProfileKey("child")).hasSize(2);
+ Collection<WidgetDto> widgets = dao.findAll(session);
+ assertThat(widgets).hasSize(5);
+ for (WidgetDto widget : widgets) {
+ assertThat(widget.getId()).isNotNull();
+ assertThat(widget.getName()).isNotNull();
+ assertThat(widget.getDescription()).isNotNull();
+ }
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java b/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java
new file mode 100644
index 00000000000..4915c0e2291
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java
@@ -0,0 +1,116 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.event;
+
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class EventDaoTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ DbSession session;
+
+ EventDao dao;
+
+ @Before
+ public void setup() {
+ dbTester.truncateTables();
+ session = dbTester.myBatis().openSession(false);
+ dao = new EventDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void select_by_component_uuid() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<EventDto> dtos = dao.selectByComponentUuid(session, "ABCD");
+ assertThat(dtos).hasSize(3);
+
+ dtos = dao.selectByComponentUuid(session, "BCDE");
+ assertThat(dtos).hasSize(1);
+
+ EventDto dto = dtos.get(0);
+ assertThat(dto.getId()).isEqualTo(4L);
+ assertThat(dto.getComponentUuid()).isEqualTo("BCDE");
+ assertThat(dto.getSnapshotId()).isEqualTo(1000L);
+ assertThat(dto.getName()).isEqualTo("1.0");
+ assertThat(dto.getCategory()).isEqualTo("Version");
+ assertThat(dto.getDescription()).isEqualTo("Version 1.0");
+ assertThat(dto.getData()).isEqualTo("some data");
+ assertThat(dto.getDate()).isEqualTo(1413407091086L);
+ assertThat(dto.getCreatedAt()).isEqualTo(1225630680000L);
+ }
+
+ @Test
+ public void return_different_categories() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<EventDto> dtos = dao.selectByComponentUuid(session, "ABCD");
+ assertThat(dtos).extracting("category").containsOnly(EventDto.CATEGORY_ALERT, EventDto.CATEGORY_PROFILE, EventDto.CATEGORY_VERSION);
+ }
+
+ @Test
+ public void insert() {
+ dbTester.prepareDbUnit(getClass(), "empty.xml");
+
+ dao.insert(session, new EventDto()
+ .setName("1.0")
+ .setCategory(EventDto.CATEGORY_VERSION)
+ .setDescription("Version 1.0")
+ .setData("some data")
+ .setDate(1413407091086L)
+ .setComponentUuid("ABCD")
+ .setSnapshotId(1000L)
+ .setCreatedAt(1225630680000L)
+ );
+ session.commit();
+
+ dbTester.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "events");
+ }
+
+ @Test
+ public void delete() {
+ dbTester.prepareDbUnit(getClass(), "delete.xml");
+
+ dao.delete(session, 1L);
+ session.commit();
+
+ assertThat(dbTester.countRowsOfTable("events")).isEqualTo(0);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
index a70e1a3d08e..9a083137952 100644
--- a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
@@ -21,24 +21,23 @@
package org.sonar.db.issue;
import java.util.Collection;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
import static org.assertj.core.api.Assertions.assertThat;
-public class ActionPlanStatsDaoTest extends AbstractDaoTestCase {
+public class ActionPlanStatsDaoTest {
- ActionPlanStatsDao dao;
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
- @Before
- public void createDao() {
- dao = new ActionPlanStatsDao(getMyBatis());
- }
+ ActionPlanStatsDao dao = dbTester.getDbClient().getActionPlanStatsDao();
@Test
public void should_find_by_project() {
- setupData("shared", "should_find_by_project");
+ dbTester.prepareDbUnit(getClass(), "shared.xml", "should_find_by_project.xml");
Collection<ActionPlanStatsDto> result = dao.findByProjectId(1l);
assertThat(result).isNotEmpty();
diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
index 24f556df1e6..dc64f45d05d 100644
--- a/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
@@ -20,12 +20,17 @@
package org.sonar.db.issue;
+import java.util.Arrays;
+import java.util.List;
import org.apache.ibatis.executor.result.DefaultResultHandler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
import org.sonar.db.AbstractDaoTestCase;
import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.rule.RuleTesting;
import static org.assertj.core.api.Assertions.assertThat;
@@ -91,4 +96,116 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(issue.getComponentKey()).isNotNull();
assertThat(issue.getProjectKey()).isNull();
}
+
+ @Test
+ public void get_by_key() {
+ setupData("shared", "get_by_key");
+
+ IssueDto issue = dao.selectByKey(session, "ABCDE");
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getId()).isEqualTo(100L);
+ assertThat(issue.getComponentUuid()).isEqualTo("CDEF");
+ assertThat(issue.getProjectUuid()).isEqualTo("ABCD");
+ assertThat(issue.getRuleId()).isEqualTo(500);
+ assertThat(issue.getLanguage()).isEqualTo("java");
+ assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(issue.isManualSeverity()).isFalse();
+ assertThat(issue.getMessage()).isNull();
+ assertThat(issue.getLine()).isEqualTo(200);
+ assertThat(issue.getEffortToFix()).isEqualTo(4.2);
+ assertThat(issue.getStatus()).isEqualTo("OPEN");
+ assertThat(issue.getResolution()).isEqualTo("FIXED");
+ assertThat(issue.getChecksum()).isEqualTo("XXX");
+ assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
+ assertThat(issue.getReporter()).isEqualTo("arthur");
+ assertThat(issue.getAssignee()).isEqualTo("perceval");
+ assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
+ assertThat(issue.getIssueCreationDate()).isNotNull();
+ assertThat(issue.getIssueUpdateDate()).isNotNull();
+ assertThat(issue.getIssueCloseDate()).isNotNull();
+ assertThat(issue.getCreatedAt()).isEqualTo(1400000000000L);
+ assertThat(issue.getUpdatedAt()).isEqualTo(1450000000000L);
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getProjectKey()).isEqualTo("struts");
+ }
+
+ @Test
+ public void get_by_keys() {
+ setupData("shared", "get_by_key");
+
+ List<IssueDto> issues = dao.selectByKeys(session, Arrays.asList("ABCDE"));
+ assertThat(issues).hasSize(1);
+ }
+
+ @Test
+ public void find_by_action_plan() {
+ setupData("shared", "find_by_action_plan");
+
+ List<IssueDto> issues = dao.findByActionPlan(session, "AP-1");
+ assertThat(issues).hasSize(1);
+
+ IssueDto issue = issues.get(0);
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getActionPlanKey()).isEqualTo("AP-1");
+ assertThat(issue.getComponentUuid()).isEqualTo("CDEF");
+ assertThat(issue.getProjectUuid()).isEqualTo("ABCD");
+ assertThat(issue.getRuleId()).isEqualTo(500);
+ assertThat(issue.getLanguage()).isEqualTo("java");
+ assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(issue.isManualSeverity()).isFalse();
+ assertThat(issue.getMessage()).isNull();
+ assertThat(issue.getLine()).isEqualTo(200);
+ assertThat(issue.getEffortToFix()).isEqualTo(4.2);
+ assertThat(issue.getStatus()).isEqualTo("OPEN");
+ assertThat(issue.getResolution()).isEqualTo("FIXED");
+ assertThat(issue.getChecksum()).isEqualTo("XXX");
+ assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
+ assertThat(issue.getReporter()).isEqualTo("arthur");
+ assertThat(issue.getAssignee()).isEqualTo("perceval");
+ assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
+ assertThat(issue.getIssueCreationDate()).isNotNull();
+ assertThat(issue.getIssueUpdateDate()).isNotNull();
+ assertThat(issue.getIssueCloseDate()).isNotNull();
+ assertThat(issue.getCreatedAt()).isNotNull();
+ assertThat(issue.getUpdatedAt()).isNotNull();
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getProjectKey()).isEqualTo("struts");
+ }
+
+ @Test
+ public void insert() {
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L).setUuid("component-uuid"));
+ dto.setProject(new ComponentDto().setKey("struts").setId(100L).setUuid("project-uuid"));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationTime(1_500_000_000_000L);
+ dto.setIssueUpdateTime(1_500_000_000_001L);
+ dto.setIssueCloseTime(1_500_000_000_002L);
+ dto.setCreatedAt(1_400_000_000_000L);
+ dto.setUpdatedAt(1_450_000_000_000L);
+
+ dao.insert(session, dto);
+ session.commit();
+
+ checkTables("insert", new String[] {"id"}, "issues");
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
new file mode 100644
index 00000000000..9621d6aa945
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
@@ -0,0 +1,333 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.measure;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.measure.MeasureDao;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.PastMeasureDto;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class MeasureDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ DbSession session;
+ MeasureDao sut;
+
+ @Before
+ public void setUp() {
+ db.truncateTables();
+ session = db.myBatis().openSession(false);
+ sut = new MeasureDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void get_value_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc");
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getData()).isNull();
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+ assertThat(result.getAlertStatus()).isEqualTo("OK");
+ assertThat(result.getAlertText()).isEqualTo("Green");
+ }
+
+ @Test
+ // TODO the string must be longer than 4000 char to be persisted in the data field
+ public void get_data_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "authors_by_line");
+ assertThat(result.getId()).isEqualTo(20);
+ assertThat(result.getData()).isEqualTo("0123456789012345678901234567890123456789");
+ }
+
+ @Test
+ public void get_text_value_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "coverage_line_hits_data");
+ assertThat(result.getId()).isEqualTo(21);
+ assertThat(result.getData()).isEqualTo("36=1;37=1;38=1;39=1;43=1;48=1;53=1");
+ }
+
+ @Test
+ public void find_by_component_key_and_metrics() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ List<MeasureDto> results = sut.findByComponentKeyAndMetricKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java",
+ newArrayList("ncloc", "authors_by_line"));
+ assertThat(results).hasSize(2);
+
+ results = sut.findByComponentKeyAndMetricKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java", newArrayList("ncloc"));
+ assertThat(results).hasSize(1);
+
+ MeasureDto result = results.get(0);
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getComponentKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.getMetricKey()).isEqualTo("ncloc");
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+ }
+
+ @Test
+ public void find_by_component_key_and_metric() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc");
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getMetricKey()).isEqualTo("ncloc");
+ assertThat(result.getComponentKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+
+ assertThat(sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "unknown")).isNull();
+ }
+
+ @Test
+ public void exists_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ assertThat(sut.existsByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc")).isTrue();
+ assertThat(sut.existsByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "unknown")).isFalse();
+ }
+
+ @Test
+ public void select_past_measures_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures.xml");
+
+ List<PastMeasureDto> fileMeasures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 1000L, ImmutableSet.of(1, 2));
+ assertThat(fileMeasures).hasSize(2);
+
+ PastMeasureDto fileMeasure1 = fileMeasures.get(0);
+ assertThat(fileMeasure1.getValue()).isEqualTo(5d);
+ assertThat(fileMeasure1.getMetricId()).isEqualTo(1);
+ assertThat(fileMeasure1.getRuleId()).isNull();
+ assertThat(fileMeasure1.getCharacteristicId()).isNull();
+ assertThat(fileMeasure1.getPersonId()).isNull();
+
+ PastMeasureDto fileMeasure2 = fileMeasures.get(1);
+ assertThat(fileMeasure2.getValue()).isEqualTo(60d);
+ assertThat(fileMeasure2.getMetricId()).isEqualTo(2);
+
+ List<PastMeasureDto> projectMeasures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1, 2));
+ assertThat(projectMeasures).hasSize(2);
+
+ PastMeasureDto projectMeasure1 = projectMeasures.get(0);
+ assertThat(projectMeasure1.getValue()).isEqualTo(60d);
+ assertThat(projectMeasure1.getMetricId()).isEqualTo(1);
+
+ PastMeasureDto projectMeasure2 = projectMeasures.get(1);
+ assertThat(projectMeasure2.getValue()).isEqualTo(80d);
+ assertThat(projectMeasure2.getMetricId()).isEqualTo(2);
+
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "UNKNOWN", 1000L, ImmutableSet.of(1, 2))).isEmpty();
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 987654L, ImmutableSet.of(1, 2))).isEmpty();
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 1000L, ImmutableSet.of(123, 456))).isEmpty();
+ }
+
+ @Test
+ public void select_past_measures_on_rule_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_rule_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isEqualTo(30);
+ assertThat(measure2.getCharacteristicId()).isNull();
+ assertThat(measure2.getPersonId()).isNull();
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isEqualTo(31);
+ assertThat(measure3.getCharacteristicId()).isNull();
+ assertThat(measure3.getPersonId()).isNull();
+ }
+
+ @Test
+ public void select_past_measures_on_characteristic_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_characteristic_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isNull();
+ assertThat(measure2.getCharacteristicId()).isEqualTo(10);
+ assertThat(measure2.getPersonId()).isNull();
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isNull();
+ assertThat(measure3.getCharacteristicId()).isEqualTo(11);
+ assertThat(measure3.getPersonId()).isNull();
+ }
+
+ @Test
+ public void select_past_measures_on_person_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_person_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isNull();
+ assertThat(measure2.getCharacteristicId()).isNull();
+ assertThat(measure2.getPersonId()).isEqualTo(20);
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isNull();
+ assertThat(measure3.getCharacteristicId()).isNull();
+ assertThat(measure3.getPersonId()).isEqualTo(21);
+ }
+
+ @Test
+ public void insert() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session, new MeasureDto()
+ .setSnapshotId(2L)
+ .setMetricId(3)
+ .setCharacteristicId(4)
+ .setPersonId(23)
+ .setRuleId(5)
+ .setComponentId(6L)
+ .setValue(2.0d)
+ .setData("measure-value")
+ .setVariation(1, 1.0d)
+ .setVariation(2, 2.0d)
+ .setVariation(3, 3.0d)
+ .setVariation(4, 4.0d)
+ .setVariation(5, 5.0d)
+ .setAlertStatus("alert")
+ .setAlertText("alert-text")
+ .setDescription("measure-description")
+ );
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "project_measures");
+ }
+
+ @Test
+ public void insert_measures() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session, new MeasureDto()
+ .setSnapshotId(2L)
+ .setMetricId(3)
+ .setComponentId(6L)
+ .setValue(2.0d),
+ new MeasureDto()
+ .setSnapshotId(3L)
+ .setMetricId(4)
+ .setComponentId(6L)
+ .setValue(4.0d)
+ );
+ session.commit();
+
+ assertThat(db.countRowsOfTable("project_measures")).isEqualTo(2);
+ }
+
+ private static Map<Long, PastMeasureDto> pastMeasuresById(List<PastMeasureDto> pastMeasures) {
+ return FluentIterable.from(pastMeasures).uniqueIndex(new Function<PastMeasureDto, Long>() {
+ @Nullable
+ @Override
+ public Long apply(PastMeasureDto input) {
+ return input.getId();
+ }
+ });
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
index 592e42b406e..11aa33abc18 100644
--- a/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
@@ -55,7 +55,7 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
when(system2.now()).thenReturn(1450000000000L);
dbSession = getMyBatis().openSession(false);
- sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2);
+ sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), system2);
}
@After
@@ -66,14 +66,14 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void shouldDeleteAbortedBuilds() {
setupData("shouldDeleteAbortedBuilds");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldDeleteAbortedBuilds", "snapshots");
}
@Test
public void should_purge_project() {
setupData("shouldPurgeProject");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldPurgeProject", "projects", "snapshots");
}
@@ -88,28 +88,28 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void delete_file_sources_of_disabled_resources() {
setupData("delete_file_sources_of_disabled_resources");
- sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("delete_file_sources_of_disabled_resources", "file_sources");
}
@Test
public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() {
setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles");
- sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY);
+ sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldDeleteHistoricalDataOfDirectoriesAndFiles", "projects", "snapshots");
}
@Test
public void disable_resources_without_last_snapshot() {
setupData("disable_resources_without_last_snapshot");
- sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("disable_resources_without_last_snapshot", new String[] {"issue_close_date", "issue_update_date"}, "projects", "snapshots", "issues");
}
@Test
public void shouldDeleteSnapshots() {
setupData("shouldDeleteSnapshots");
- sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L));
+ sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L), new PurgeProfiler());
checkTables("shouldDeleteSnapshots", "snapshots");
}
@@ -130,21 +130,21 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void should_delete_project_and_associated_data() {
setupData("shouldDeleteProject");
- sut.deleteResourceTree(new IdUuidPair(1L, "A"));
+ sut.deleteResourceTree(new IdUuidPair(1L, "A"), new PurgeProfiler());
assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources");
}
@Test
public void should_delete_old_closed_issues() {
setupData("should_delete_old_closed_issues");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("should_delete_old_closed_issues", "issues", "issue_changes");
}
@Test
public void should_delete_all_closed_issues() {
setupData("should_delete_all_closed_issues");
- sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0), PurgeListener.EMPTY);
+ sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("should_delete_all_closed_issues", "issues", "issue_changes");
}
diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
index 1aa9d8aebcb..857b58ed48a 100644
--- a/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
@@ -30,9 +30,11 @@ import org.mockito.stubbing.Answer;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.purge.PurgeDao;
+import org.sonar.db.purge.PurgeProfiler;
import org.sonar.db.purge.PurgeSnapshotQuery;
import org.sonar.db.purge.PurgeableSnapshotDto;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.anyListOf;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.eq;
@@ -52,13 +54,13 @@ public class DefaultPeriodCleanerTest {
Filter filter1 = newLazyFilter();
Filter filter2 = newLazyFilter();
- DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao);
+ DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, new PurgeProfiler());
cleaner.doClean(123L, Arrays.asList(filter1, filter2), session);
verify(filter1).log();
verify(filter2).log();
- verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()), eq(session));
- verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()), eq(session));
+ verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()), eq(session), any(PurgeProfiler.class));
+ verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()), eq(session), any(PurgeProfiler.class));
}
private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() {
diff --git a/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java b/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java
new file mode 100644
index 00000000000..1b744886d6f
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java
@@ -0,0 +1,105 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.rule;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.db.rule.RuleDto.Format;
+
+/**
+ * Utility class for tests involving rules
+ */
+public class RuleTesting {
+
+ public static final RuleKey XOO_X1 = RuleKey.of("xoo", "x1");
+ public static final RuleKey XOO_X2 = RuleKey.of("xoo", "x2");
+ public static final RuleKey XOO_X3 = RuleKey.of("xoo", "x3");
+
+ private RuleTesting() {
+ // only static helpers
+ }
+
+ public static RuleDto newXooX1() {
+ return newDto(XOO_X1).setLanguage("xoo");
+ }
+
+ public static RuleDto newXooX2() {
+ return newDto(XOO_X2).setLanguage("xoo");
+ }
+
+ public static RuleDto newXooX3() {
+ return newDto(XOO_X3).setLanguage("xoo");
+ }
+
+ /**
+ * Full RuleDto used to feed database with fake data. Tests must not rely on the
+ * field contents declared here. They should override the fields they need to test,
+ * for example:
+ * <pre>
+ * ruleDao.insert(dbSession, RuleTesting.newDto(key).setStatus(RuleStatus.BETA));
+ * </pre>
+ */
+ public static RuleDto newDto(RuleKey ruleKey) {
+ return new RuleDto()
+ .setRuleKey(ruleKey.rule())
+ .setRepositoryKey(ruleKey.repository())
+ .setName("Rule " + ruleKey.rule())
+ .setDescription("Description " + ruleKey.rule())
+ .setDescriptionFormat(Format.HTML)
+ .setStatus(RuleStatus.READY)
+ .setConfigKey("InternalKey" + ruleKey.rule())
+ .setSeverity(Severity.INFO)
+ .setIsTemplate(false)
+ .setTags(ImmutableSet.of("tag1", "tag2"))
+ .setSystemTags(ImmutableSet.of("systag1", "systag2"))
+ .setLanguage("js")
+ .setRemediationFunction("LINEAR")
+ .setDefaultRemediationFunction("LINEAR_OFFSET")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix");
+ }
+
+ public static RuleDto newTemplateRule(RuleKey ruleKey) {
+ return newDto(ruleKey)
+ .setIsTemplate(true);
+ }
+
+ public static RuleDto newCustomRule(RuleDto templateRule) {
+ Preconditions.checkNotNull(templateRule.getId(), "The template rule need to be persisted before creating this custom rule.");
+ return newDto(RuleKey.of(templateRule.getRepositoryKey(), templateRule.getRuleKey() + "_" + System.currentTimeMillis()))
+ .setLanguage(templateRule.getLanguage())
+ .setTemplateId(templateRule.getId());
+ }
+
+ public static RuleDto newManualRule(String manualKey) {
+ return new RuleDto().setRuleKey(manualKey)
+ .setName("Name " + manualKey)
+ .setRepositoryKey(RuleKey.MANUAL_REPOSITORY_KEY)
+ .setDescription("Description " + manualKey)
+ .setStatus(RuleStatus.READY);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java
new file mode 100644
index 00000000000..09d7fbcff1b
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java
@@ -0,0 +1,175 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.source;
+
+import com.google.common.base.Function;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.db.DbSession;
+import org.sonar.db.source.FileSourceDto.Type;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FileSourceDaoTest extends AbstractDaoTestCase {
+
+ DbSession session;
+
+ FileSourceDao sut;
+
+ @Before
+ public void setUpTestData() {
+ session = getMyBatis().openSession(false);
+ sut = new FileSourceDao(getMyBatis());
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void select() {
+ setupData("shared");
+
+ FileSourceDto fileSourceDto = sut.selectSource("FILE1_UUID");
+
+ assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
+ assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
+ assertThat(fileSourceDto.getProjectUuid()).isEqualTo("PRJ_UUID");
+ assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
+ assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
+ assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
+ assertThat(fileSourceDto.getDataType()).isEqualTo(Type.SOURCE);
+ }
+
+ @Test
+ public void select_line_hashes() {
+ setupData("shared");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "FILE1_UUID", fn);
+
+ assertThat(fn.result).isEqualTo("ABC\\nDEF\\nGHI");
+ }
+
+ @Test
+ public void no_line_hashes_on_unknown_file() {
+ setupData("shared");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "unknown", fn);
+
+ assertThat(fn.result).isNull();
+ }
+
+ @Test
+ public void no_line_hashes_when_only_test_data() {
+ setupData("no_line_hashes_when_only_test_data");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "FILE1_UUID", fn);
+
+ assertThat(fn.result).isNull();
+ }
+
+ @Test
+ public void insert() {
+ setupData("shared");
+
+ sut.insert(new FileSourceDto()
+ .setProjectUuid("PRJ_UUID")
+ .setFileUuid("FILE2_UUID")
+ .setBinaryData("FILE2_BINARY_DATA".getBytes())
+ .setDataHash("FILE2_DATA_HASH")
+ .setLineHashes("LINE1_HASH\\nLINE2_HASH")
+ .setSrcHash("FILE2_HASH")
+ .setDataType(Type.SOURCE)
+ .setCreatedAt(1500000000000L)
+ .setUpdatedAt(1500000000001L));
+
+ checkTable("insert", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type");
+ }
+
+ @Test
+ public void update() {
+ setupData("shared");
+
+ sut.update(new FileSourceDto()
+ .setId(101L)
+ .setProjectUuid("PRJ_UUID")
+ .setFileUuid("FILE1_UUID")
+ .setBinaryData("updated data".getBytes())
+ .setDataHash("NEW_DATA_HASH")
+ .setSrcHash("NEW_FILE_HASH")
+ .setLineHashes("NEW_LINE_HASHES")
+ .setDataType(Type.SOURCE)
+ .setUpdatedAt(1500000000002L));
+
+ checkTable("update", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type");
+ }
+
+ @Test
+ public void update_date_when_updated_date_is_zero() {
+ setupData("update_date_when_updated_date_is_zero");
+
+ sut.updateDateWhenUpdatedDateIsZero(session, "ABCD", 1500000000002L);
+ session.commit();
+
+ checkTable("update_date_when_updated_date_is_zero", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at",
+ "data_type");
+ }
+
+ private static class ReaderToStringFunction implements Function<Reader, String> {
+
+ String result = null;
+
+ @Override
+ public String apply(Reader input) {
+ try {
+ result = IOUtils.toString(input);
+ return IOUtils.toString(input);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static class InputStreamToStringFunction implements Function<InputStream, String> {
+
+ String result = null;
+
+ @Override
+ public String apply(InputStream input) {
+ try {
+ result = IOUtils.toString(input);
+ return IOUtils.toString(input);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java
new file mode 100644
index 00000000000..ff1c8cfecef
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.db.user;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+@Category(DbTests.class)
+public class UserGroupDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ private UserGroupDao dao;
+ private DbSession session;
+
+ @Before
+ public void before() {
+ db.truncateTables();
+ this.session = db.myBatis().openSession(false);
+ this.dao = new UserGroupDao();
+ }
+
+ @After
+ public void after() {
+ this.session.close();
+ }
+
+ @Test
+ public void insert() {
+ UserGroupDto userGroupDto = new UserGroupDto().setUserId(1L).setGroupId(2L);
+ dao.insert(session, userGroupDto);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", "groups_users");
+ }
+
+ @Test
+ public void delete_members_by_group_id() {
+ db.prepareDbUnit(getClass(), "delete_members_by_group_id.xml");
+ dao.deleteMembersByGroupId(session, 1L);
+ session.commit();
+ db.assertDbUnit(getClass(), "delete_members_by_group_id-result.xml", "groups_users");
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java b/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java
deleted file mode 100644
index d4743f578cc..00000000000
--- a/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.jpa.test;
-
-import java.io.InputStream;
-import java.sql.SQLException;
-import org.apache.commons.io.IOUtils;
-import org.apache.ibatis.session.SqlSession;
-import org.dbunit.Assertion;
-import org.dbunit.DataSourceDatabaseTester;
-import org.dbunit.DatabaseUnitException;
-import org.dbunit.IDatabaseTester;
-import org.dbunit.database.DatabaseConfig;
-import org.dbunit.database.IDatabaseConnection;
-import org.dbunit.dataset.CompositeDataSet;
-import org.dbunit.dataset.IDataSet;
-import org.dbunit.dataset.ITable;
-import org.dbunit.dataset.ReplacementDataSet;
-import org.dbunit.dataset.filter.DefaultColumnFilter;
-import org.dbunit.dataset.xml.FlatXmlDataSet;
-import org.dbunit.ext.mssql.InsertIdentityOperation;
-import org.dbunit.operation.DatabaseOperation;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.sonar.db.Database;
-import org.sonar.db.DatabaseCommands;
-import org.sonar.db.H2Database;
-import org.sonar.db.MyBatis;
-import org.sonar.db.deprecated.NullQueue;
-import org.sonar.db.version.DatabaseVersion;
-import org.sonar.db.version.SchemaMigrationMapper;
-
-import static org.junit.Assert.fail;
-
-/**
- * @deprecated this class does not support non-H2 databases
- */
-@Deprecated
-public abstract class AbstractDbUnitTestCase {
- private static Database database;
- private static MyBatis myBatis;
- private static DatabaseCommands databaseCommands;
- private IDatabaseTester databaseTester;
-
- @BeforeClass
- public static void startDatabase() throws SQLException {
- if (database == null) {
- database = new H2Database("sonarHibernate", true);
- database.start();
-
- databaseCommands = DatabaseCommands.forDialect(database.getDialect());
-
- myBatis = new MyBatis(database, new NullQueue());
- myBatis.start();
- try (SqlSession session = myBatis.openSession(false)) {
- session.getMapper(SchemaMigrationMapper.class).insert(String.valueOf(DatabaseVersion.LAST_VERSION));
- session.commit();
- }
- }
- }
-
- @Before
- public void startDbUnit() throws Exception {
- databaseCommands.truncateDatabase(database.getDataSource());
- databaseTester = new DataSourceDatabaseTester(database.getDataSource());
- }
-
- protected MyBatis getMyBatis() {
- return myBatis;
- }
-
- protected Database getDatabase() {
- return database;
- }
-
- protected void setupData(String... testNames) {
- InputStream[] streams = new InputStream[testNames.length];
- try {
- for (int i = 0; i < testNames.length; i++) {
- String className = getClass().getName();
- className = String.format("/%s/%s.xml", className.replace(".", "/"), testNames[i]);
- streams[i] = getClass().getResourceAsStream(className);
- if (streams[i] == null) {
- throw new RuntimeException("Test not found :" + className);
- }
- }
-
- setupData(streams);
- databaseCommands.resetPrimaryKeys(database.getDataSource());
- } catch (SQLException e) {
- throw translateException("Could not setup DBUnit data", e);
- } finally {
- for (InputStream stream : streams) {
- IOUtils.closeQuietly(stream);
- }
- }
- }
-
- private void setupData(InputStream... dataSetStream) {
- IDatabaseConnection connection = null;
- try {
- IDataSet[] dataSets = new IDataSet[dataSetStream.length];
- for (int i = 0; i < dataSetStream.length; i++) {
- dataSets[i] = getData(dataSetStream[i]);
- }
- databaseTester.setDataSet(new CompositeDataSet(dataSets));
-
- connection = createConnection();
-
- new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, databaseTester.getDataSet());
- } catch (Exception e) {
- throw translateException("Could not setup DBUnit data", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- private void closeQuietly(IDatabaseConnection connection) {
- try {
- if (connection != null) {
- connection.close();
- }
- } catch (SQLException ignored) {
-
- }
- }
-
- protected void checkTables(String testName, String... tables) {
- checkTables(testName, new String[0], tables);
- }
-
- protected void checkTables(String testName, String[] excludedColumnNames, String... tables) {
- IDatabaseConnection connection = null;
- try {
- connection = createConnection();
-
- IDataSet dataSet = connection.createDataSet();
- IDataSet expectedDataSet = getExpectedData(testName);
- for (String table : tables) {
- ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames);
- ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable(table), excludedColumnNames);
- Assertion.assertEquals(filteredExpectedTable, filteredTable);
- }
- } catch (DatabaseUnitException e) {
- fail(e.getMessage());
- } catch (SQLException e) {
- throw translateException("Error while checking results", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- protected void checkTable(String testName, String table, String... columns) {
- IDatabaseConnection connection = null;
- try {
- connection = createConnection();
-
- IDataSet dataSet = connection.createDataSet();
- IDataSet expectedDataSet = getExpectedData(testName);
- ITable filteredTable = DefaultColumnFilter.includedColumnsTable(dataSet.getTable(table), columns);
- ITable filteredExpectedTable = DefaultColumnFilter.includedColumnsTable(expectedDataSet.getTable(table), columns);
- Assertion.assertEquals(filteredExpectedTable, filteredTable);
-
- } catch (DatabaseUnitException e) {
- fail(e.getMessage());
- } catch (SQLException e) {
- throw translateException("Error while checking results", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- private IDatabaseConnection createConnection() {
- try {
- IDatabaseConnection connection = databaseTester.getConnection();
- connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, databaseCommands.getDbUnitFactory());
- return connection;
- } catch (Exception e) {
- throw translateException("Error while getting connection", e);
- }
- }
-
- private IDataSet getExpectedData(String testName) {
- String className = getClass().getName();
- className = String.format("/%s/%s-result.xml", className.replace('.', '/'), testName);
-
- InputStream in = getClass().getResourceAsStream(className);
- try {
- return getData(in);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- private IDataSet getData(InputStream stream) {
- try {
- ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream));
- dataSet.addReplacementObject("[null]", null);
- dataSet.addReplacementObject("[false]", Boolean.FALSE);
- dataSet.addReplacementObject("[true]", Boolean.TRUE);
- return dataSet;
- } catch (Exception e) {
- throw translateException("Could not read the dataset stream", e);
- }
- }
-
- private static RuntimeException translateException(String msg, Exception cause) {
- RuntimeException runtimeException = new RuntimeException(String.format("%s: [%s] %s", msg, cause.getClass().getName(), cause.getMessage()));
- runtimeException.setStackTrace(cause.getStackTrace());
- return runtimeException;
- }
-}
diff --git a/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml b/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml
deleted file mode 100644
index 64c38fb55ea..00000000000
--- a/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<dataset>
-
- <properties prop_key="key1" resource_id="[null]" text_value="value1" user_id="[null]"/>
- <properties prop_key="key2" resource_id="[null]" text_value="value2" user_id="[null]"/>
-
-</dataset> \ No newline at end of file
diff --git a/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml
new file mode 100644
index 00000000000..e76d538413e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml
@@ -0,0 +1,5 @@
+<dataset>
+ <issues id="10" kee="AB" />
+ <issues id="20" kee="CD" />
+ <issues id="30" kee="EF" />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql
new file mode 100644
index 00000000000..333bb0e193e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE "ISSUES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(200) NOT NULL
+);
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
index 871dedcb5e9..871dedcb5e9 100644
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
new file mode 100644
index 00000000000..33e9449d1dd
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
@@ -0,0 +1,7 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+ <project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
+ <project_links id="3" component_uuid="BCDE" link_type="homepage" name="Home" href="http://www.struts.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
new file mode 100644
index 00000000000..6b80fc9d01c
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="BCDE" link_type="ci" name="CI" href="github"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml
new file mode 100644
index 00000000000..aff69473ce1
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml
@@ -0,0 +1,32 @@
+<dataset>
+
+ <!-- Real projects -->
+ <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid_path=".ABCD." copy_resource_id="[null]" name="Project One" qualifier="TRK" scope="PRJ"/>
+ <projects id="2" uuid="BCDE" project_uuid="BCDE" module_uuid_path=".BCDE." copy_resource_id="[null]" name="Project Two" qualifier="TRK" scope="PRJ"/>
+
+ <!-- Copy projects -->
+ <projects id="3" uuid="CDEF" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="1" name="Copy Project One" qualifier="TRK" scope="FIL"/>
+ <projects id="4" uuid="DEFG" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="2" name="Copy Project One" qualifier="TRK" scope="FIL"/>
+
+ <!-- View containing all projects -->
+ <projects id="5" uuid="EFGH" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="[null]" name="All projects" qualifier="VW" scope="PRJ"/>
+
+ <resource_index id="1" kee="project one" resource_id="1" root_project_id="1" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index id="2" kee="roject one" resource_id="1" root_project_id="1" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index id="3" kee="oject one" resource_id="1" root_project_id="1" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index id="4" kee="ject one" resource_id="1" root_project_id="1" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index id="5" kee="ect one" resource_id="1" root_project_id="1" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index id="6" kee="ct one" resource_id="1" root_project_id="1" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index id="7" kee="t one" resource_id="1" root_project_id="1" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index id="8" kee=" one" resource_id="1" root_project_id="1" position="7" name_size="11" qualifier="TRK"/>
+ <resource_index id="9" kee="one" resource_id="1" root_project_id="1" position="8" name_size="11" qualifier="TRK"/>
+ <resource_index id="10" kee="project two" resource_id="2" root_project_id="2" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index id="11" kee="roject two" resource_id="2" root_project_id="2" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index id="12" kee="oject two" resource_id="2" root_project_id="2" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index id="13" kee="ject two" resource_id="2" root_project_id="2" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index id="14" kee="ect two" resource_id="2" root_project_id="2" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index id="15" kee="ct two" resource_id="2" root_project_id="2" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index id="16" kee="t two" resource_id="2" root_project_id="2" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index id="17" kee="two" resource_id="2" root_project_id="2" position="7" name_size="11" qualifier="TRK"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml
new file mode 100644
index 00000000000..a138d68b188
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <snapshots id="1" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1500000000001"
+ period2_mode="days2" period2_param="31" period2_date="1500000000002"
+ period3_mode="days3" period3_param="32" period3_date="1500000000003"
+ period4_mode="days4" period4_param="33" period4_date="1500000000004"
+ period5_mode="days5" period5_param="34" period5_date="1500000000005"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1403042400000" build_date="1500000000006"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml
new file mode 100644
index 00000000000..9ba70bee6f4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml
@@ -0,0 +1,90 @@
+<dataset>
+
+ <!-- root project -->
+ <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
+ uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="."
+ description="the description" long_name="Apache Struts"
+ enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="[null]" />
+ <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path=""/>
+ <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000"
+ version="[null]" path=""/>
+
+ <!-- module -->
+ <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core"
+ uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ scope="PRJ" qualifier="BRC" long_name="Struts Core"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1."/>
+
+ <!-- sub module -->
+ <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data"
+ uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH."
+ scope="PRJ" qualifier="BRC" long_name="Struts Data"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2."/>
+
+ <!-- directory -->
+ <projects long_name="org.struts" id="4" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts"
+ uuid="GHIJ" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path=".ABCD.EFGH.FGHI."
+ name="src/org/struts" root_id="3"
+ description="[null]"
+ enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" authorization_updated_at="[null]" />
+ <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="DIR" qualifier="PAC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2.3."/>
+
+ <!-- file -->
+ <projects long_name="org.struts.RequestContext" id="5" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:src/org/struts/RequestContext.java"
+ uuid="HIJK" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path=".ABCD.EFGH.FGHI."
+ name="RequestContext.java" root_id="3"
+ description="[null]"
+ enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts/RequestContext.java" authorization_updated_at="[null]" />
+
+ <snapshots id="5" project_id="5" parent_snapshot_id="4" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2.3.4."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml
new file mode 100644
index 00000000000..3f56960cd92
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml
@@ -0,0 +1,48 @@
+<dataset>
+
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD"
+ description="[null]"
+ enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+
+ <!-- version 1.0 -->
+ <snapshots id="1000" purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]"
+ period5_param="[null]" period5_date="[null]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225630680000" build_date="1225630680000" version="1.0" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.1 -->
+ <snapshots id="1001" purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]"
+ period5_param="[null]" period5_date="[null]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225803480000" build_date="1225803480000" version="1.1" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.2-SNAPSHOT -->
+ <snapshots id="1002" purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]"
+ period5_param="[null]" period5_date="[null]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225976280000" build_date="1225976280000" version="1.2-SNAPSHOT" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.2-SNAPSHOT, current analysis -->
+ <snapshots id="1003" purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]" period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]" period4_date="[null]" period5_mode="[null]"
+ period5_param="[null]" period5_date="[null]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1226235480000" build_date="1226235480000" version="1.2-SNAPSHOT" path=""
+ status="U" islast="[true]" depth="0"/>
+
+ <events id="1" name="1.0" component_uuid="ABCD" snapshot_id="1000" category="Version" event_date="1225630680000" created_at="1225630680000" description="" event_data="[null]"/>
+ <events id="2" name="Foo" component_uuid="ABCD" snapshot_id="1000" category="Other" event_date="1225717080000" created_at="1225717080000" description="" event_data="[null]"/>
+ <events id="3" name="1.1" component_uuid="ABCD" snapshot_id="1001" category="Version" event_date="1225803480000" created_at="1225803480000" description="" event_data="[null]"/>
+ <events id="4" name="Bar" component_uuid="ABCD" snapshot_id="1001" category="Other" event_date="1225889880000" created_at="1225889880000" description="" event_data="[null]"/>
+ <events id="5" name="Uhh" component_uuid="ABCD" snapshot_id="1002" category="Other" event_date="1226062680000" created_at="1226062680000" description="" event_data="[null]"/>
+ <events id="6" name="1.2-SNAPSHOT" component_uuid="ABCD" snapshot_id="1003" category="Version" event_date="1226235480000" created_at="1226235480000" description=""
+ event_data="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml
new file mode 100644
index 00000000000..1f32010f385
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml
@@ -0,0 +1,64 @@
+<dataset>
+
+ <!-- PROJECT_ID = 1 -->
+ <snapshots id="1" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400001" build_date="1317247200000"
+ version="2.0-SNAPSHOT" path="1.2."/>
+ <snapshots id="2" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400002" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="3" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400003" build_date="1317247200000"
+ version="2.2-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 2 -->
+ <snapshots id="4" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <!-- Unprocessed snapshot -->
+ <snapshots id="5" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="U" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 3 - no last snapshot -->
+ <snapshots id="6" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml
new file mode 100644
index 00000000000..a52b271da32
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml
new file mode 100644
index 00000000000..4c18e257396
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml
@@ -0,0 +1,65 @@
+<dataset>
+
+ <!-- PROJECT_ID = 1 -->
+ <snapshots id="1" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="2" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="3" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+
+ <!-- PROJECT_ID = 2 -->
+ <snapshots id="4" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 3 - no last snapshot -->
+ <snapshots id="5" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- Child of snapshot id=1 -->
+ <snapshots id="6" project_id="55" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml
new file mode 100644
index 00000000000..dba17d047a4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml
@@ -0,0 +1,26 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ uuid="REPORT_1"
+ project_key="123456789-987654321"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411509600000"
+ />
+ <analysis_reports
+ id="2"
+ uuid="REPORT_2"
+ project_key="123456789-987654321"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ uuid="REPORT_3"
+ project_key="123456789-987654321"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
new file mode 100644
index 00000000000..ae28befd603
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
@@ -0,0 +1,18 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="REPORT_1"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ uuid="REPORT_2"
+ report_status="WORKING"
+ created_at="1411423200000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml
new file mode 100644
index 00000000000..d25e3641ce9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml
@@ -0,0 +1,24 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="ProjectKey1"
+ project_name="Project 1"
+ uuid="UUID_1"
+ report_status="PENDING"
+ started_at="[null]"
+ finished_at="[null]"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="ProjectKey2"
+ project_name="Project 2"
+ uuid="UUID_2"
+ report_status="PENDING"
+ started_at="[null]"
+ finished_at="[null]"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml
new file mode 100644
index 00000000000..c38ac125e00
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml
@@ -0,0 +1,12 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="REPORT_1"
+ report_status="WORKING"
+ created_at="1500000000001"
+ updated_at="1500000000002"
+ started_at="1500000000003"
+ finished_at="1500000000004"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
new file mode 100644
index 00000000000..82f93e9fec5
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
@@ -0,0 +1,27 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="111111111-987654321"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="123456789-987654321"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411682400000"
+ />
+ <!-- not select as the previous report which is working is on the same project -->
+ <analysis_reports
+ id="3"
+ project_key="123456789-987654321"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml
new file mode 100644
index 00000000000..972fde88fd7
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml
@@ -0,0 +1,37 @@
+<dataset>
+ <!-- WORKING -->
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+
+ <!-- PENDING on P1, which is already being WORKING-->
+ <analysis_reports
+ id="2"
+ project_key="P1"
+ uuid="UUID_2"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P2"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="4"
+ project_key="P2"
+ uuid="UUID_4"
+ report_status="PENDING"
+ created_at="1420066800000"
+ updated_at="1420066800000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml
new file mode 100644
index 00000000000..de9d5b9f330
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ project_name="Project 1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ project_name="Project 2"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="987654321-123456789"
+ project_name="Project 2"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml
new file mode 100644
index 00000000000..c1e3284f108
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml
@@ -0,0 +1,26 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="987654321-123456789"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml
new file mode 100644
index 00000000000..e573e0c5b06
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml
@@ -0,0 +1,3 @@
+<dataset>
+ <analysis_reports/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
new file mode 100644
index 00000000000..16fb8dc0895
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
@@ -0,0 +1,36 @@
+<dataset>
+ <!-- all rows are PENDING, updated_at is now, started_at is null -->
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_1"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="2"
+ project_key="P2"
+ project_name="Project2"
+ uuid="UUID_2"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml
new file mode 100644
index 00000000000..a630cb4ec4b
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml
@@ -0,0 +1,35 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411509600000"
+ started_at="1411509600000"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="2"
+ project_key="P2"
+ project_name="Project2"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ started_at="1411509600000"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip
new file mode 100644
index 00000000000..a540bc5b5ca
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip
Binary files differ
diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml
new file mode 100644
index 00000000000..a942341e3d4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml
@@ -0,0 +1,18 @@
+<dataset>
+
+ <widgets id="1" dashboard_id="1" widget_key="polop" name="Polop" description="Palap"
+ column_index="1" row_index="1" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="2" dashboard_id="1" widget_key="false_positive_reviews" name="Polop" description="Palap"
+ column_index="1" row_index="2" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="3" dashboard_id="1" widget_key="my_reviews" name="Polop" description="Palap"
+ column_index="1" row_index="3" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="4" dashboard_id="1" widget_key="reviews_per_developer" name="Polop" description="Palap"
+ column_index="1" row_index="4" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="5" dashboard_id="1" widget_key="unresolved_issues_statuses" name="Polop" description="Palap"
+ column_index="1" row_index="5" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml
new file mode 100644
index 00000000000..c22a68ed8e0
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1225630680000"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml
new file mode 100644
index 00000000000..27a2a24e080
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml
new file mode 100644
index 00000000000..0002deec3c2
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+ <events id="2" name="Red (was Orange)" category="Alert" description="Critical issues variation > 0 since previous version (1.0 - 2015 Feb 09), Open issues > 0"
+ event_data="[null]" event_date="1413407091086" component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+ <events id="3" name="Changes in 'Default' (Java)" category="Profile" description="Version 1.0" event_data="from=2014-10-12T08:36:25+0000;key=java-default;to=2014-10-12T10:36:25+0000"
+ event_date="1413407091086" component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+ <events id="4" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="BCDE" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml
new file mode 100644
index 00000000000..a052d421f66
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml
@@ -0,0 +1,29 @@
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="CDEF"
+ project_uuid="ABCD"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ action_plan_key="AP-1"
+ author_login="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="1400000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml
new file mode 100644
index 00000000000..154a7a67883
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml
@@ -0,0 +1,28 @@
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="CDEF"
+ project_uuid="ABCD"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml
new file mode 100644
index 00000000000..fc1543cb2b9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="component-uuid"
+ project_uuid="project-uuid"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ tags="[null]"
+ issue_creation_date="1500000000000"
+ issue_update_date="1500000000001"
+ issue_close_date="1500000000002"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml
new file mode 100644
index 00000000000..d5959c63659
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="123"
+ project_uuid="101"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ tags="[null]"
+ issue_creation_date="1368828000000"
+ issue_update_date="1368914400000"
+ issue_close_date="1369000800000"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml
new file mode 100644
index 00000000000..9c41f1922cc
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml
@@ -0,0 +1,28 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="123"
+ project_uuid="100"
+ rule_id="200"
+ severity="INFO"
+ manual_severity="[false]"
+ message="old"
+ line="[null]"
+ effort_to_fix="[null]"
+ technical_debt="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ author_login="[null]"
+ assignee="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="[null]"
+ issue_update_date="[null]"
+ issue_close_date="[null]"
+ created_at="1400000000000"
+ updated_at="1400000000000"
+ action_plan_key="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml
new file mode 100644
index 00000000000..dda18829567
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+ <project_measures/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
new file mode 100644
index 00000000000..26c55c5d3c4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
@@ -0,0 +1,27 @@
+<dataset>
+ <project_measures
+ id="1"
+ snapshot_id="2"
+ metric_id="3"
+ characteristic_id="4"
+ rule_id="5"
+ project_id="6"
+ person_id="23"
+ value="2.0"
+ text_value="measure-value"
+ tendency="[null]"
+ rule_priority="[null]"
+ measure_date="[null]"
+ measure_data="[null]"
+ variation_value_1="1.0"
+ variation_value_2="2.0"
+ variation_value_3="3.0"
+ variation_value_4="4.0"
+ variation_value_5="5.0"
+ alert_status="alert"
+ alert_text="alert-text"
+ url="[null]"
+ description="measure-description"
+ rules_category_id="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml
new file mode 100644
index 00000000000..1a9eaecf522
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml
@@ -0,0 +1,59 @@
+<dataset>
+
+ <metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <metrics id="2" name="coverage" VAL_TYPE="INT" enabled="[true]"/>
+
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- package -->
+ <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="project:org.foo" name="org.foo"
+ root_id="1" uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- file -->
+ <projects long_name="org.foo.Bar" id="3" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar"
+ name="Bar" root_id="[null]" uuid="CDEF" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+ <snapshots id="1001" project_id="2" parent_snapshot_id="1000" root_project_id="1" root_snapshot_id="1000"
+ scope="DIR" qualifier="PAC" created_at="1225544280000" build_date="1225544280000" version="[null]" path="1000."
+ status="P" islast="[false]" depth="1"/>
+ <snapshots id="1002" project_id="3" parent_snapshot_id="1001" root_project_id="1" root_snapshot_id="1000"
+ scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path="1000.1001."
+ status="P" islast="[false]" depth="2"/>
+
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="80" METRIC_ID="2" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <!-- package measures -->
+ <project_measures id="3" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1001" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="4" VALUE="70" METRIC_ID="2" SNAPSHOT_ID="1001" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <!-- file measures -->
+ <project_measures id="5" VALUE="5" METRIC_ID="1" SNAPSHOT_ID="1002" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="6" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="1002" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml
new file mode 100644
index 00000000000..7e06f10c94c
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml
@@ -0,0 +1,28 @@
+<dataset>
+
+ <metrics id="1" name="sqale_index" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]" short_name="" enabled="[true]"/>
+
+ <!-- Root characteristic -->
+ <characteristics id="10" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" enabled="[true]" created_at="2013-11-20" updated_at="2013-11-22"/>
+
+ <!-- Characteristic -->
+ <characteristics id="11" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="10" characteristic_order="[null]" enabled="[true]"
+ created_at="2013-11-20" updated_at="2013-11-22"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="10"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="11"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
new file mode 100644
index 00000000000..47a1c6933e4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
@@ -0,0 +1,22 @@
+<dataset>
+
+ <metrics delete_historical_data="[null]" id="1" name="sqale_index" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="20"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="21"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml
new file mode 100644
index 00000000000..b6ccf49fca2
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml
@@ -0,0 +1,32 @@
+<dataset>
+
+ <metrics delete_historical_data="[null]" id="1" name="minor_violations" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Classes that override clone should be Cloneable and call super.clone()"
+ plugin_rule_key="S1182"
+ plugin_config_key="S1182" plugin_name="squid" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Overriding methods should do more than simply call the same method in the super class"
+ plugin_rule_key="S1185"
+ plugin_config_key="S1185" plugin_name="squid" description="[null]" priority="1" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="30" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="31" characteristic_id="[null]" person_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml
new file mode 100644
index 00000000000..c27311c8d38
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml
@@ -0,0 +1,21 @@
+<dataset>
+
+ <metrics id="10" name="authors_by_line"/>
+ <metrics id="11" name="coverage_line_hits_data"/>
+ <metrics id="12" name="ncloc"/>
+
+ <projects id="1" kee="org.struts:struts-core:src/org/struts/RequestContext.java" enabled="[true]"/>
+
+ <snapshots id="5" project_id="1" islast="[true]" />
+
+ <project_measures id="20" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" measure_data="[null]"
+ variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
+ alert_status="[null]" alert_text="[null]" />
+ <project_measures id="21" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" measure_data="[null]"
+ variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
+ alert_status="[null]" alert_text="[null]" />
+ <project_measures id="22" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
+ variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
+ alert_status="OK" alert_text="Green"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml
deleted file mode 100644
index 2283bba7d52..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" inheritance="INHERITED"-->
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml
deleted file mode 100644
index 617cd7e08b0..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" inheritance="[null]"-->
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml
deleted file mode 100644
index a06288e57b6..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"/>-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml
deleted file mode 100644
index 900eb2c2874..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>-->
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml
deleted file mode 100644
index b8aba08833d..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>-->
- <!--<active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>-->
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml
deleted file mode 100644
index d1bbff5912e..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <!--<active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>-->
- <!--<active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/>-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml
deleted file mode 100644
index 47c6ceeac24..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
- <active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml
deleted file mode 100644
index 574cbabdd56..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml
deleted file mode 100644
index ed2e17d48d3..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml
deleted file mode 100644
index b6d5461c10d..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
- <rules_profiles id="1" name="Child" language="java" parent_kee="parent" kee="child" is_default="[false]"/>
-
- <rules_profiles id="2" name="Parent" language="java" parent_kee="[null]" kee="parent" is_default="[false]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml
deleted file mode 100644
index 30111d636a7..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="4"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml
deleted file mode 100644
index 289da2f39f2..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<dataset>
-
- <active_rule_parameters id="1" active_rule_id="2" rules_parameter_id="3" rules_parameter_key="newMax" value="30"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml
new file mode 100644
index 00000000000..4f347782dca
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml
@@ -0,0 +1,17 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash"
+ line_hashes="ABC\nDEF\nGHI"
+ src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+
+ <file_sources id="102" project_uuid="PRJ_UUID" file_uuid="FILE2_UUID"
+ binary_data="[ignore]"
+ data_hash="FILE2_DATA_HASH"
+ line_hashes="LINE1_HASH\nLINE2_HASH"
+ src_hash="FILE2_HASH"
+ created_at="1500000000000" updated_at="1500000000001" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml
new file mode 100644
index 00000000000..010394a156e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml
@@ -0,0 +1,9 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="[null]"
+ line_hashes="[null]"
+ src_hash="[null]"
+ created_at="1500000000000" updated_at="1500000000000" data_type="TEST" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml
new file mode 100644
index 00000000000..5187ca217af
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml
@@ -0,0 +1,9 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash"
+ line_hashes="ABC\nDEF\nGHI"
+ src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml
new file mode 100644
index 00000000000..8dbe32d946d
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml
@@ -0,0 +1,11 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="[ignore]"
+ data_hash="NEW_DATA_HASH"
+ line_hashes="NEW_LINE_HASHES"
+ src_hash="NEW_FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002" data_type="SOURCE" />
+
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
new file mode 100644
index 00000000000..1ba1fe63a55
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
@@ -0,0 +1,18 @@
+<dataset>
+
+ <!-- Updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002" data_type="SOURCE" />
+
+ <!-- Not updated because updated_at is not null -->
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+ <!-- Not updated because on another project -->
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
new file mode 100644
index 00000000000..77a1f85b06a
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
@@ -0,0 +1,16 @@
+<dataset>
+
+ <!-- Only this source should be updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml
new file mode 100644
index 00000000000..edac414e636
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="2"/>
+ <groups_users user_id="2" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml
new file mode 100644
index 00000000000..2430e53dd8e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml
@@ -0,0 +1,8 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="1"/>
+ <groups_users user_id="2" group_id="1"/>
+ <groups_users user_id="1" group_id="2"/>
+ <groups_users user_id="2" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml
new file mode 100644
index 00000000000..2e5bb1ada57
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml b/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml
deleted file mode 100644
index aeb851beb8e..00000000000
--- a/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-
- <rules_profiles id="1" name="profile one" language="java" is_default="[false]"/>
- <rules_profiles id="2" name="profile two" language="java" is_default="[false]"/>
- <rules_profiles id="3" name="profile three" language="plsql" is_default="[false]"/>
-
-</dataset> \ No newline at end of file