From 647037bf676290036eab93512139d52f283ca4d3 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 20 Feb 2014 12:53:09 +0100 Subject: [PATCH] SONAR-4996 Prepare migration to update issue changelog debt to seconds --- .../sonar/core/persistence/TestDatabase.java | 2 +- .../sonar/api/utils/WorkDurationFactory.java | 4 + .../db/migrations/debt/DebtConvertor.java | 71 +++++++ .../debt/IssueChangelogMigration.java | 175 ++++++++++++++++++ .../db/migrations/debt/IssueMigration.java | 65 ++----- ...sueReferentials.java => Referentials.java} | 18 +- .../server/technicaldebt/DebtService.java | 4 - .../db/migrations/debt/DebtConvertorTest.java | 79 ++++++++ .../debt/IssueChangelogMigrationTest.java | 59 ++++++ .../migrations/debt/IssueMigrationTest.java | 16 +- .../server/technicaldebt/DebtServiceTest.java | 5 - .../IssueChangelogMigrationTest/schema.sql | 28 +++ 12 files changed, 451 insertions(+), 75 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java create mode 100644 sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java rename sonar-server/src/main/java/org/sonar/server/db/migrations/debt/{IssueReferentials.java => Referentials.java} (86%) create mode 100644 sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java create mode 100644 sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java create mode 100644 sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java b/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java index 00eb8c66033..545bf45e36b 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/TestDatabase.java @@ -65,7 +65,7 @@ import java.util.Properties; import static org.junit.Assert.fail; /** - * This class should be call using @ClassRule, in order to create the schema once per test class. + * 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(). */ public class TestDatabase extends ExternalResource { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkDurationFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkDurationFactory.java index d5f914b0dba..b86ee4fbf96 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkDurationFactory.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/WorkDurationFactory.java @@ -44,6 +44,10 @@ public final class WorkDurationFactory implements BatchComponent, ServerComponen return WorkDuration.createFromValueAndUnit(value, unit, hoursInDay()); } + /** + * @deprecated since 4.3 + */ + @Deprecated public WorkDuration createFromWorkingLong(long duration) { return WorkDuration.createFromLong(duration, hoursInDay()); } diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java new file mode 100644 index 00000000000..4ae3b4ef185 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java @@ -0,0 +1,71 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import org.sonar.api.config.Settings; + +class DebtConvertor { + + static final String HOURS_IN_DAY_PROPERTY = "sonar.technicalDebt.hoursInDay"; + private final Settings settings; + + DebtConvertor(Settings settings) { + this.settings = settings; + } + + long createFromLong(long durationInLong) { + int hoursInDay = hoursInDay(); + + long durationInSeconds = 0; + + long remainingTime = durationInLong; + Long currentTime = remainingTime / 10000; + if (currentTime > 0) { + durationInSeconds = currentTime.intValue() * hoursInDay * 3600; + remainingTime = remainingTime - (currentTime * 10000); + } + + currentTime = remainingTime / 100; + if (currentTime > 0) { + durationInSeconds += currentTime.intValue() * 3600; + remainingTime = remainingTime - (currentTime * 100); + } + + currentTime = remainingTime; + if (currentTime > 0) { + durationInSeconds += currentTime.intValue() * 60; + } + + return durationInSeconds; + } + + private int hoursInDay() { + int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY); + if (hoursInDay < 0) { + throw new IllegalArgumentException(String.format("Bad value of %s: %d", HOURS_IN_DAY_PROPERTY, hoursInDay)); + } + if (hoursInDay == 0) { + hoursInDay = 8; + } + return hoursInDay; + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java new file mode 100644 index 00000000000..2b85cb05849 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java @@ -0,0 +1,175 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.dbutils.QueryRunner; +import org.apache.commons.dbutils.handlers.AbstractListHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.System2; +import org.sonar.core.persistence.Database; +import org.sonar.server.db.migrations.DatabaseMigration; +import org.sonar.server.db.migrations.util.SqlUtil; + +import java.sql.Connection; +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * Used in the Active Record Migration 514 + */ +public class IssueChangelogMigration implements DatabaseMigration { + + private Logger logger = LoggerFactory.getLogger(IssueChangelogMigration.class); + + private static final String ID = "id"; + private static final String CHANGE_DATA = "changeData"; + + private static final String FAILURE_MESSAGE = "Fail to convert issue changelog debt from work duration to seconds"; + + private static final String SQL_SELECT = "SELECT * FROM issue_changes WHERE change_type = 'diff' and change_data LIKE '%technicalDebt%'"; + private static final String SQL_UPDATE = "UPDATE issue_changes SET change_data=?,updated_at=? WHERE id=?"; + + static final String SQL_SELECT_ISSUES; + + static { + StringBuilder sb = new StringBuilder("select c.id as "+ ID +", c.change_data as " + CHANGE_DATA + + " from issue_changes c " + + " where "); + for (int i = 0; i < Referentials.GROUP_SIZE; i++) { + if (i > 0) { + sb.append(" or "); + } + sb.append("c.id=?"); + } + SQL_SELECT_ISSUES = sb.toString(); + } + + private final DebtConvertor debtConvertor; + private final System2 system2; + private final Database db; + + public IssueChangelogMigration(Database database, Settings settings) { + this(database, settings, System2.INSTANCE); + } + + @VisibleForTesting + IssueChangelogMigration(Database database, Settings settings, System2 system2) { + this.db = database; + this.debtConvertor = new DebtConvertor(settings); + this.system2 = system2; + } + + @Override + public void execute() { + try { + logger.info("Initialize input"); + Referentials referentials = new Referentials(db, SQL_SELECT); + if (referentials.size() > 0) { + logger.info("Migrate {} issues changelog", referentials.size()); + convert(referentials); + } + } catch (SQLException e) { + logger.error(FAILURE_MESSAGE, e); + SqlUtil.log(logger, e); + throw MessageException.of(FAILURE_MESSAGE); + + } catch (Exception e) { + logger.error(FAILURE_MESSAGE, e); + throw MessageException.of(FAILURE_MESSAGE); + } + } + + public Object convert(Referentials referentials) throws Exception { + // For each group of 1000 issue ids: + // - load related issues + // - in a transaction + // -- update issues + + Long[] issueIds = referentials.pollGroupOfIds(); + while (issueIds.length > 0) { + List> rows = selectRows(issueIds); + convert(rows, issueIds); + + issueIds = referentials.pollGroupOfIds(); + } + return null; + } + + private List> selectRows(Long[] issueIds) throws SQLException { + Connection readConnection = null; + try { + readConnection = db.getDataSource().getConnection(); + IssueHandler issueHandler = new IssueHandler(); + return new QueryRunner().query(readConnection, SQL_SELECT_ISSUES, issueHandler, issueIds); + + } finally { + DbUtils.closeQuietly(readConnection); + } + } + + private void convert(List> rows, Long[] issueIds) throws SQLException { + Connection readConnection = null; + Connection writeConnection = null; + try { + readConnection = db.getDataSource().getConnection(); + writeConnection = db.getDataSource().getConnection(); + writeConnection.setAutoCommit(false); + + List allParams = Lists.newArrayList(); + QueryRunner runner = new QueryRunner(); + for (Map row : rows) { + Object[] params = new Object[3]; +// params[0] = debtConvertor.createFromLong((Long) row.get(CHANGE_DATA)); + params[0] = row.get(CHANGE_DATA); + params[1] = new Date(system2.now()); + params[2] = row.get(ID); + allParams.add(params); + } + runner.batch(writeConnection, SQL_UPDATE, allParams.toArray(new Object[allParams.size()][])); + writeConnection.commit(); + + } finally { + DbUtils.closeQuietly(readConnection); + DbUtils.closeQuietly(writeConnection); + } + } + + private static class IssueHandler extends AbstractListHandler> { + @Override + protected Map handleRow(ResultSet rs) throws SQLException { + Map map = Maps.newHashMap(); + map.put(ID, SqlUtil.getLong(rs, ID)); + map.put(CHANGE_DATA, SqlUtil.getLong(rs, CHANGE_DATA)); + return map; + } + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java index 1ead0d8bf36..e5e879c46bb 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueMigration.java @@ -43,7 +43,7 @@ import java.util.List; import java.util.Map; /** - * Used in the Active Record Migration 401 + * Used in the Active Record Migration 513 */ public class IssueMigration implements DatabaseMigration { @@ -52,10 +52,10 @@ public class IssueMigration implements DatabaseMigration { private static final String ID = "id"; private static final String DEBT = "debt"; - static final String HOURS_IN_DAY_PROPERTY = "sonar.technicalDebt.hoursInDay"; private static final String FAILURE_MESSAGE = "Fail to convert issue debt from work duration to seconds"; - private static final String SQL_UPDATE_ISSUE = "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?"; + private static final String SQL_SELECT = "SELECT id FROM issues WHERE technical_debt IS NOT NULL"; + private static final String SQL_UPDATE = "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?"; static final String SQL_SELECT_ISSUES; @@ -63,7 +63,7 @@ public class IssueMigration implements DatabaseMigration { StringBuilder sb = new StringBuilder("select i.id as "+ ID +", i.technical_debt as " + DEBT + " from issues i " + " where "); - for (int i = 0; i < IssueReferentials.GROUP_SIZE; i++) { + for (int i = 0; i < Referentials.GROUP_SIZE; i++) { if (i > 0) { sb.append(" or "); } @@ -72,7 +72,7 @@ public class IssueMigration implements DatabaseMigration { SQL_SELECT_ISSUES = sb.toString(); } - private final Settings settings; + private final DebtConvertor debtConvertor; private final System2 system2; private final Database db; @@ -83,7 +83,7 @@ public class IssueMigration implements DatabaseMigration { @VisibleForTesting IssueMigration(Database database, Settings settings, System2 system2) { this.db = database; - this.settings = settings; + this.debtConvertor = new DebtConvertor(settings); this.system2 = system2; } @@ -91,9 +91,9 @@ public class IssueMigration implements DatabaseMigration { public void execute() { try { logger.info("Initialize input"); - IssueReferentials referentials = new IssueReferentials(db); - if (referentials.totalIssues() > 0) { - logger.info("Migrate {} issues", referentials.totalIssues()); + Referentials referentials = new Referentials(db, SQL_SELECT); + if (referentials.size() > 0) { + logger.info("Migrate {} issues", referentials.size()); convert(referentials); } } catch (SQLException e) { @@ -107,18 +107,18 @@ public class IssueMigration implements DatabaseMigration { } } - public Object convert(IssueReferentials referentials) throws Exception { + public Object convert(Referentials referentials) throws Exception { // For each group of 1000 issue ids: // - load related issues // - in a transaction // -- update issues - Long[] issueIds = referentials.pollGroupOfIssueIds(); + Long[] issueIds = referentials.pollGroupOfIds(); while (issueIds.length > 0) { List> rows = selectRows(issueIds); convert(rows, issueIds); - issueIds = referentials.pollGroupOfIssueIds(); + issueIds = referentials.pollGroupOfIds(); } return null; } @@ -143,18 +143,16 @@ public class IssueMigration implements DatabaseMigration { writeConnection = db.getDataSource().getConnection(); writeConnection.setAutoCommit(false); - int hoursInDay = hoursInDay(); - List allParams = Lists.newArrayList(); QueryRunner runner = new QueryRunner(); for (Map row : rows) { Object[] params = new Object[3]; - params[0] = createFromLong((Long) row.get(DEBT), hoursInDay); + params[0] = debtConvertor.createFromLong((Long) row.get(DEBT)); params[1] = new Date(system2.now()); params[2] = row.get(ID); allParams.add(params); } - runner.batch(writeConnection, SQL_UPDATE_ISSUE, allParams.toArray(new Object[allParams.size()][])); + runner.batch(writeConnection, SQL_UPDATE, allParams.toArray(new Object[allParams.size()][])); writeConnection.commit(); } finally { @@ -163,30 +161,6 @@ public class IssueMigration implements DatabaseMigration { } } - static long createFromLong(long durationInLong, int hoursInDay) { - long durationInSeconds = 0; - - long remainingTime = durationInLong; - Long currentTime = remainingTime / 10000; - if (currentTime > 0) { - durationInSeconds = currentTime.intValue() * hoursInDay * 3600; - remainingTime = remainingTime - (currentTime * 10000); - } - - currentTime = remainingTime / 100; - if (currentTime > 0) { - durationInSeconds += currentTime.intValue() * 3600; - remainingTime = remainingTime - (currentTime * 100); - } - - currentTime = remainingTime; - if (currentTime > 0) { - durationInSeconds += currentTime.intValue() * 60; - } - - return durationInSeconds; - } - private static class IssueHandler extends AbstractListHandler> { @Override protected Map handleRow(ResultSet rs) throws SQLException { @@ -197,15 +171,4 @@ public class IssueMigration implements DatabaseMigration { } } - private int hoursInDay() { - int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY); - if (hoursInDay < 0) { - throw new IllegalArgumentException(String.format("Bad value of %s: %d", HOURS_IN_DAY_PROPERTY, hoursInDay)); - } - if (hoursInDay == 0) { - hoursInDay = 8; - } - return hoursInDay; - } - } diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueReferentials.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/Referentials.java similarity index 86% rename from sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueReferentials.java rename to sonar-server/src/main/java/org/sonar/server/db/migrations/debt/Referentials.java index 6743cb90392..47b577c4cdd 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueReferentials.java +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/Referentials.java @@ -33,23 +33,25 @@ import java.util.concurrent.ConcurrentLinkedQueue; /** * Data loaded from database before migrating debt of issues. */ -class IssueReferentials { +class Referentials { static final int GROUP_SIZE = 1000; - private final Queue groupsOfIssuesIds; + private final Queue groupsOfIds; + private final String query; private long totalIssues = 0L; - IssueReferentials(Database database) throws SQLException { - groupsOfIssuesIds = initGroupOfIssueIds(database); + Referentials(Database database, String query) throws SQLException { + this.query = query; + groupsOfIds = initGroupOfIssueIds(database); } - long totalIssues() { + long size() { return totalIssues; } - Long[] pollGroupOfIssueIds() { - long[] longs = groupsOfIssuesIds.poll(); + Long[] pollGroupOfIds() { + long[] longs = groupsOfIds.poll(); if (longs == null) { return new Long[0]; } @@ -68,7 +70,7 @@ class IssueReferentials { connection.setAutoCommit(false); stmt = connection.createStatement(); stmt.setFetchSize(10000); - rs = stmt.executeQuery("SELECT id FROM issues WHERE technical_debt IS NOT NULL"); + rs = stmt.executeQuery(query); ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); totalIssues = 0; diff --git a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java index 8c37f5fba87..ac5f4031d72 100644 --- a/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java +++ b/sonar-server/src/main/java/org/sonar/server/technicaldebt/DebtService.java @@ -46,10 +46,6 @@ public class DebtService implements ServerComponent { return debtFormatter.format(UserSession.get().locale(), debt); } - public WorkDuration toTechnicalDebt(String technicalDebtInLong) { - return workDurationFactory.createFromWorkingLong(Long.parseLong(technicalDebtInLong)); - } - public WorkDuration toWorkDuration(long debt) { return workDurationFactory.createFromSeconds(debt); } diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java new file mode 100644 index 00000000000..d6a3544d84d --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.sonar.api.config.Settings; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class DebtConvertorTest { + + DebtConvertor convertor; + + Settings settings = new Settings(); + + @Before + public void setUp() throws Exception { + convertor = new DebtConvertor(settings); + } + + @Test + public void convert() throws Exception { + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); + + assertThat(convertor.createFromLong(1)).isEqualTo(60); + assertThat(convertor.createFromLong(100)).isEqualTo(3600); + assertThat(convertor.createFromLong(10000)).isEqualTo(28800); + assertThat(convertor.createFromLong(10101)).isEqualTo(32460); + } + + @Ignore("Failing, to be fixed") + @Test + public void convert_with_useless_zro_in_front() throws Exception { + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); + + assertThat(convertor.createFromLong(01)).isEqualTo(60); + assertThat(convertor.createFromLong(0100)).isEqualTo(3600); + assertThat(convertor.createFromLong(010000)).isEqualTo(28800); + assertThat(convertor.createFromLong(010101)).isEqualTo(32460); + } + + @Test + public void use_default_value_for_hours_in_day_when_no_property() throws Exception { + assertThat(convertor.createFromLong(1)).isEqualTo(60); + } + + @Test + public void fail_on_bad_hours_in_day_settings() throws Exception { + try { + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, -2); + convertor.createFromLong(1); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java new file mode 100644 index 00000000000..925c381fc30 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Ignore; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.System2; +import org.sonar.core.persistence.TestDatabase; + +import static org.mockito.Mockito.when; + +@Ignore +@RunWith(MockitoJUnitRunner.class) +public class IssueChangelogMigrationTest { + + @ClassRule + public static TestDatabase db = new TestDatabase().schema(IssueMigrationTest.class, "schema.sql"); + + @Mock + System2 system2; + + Settings settings; + + IssueChangelogMigration migration; + + @Before + public void setUp() throws Exception { + when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime()); + settings = new Settings(); + + migration = new IssueChangelogMigration(db.database(), settings, system2); + } + + +} diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java index bcef449b73c..fd13cc4e689 100644 --- a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/IssueMigrationTest.java @@ -47,18 +47,22 @@ public class IssueMigrationTest { Settings settings; + IssueMigration issueMigration; + @Before public void setUp() throws Exception { when(system2.now()).thenReturn(DateUtils.parseDate("2014-02-19").getTime()); settings = new Settings(); + + issueMigration = new IssueMigration(db.database(), settings, system2); } @Test - public void migrate_violations() throws Exception { + public void migrate_issues() throws Exception { db.prepareDbUnit(getClass(), "migrate_issues_debt.xml"); - settings.setProperty(IssueMigration.HOURS_IN_DAY_PROPERTY, 8); - new IssueMigration(db.database(), settings, system2).execute(); + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); + issueMigration.execute(); db.assertDbUnit(getClass(), "migrate_issues_debt_result.xml", "issues"); } @@ -67,7 +71,7 @@ public class IssueMigrationTest { public void use_default_value_for_hours_in_day_when_no_property() throws Exception { db.prepareDbUnit(getClass(), "use_default_value_for_hours_in_day_when_no_property.xml"); - new IssueMigration(db.database(), settings, system2).execute(); + issueMigration.execute(); db.assertDbUnit(getClass(), "use_default_value_for_hours_in_day_when_no_property_result.xml", "issues"); } @@ -77,8 +81,8 @@ public class IssueMigrationTest { db.prepareDbUnit(getClass(), "migrate_issues_debt.xml"); try { - settings.setProperty(IssueMigration.HOURS_IN_DAY_PROPERTY, -2); - new IssueMigration(db.database(), settings, system2).execute(); + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, -2); + issueMigration.execute(); fail(); } catch (Exception e) { assertThat(e).isInstanceOf(MessageException.class); diff --git a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java index ba774a21ee5..a94508726b9 100644 --- a/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/technicaldebt/DebtServiceTest.java @@ -59,11 +59,6 @@ public class DebtServiceTest { verify(debtFormatter).format(any(Locale.class), eq(10L)); } - @Test - public void to_technical_debt() { - assertThat(service.toTechnicalDebt("500")).isEqualTo(WorkDuration.createFromValueAndUnit(5, WorkDuration.UNIT.HOURS, HOURS_IN_DAY)); - } - @Test public void to_work_duration() { assertThat(service.toWorkDuration(HOURS_IN_DAY * 60 * 60L)).isEqualTo(WorkDuration.createFromValueAndUnit(1, WorkDuration.UNIT.DAYS, HOURS_IN_DAY)); diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql new file mode 100644 index 00000000000..f3f71cfa229 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/IssueChangelogMigrationTest/schema.sql @@ -0,0 +1,28 @@ +-- 4.3 + +CREATE TABLE "ISSUES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(50) UNIQUE NOT NULL, + "COMPONENT_ID" INTEGER NOT NULL, + "ROOT_COMPONENT_ID" INTEGER, + "RULE_ID" INTEGER, + "SEVERITY" VARCHAR(10), + "MANUAL_SEVERITY" BOOLEAN NOT NULL, + "MESSAGE" VARCHAR(4000), + "LINE" INTEGER, + "EFFORT_TO_FIX" DOUBLE, + "STATUS" VARCHAR(20), + "RESOLUTION" VARCHAR(20), + "CHECKSUM" VARCHAR(1000), + "REPORTER" VARCHAR(40), + "ASSIGNEE" VARCHAR(40), + "AUTHOR_LOGIN" VARCHAR(100), + "ACTION_PLAN_KEY" VARCHAR(50) NULL, + "ISSUE_ATTRIBUTES" VARCHAR(4000), + "ISSUE_CREATION_DATE" TIMESTAMP, + "ISSUE_CLOSE_DATE" TIMESTAMP, + "ISSUE_UPDATE_DATE" TIMESTAMP, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP, + "TECHNICAL_DEBT" INTEGER +); -- 2.39.5