From fb767a2195acfe7dc35196dff7d8bd6090adaa13 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 17 Feb 2015 15:50:23 +0100 Subject: [PATCH] SONAR-6187 Enhance SQALE model with new characteristics --- .../db/migrations/DatabaseMigrations.java | 6 +- ...SubCharacteristicsComplianceMigration.java | 313 ++++++++++++++++++ .../db/migrations/v453/package-info.java | 24 ++ .../com/sonar/sqale/technical-debt-model.xml | 69 ++-- ...haracteristicsComplianceMigrationTest.java | 117 +++++++ .../org/sonar/server/debt/DebtMediumTest.java | 6 +- .../do_nothing_when_already_migrated.xml | 33 ++ ...iance_already_exists_as_characteristic.xml | 7 + ...eady_exists_under_wrong_characteristic.xml | 9 + ...usability_exists_as_sub_characteristic.xml | 7 + ...the_top_if_security_does_exists-result.xml | 22 ++ ...ity_at_the_top_if_security_does_exists.xml | 7 + .../migrate-result.xml | 54 +++ .../migrate.xml | 19 ++ .../schema.sql | 10 + ...ate_usability_if_already_exists-result.xml | 22 ++ .../update_usability_if_already_exists.xml | 10 + ...lity_and_sub_characteristics_compliance.rb | 31 ++ .../core/persistence/DatabaseVersion.java | 2 +- .../org/sonar/core/persistence/rows-h2.sql | 1 + .../api/server/rule/RulesDefinition.java | 55 +++ 21 files changed, 798 insertions(+), 26 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/package-info.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/do_nothing_when_already_migrated.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_as_characteristic.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_under_wrong_characteristic.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_usability_exists_as_sub_characteristic.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/schema.sql create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists-result.xml create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists.xml create mode 100644 server/sonar-web/src/main/webapp/WEB-INF/db/migrate/606_add_characteristic_usability_and_sub_characteristics_compliance.rb diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java index 8bc203035ab..60b84728fee 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java @@ -29,6 +29,7 @@ import org.sonar.server.db.migrations.v451.AddMissingCustomRuleParametersMigrati import org.sonar.server.db.migrations.v45.AddMissingRuleParameterDefaultValuesMigration; import org.sonar.server.db.migrations.v45.DeleteMeasuresOnDeletedProfilesMigration; import org.sonar.server.db.migrations.v451.DeleteUnescapedActivities; +import org.sonar.server.db.migrations.v453.AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration; import java.util.List; @@ -63,7 +64,10 @@ public interface DatabaseMigrations { // 4.5.1 AddMissingCustomRuleParametersMigration.class, - DeleteUnescapedActivities.class + DeleteUnescapedActivities.class, + + // 4.5.3, + AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.class ); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.java new file mode 100644 index 00000000000..3405ff28dce --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.java @@ -0,0 +1,313 @@ +/* + * 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.server.db.migrations.v453; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.utils.System2; +import org.sonar.core.persistence.Database; +import org.sonar.server.db.migrations.BaseDataChange; +import org.sonar.server.db.migrations.Select; +import org.sonar.server.db.migrations.Upsert; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; + +/** + * See http://jira.codehaus.org/browse/SONAR-6187 + * + * Add a new Characteristic 'Usability' with 2 sub-characteristics 'Accessibility' and 'Ease of Use' + * and add a new sub-characteristic 'Compliance' for all characteristics. + * + * @since 4.5.3 + */ +public class AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration extends BaseDataChange { + + private static final Logger LOGGER = LoggerFactory.getLogger(AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration.class); + + private static final String COMPLIANCE_NAME = "Compliance"; + private static final String COMPLIANCE_KEY_SUFFIX = "_COMPLIANCE"; + + private final System2 system; + + public AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration(Database db, System2 system) { + super(db); + this.system = system; + } + + @Override + public void execute(Context context) throws SQLException { + CharacteristicsContext characteristicsContext = new CharacteristicsContext(context, system); + + int usabilityOder = moveCharacteristicsDownToBeAbleToInsertUsability(characteristicsContext); + createOrUpdateUsabilityCharacteristicAndItsSubCharacteristic(characteristicsContext, usabilityOder); + + createSubCharacteristic(characteristicsContext, "REUSABILITY" + COMPLIANCE_KEY_SUFFIX, "Reusability " + COMPLIANCE_NAME, "REUSABILITY"); + createSubCharacteristic(characteristicsContext, "PORTABILITY" + COMPLIANCE_KEY_SUFFIX, "Portability " + COMPLIANCE_NAME, "PORTABILITY"); + createSubCharacteristic(characteristicsContext, "MAINTAINABILITY" + COMPLIANCE_KEY_SUFFIX, "Maintainability " + COMPLIANCE_NAME, "MAINTAINABILITY"); + createSubCharacteristic(characteristicsContext, "SECURITY" + COMPLIANCE_KEY_SUFFIX, "Security " + COMPLIANCE_NAME, "SECURITY"); + createSubCharacteristic(characteristicsContext, "EFFICIENCY" + COMPLIANCE_KEY_SUFFIX, "Efficiency " + COMPLIANCE_NAME, "EFFICIENCY"); + createSubCharacteristic(characteristicsContext, "CHANGEABILITY" + COMPLIANCE_KEY_SUFFIX, "Changeability " + COMPLIANCE_NAME, "CHANGEABILITY"); + createSubCharacteristic(characteristicsContext, "RELIABILITY" + COMPLIANCE_KEY_SUFFIX, "Reliability " + COMPLIANCE_NAME, "RELIABILITY"); + createSubCharacteristic(characteristicsContext, "TESTABILITY" + COMPLIANCE_KEY_SUFFIX, "Testability " + COMPLIANCE_NAME, "TESTABILITY"); + } + + /** + * If the characteristic 'Security' exists, the new characteristic 'Usability' should be inserted just below it, + * so every existing characteristics below Security should move down. + * + * If the characteristic 'Security' does not exists, the new characteristic 'Usability' should be the first one, + * so every existing characteristics should move down. + * + * If the characteristic 'Usability' is already at the right place, nothing will be done. + */ + private int moveCharacteristicsDownToBeAbleToInsertUsability(CharacteristicsContext characteristicsContext) throws SQLException { + Characteristic security = characteristicsContext.findCharacteristicByKey("SECURITY"); + Characteristic usability = characteristicsContext.findCharacteristicByKey("USABILITY"); + + int usabilityOder = 1; + int indexToStart = 0; + if (security != null) { + indexToStart = characteristicsContext.characteristics().indexOf(security) + 1; + usabilityOder = security.getOrder() + 1; + } + + if (usability == null || usability.getOrder() != usabilityOder) { + // Move root characteristics one step lower + for (int i = indexToStart; i < characteristicsContext.characteristics().size(); i++) { + Characteristic characteristic = characteristicsContext.characteristics().get(i); + if (characteristic.getParentId() == null) { + characteristicsContext.updateCharacteristicOrder(characteristic.getKey(), characteristic.getOrder() + 1); + } + } + } + return usabilityOder; + } + + private void createOrUpdateUsabilityCharacteristicAndItsSubCharacteristic(CharacteristicsContext characteristicsContext, int newUsabilityOrder) + throws SQLException { + String usabilityKey = "USABILITY"; + Characteristic usability = characteristicsContext.findCharacteristicByKey(usabilityKey); + if (usability != null) { + if (usability.getOrder() != newUsabilityOrder) { + usability.setOrder(newUsabilityOrder); + characteristicsContext.updateCharacteristicOrder(usability.getKey(), usability.getOrder()); + } + } else { + usability = new Characteristic().setKey(usabilityKey).setName("Usability").setOrder(newUsabilityOrder); + characteristicsContext.insertCharacteristic(usability); + } + + createSubCharacteristic(characteristicsContext, "USABILITY_ACCESSIBILITY", "Accessibility", usabilityKey); + createSubCharacteristic(characteristicsContext, "USABILITY_EASE_OF_USE", "Ease of Use", usabilityKey); + createSubCharacteristic(characteristicsContext, "USABILITY" + COMPLIANCE_KEY_SUFFIX, "Usability " + COMPLIANCE_NAME, usabilityKey); + } + + private void createSubCharacteristic(CharacteristicsContext characteristicsContext, + String subCharacteristicKey, String subCharacteristicName, String parentKey) throws SQLException { + Characteristic parent = characteristicsContext.findCharacteristicByKey(parentKey); + if (parent != null) { + Characteristic subCharacteristic = characteristicsContext.findSubCharacteristicByKey(subCharacteristicKey, parent); + if (subCharacteristic == null) { + characteristicsContext.insertCharacteristic(new Characteristic().setKey(subCharacteristicKey).setName(subCharacteristicName).setParentId(parent.getId())); + } + } + // If the characteristic parent does not exits, the sub-characteristic is not added + } + + private static class Characteristic { + private Integer id; + private String key; + private String name; + private Integer order; + private Integer parentId; + + public Characteristic setId(Integer id) { + this.id = id; + return this; + } + + public Integer getId() { + return id; + } + + public Characteristic setKey(String key) { + this.key = key; + return this; + } + + public String getKey() { + return key; + } + + public Characteristic setName(String name) { + this.name = name; + return this; + } + + public String getName() { + return name; + } + + public Characteristic setOrder(@Nullable Integer order) { + this.order = order; + return this; + } + + @CheckForNull + public Integer getOrder() { + return order; + } + + public Characteristic setParentId(@Nullable Integer parentId) { + this.parentId = parentId; + return this; + } + + @CheckForNull + public Integer getParentId() { + return parentId; + } + } + + private static class CharacteristicsContext { + Context context; + private final System2 system; + Date now; + List characteristics; + + public CharacteristicsContext(Context context, System2 system) throws SQLException { + this.context = context; + this.system = system; + init(); + } + + private void init() throws SQLException { + now = new Date(system.now()); + characteristics = selectEnabledCharacteristics(); + } + + public List characteristics() { + return characteristics; + } + + @CheckForNull + public Characteristic findCharacteristicByKey(final String key) { + Characteristic characteristic = Iterables.find(characteristics, new Predicate() { + @Override + public boolean apply(@Nullable Characteristic input) { + return input != null && input.key.equals(key); + } + }, null); + if (characteristic != null) { + if (characteristic.getParentId() != null) { + throw new IllegalStateException(String.format("'%s' must be a characteristic", characteristic.getName())); + } + } + return characteristic; + } + + @CheckForNull + public Characteristic findSubCharacteristicByKey(final String key, Characteristic parent) { + Characteristic characteristic = Iterables.find(characteristics, new Predicate() { + @Override + public boolean apply(@Nullable Characteristic input) { + return input != null && input.key.equals(key); + } + }, null); + if (characteristic != null) { + Integer parentId = characteristic.getParentId(); + if (parentId == null) { + throw new IllegalStateException(String.format("'%s' must be a sub-characteristic", characteristic.getName())); + } else if (!characteristic.getParentId().equals(parent.getId())) { + throw new IllegalStateException(String.format("'%s' must be defined under '%s'", characteristic.getName(), parent.getName())); + } + } + return characteristic; + } + + private List selectEnabledCharacteristics() throws SQLException { + return context.prepareSelect( + "SELECT c.id, c.kee, c.name, c.characteristic_order, c.parent_id FROM characteristics c WHERE c.enabled=? ORDER BY c.characteristic_order") + .setBoolean(1, true) + .list(new CharacteristicReader()); + } + + private int selectCharacteristicId(String key) throws SQLException { + return context.prepareSelect( + "SELECT c.id FROM characteristics c WHERE c.kee = ? AND c.enabled=?") + .setString(1, key) + .setBoolean(2, true) + .get(Select.LONG_READER).intValue(); + } + + public void insertCharacteristic(Characteristic characteristic) throws SQLException { + if (characteristic.getParentId() == null) { + LOGGER.info("Insert new characteristic '{}'", characteristic.getKey()); + } else { + LOGGER.info("Insert new sub characteristic '{}'", characteristic.getKey()); + } + + context.prepareUpsert("INSERT INTO characteristics (kee, name, parent_id, characteristic_order, enabled, created_at) VALUES (?, ?, ?, ?, ?, ?)") + .setString(1, characteristic.getKey()) + .setString(2, characteristic.getName()) + .setInt(3, characteristic.getParentId()) + .setInt(4, characteristic.getOrder()) + .setBoolean(5, true) + .setDate(6, now) + .execute() + .commit(); + characteristic.setId(selectCharacteristicId(characteristic.getKey())); + + characteristics.add(characteristic); + } + + public void updateCharacteristicOrder(String key, Integer order) throws SQLException { + LOGGER.info("Update characteristic '{}' order to {}", key, order); + + context.prepareUpsert("UPDATE characteristics SET characteristic_order=?, updated_at=? WHERE kee=?") + .setInt(1, order) + .setDate(2, now) + .setString(3, key) + .execute() + .commit(); + } + + private static class CharacteristicReader implements Select.RowReader { + @Override + public Characteristic read(Select.Row row) throws SQLException { + return new Characteristic() + .setId(row.getInt(1)) + .setKey(row.getString(2)) + .setName(row.getString(3)) + .setOrder(row.getInt(4)) + .setParentId(row.getInt(5)); + } + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/package-info.java new file mode 100644 index 00000000000..1093a42c108 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v453/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@ParametersAreNonnullByDefault +package org.sonar.server.db.migrations.v453; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/resources/com/sonar/sqale/technical-debt-model.xml b/server/sonar-server/src/main/resources/com/sonar/sqale/technical-debt-model.xml index d2276e82e5d..4e3277a44b6 100644 --- a/server/sonar-server/src/main/resources/com/sonar/sqale/technical-debt-model.xml +++ b/server/sonar-server/src/main/resources/com/sonar/sqale/technical-debt-model.xml @@ -1,24 +1,3 @@ - REUSABILITY @@ -27,6 +6,10 @@ MODULARITY Modularity + + REUSABILITY_COMPLIANCE + Reusability Compliance + TRANSPORTABILITY Transportability @@ -51,6 +34,10 @@ OS_RELATED_PORTABILITY OS + + PORTABILITY_COMPLIANCE + Portability Compliance + SOFTWARE_RELATED_PORTABILITY Software @@ -63,6 +50,10 @@ MAINTAINABILITY Maintainability + + MAINTAINABILITY_COMPLIANCE + Maintainability Compliance + READABILITY Readability @@ -87,11 +78,31 @@ INPUT_VALIDATION_AND_REPRESENTATION Input validation and representation + + SECURITY_COMPLIANCE + Security Compliance + SECURITY_FEATURES Security features + + USABILITY + Usability + + USABILITY_ACCESSIBILITY + Accessibility + + + USABILITY_EASE_OF_USE + Ease of Use + + + USABILITY_COMPLIANCE + Usability Compliance + + EFFICIENCY Efficiency @@ -99,6 +110,10 @@ CPU_EFFICIENCY Processor use + + EFFICIENCY_COMPLIANCE + Efficiency Compliance + MEMORY_EFFICIENCY Memory use @@ -115,6 +130,10 @@ ARCHITECTURE_CHANGEABILITY Architecture + + CHANGEABILITY_COMPLIANCE + Changeability Compliance + DATA_CHANGEABILITY Data @@ -151,6 +170,10 @@ LOGIC_RELIABILITY Logic + + RELIABILITY_COMPLIANCE + Reliability Compliance + RESOURCE_RELIABILITY Resource @@ -171,6 +194,10 @@ INTEGRATION_TESTABILITY Integration level + + TESTABILITY_COMPLIANCE + Testability Compliance + UNIT_TESTABILITY Unit level diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest.java new file mode 100644 index 00000000000..d233b4a775f --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest.java @@ -0,0 +1,117 @@ +/* + * 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.server.db.migrations.v453; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.System2; +import org.sonar.core.persistence.TestDatabase; +import org.sonar.server.db.migrations.DatabaseMigration; + +import static junit.framework.TestCase.fail; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest { + + @ClassRule + public static TestDatabase db = new TestDatabase().schema(AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest.class, "schema.sql"); + + DatabaseMigration migration; + + System2 system = mock(System2.class); + + @Before + public void setUp() throws Exception { + db.executeUpdateSql("truncate table characteristics"); + + when(system.now()).thenReturn(DateUtils.parseDate("2015-02-15").getTime()); + + migration = new AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration(db.database(), system); + } + + @Test + public void migrate() throws Exception { + db.prepareDbUnit(getClass(), "migrate.xml"); + migration.execute(); + db.assertDbUnit(getClass(), "migrate-result.xml", "characteristics"); + } + + @Test + public void do_nothing_when_already_migrated() throws Exception { + db.prepareDbUnit(getClass(), "do_nothing_when_already_migrated.xml"); + migration.execute(); + db.assertDbUnit(getClass(), "do_nothing_when_already_migrated.xml", "characteristics"); + } + + @Test + public void insert_usability_at_the_top_if_security_does_exists() throws Exception { + db.prepareDbUnit(getClass(), "insert_usability_at_the_top_if_security_does_exists.xml"); + migration.execute(); + db.assertDbUnit(getClass(), "insert_usability_at_the_top_if_security_does_exists-result.xml", "characteristics"); + } + + @Test + public void update_usability_order_if_already_exists() throws Exception { + db.prepareDbUnit(getClass(), "update_usability_if_already_exists.xml"); + migration.execute(); + db.assertDbUnit(getClass(), "update_usability_if_already_exists-result.xml", "characteristics"); + } + + @Test + public void fail_if_usability_exists_as_sub_characteristic() throws Exception { + db.prepareDbUnit(getClass(), "fail_if_usability_exists_as_sub_characteristic.xml"); + + try { + migration.execute(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("'Usability' must be a characteristic"); + } + } + + @Test + public void fail_if_compliance_already_exists_as_characteristic() throws Exception { + db.prepareDbUnit(getClass(), "fail_if_compliance_already_exists_as_characteristic.xml"); + + try { + migration.execute(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("'Compliance' must be a sub-characteristic"); + } + } + + @Test + public void fail_if_compliance_already_exists_under_wrong_characteristic() throws Exception { + db.prepareDbUnit(getClass(), "fail_if_compliance_already_exists_under_wrong_characteristic.xml"); + + try { + migration.execute(); + fail(); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("'Reusability Compliance' must be defined under 'Reusability'"); + } + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/debt/DebtMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/debt/DebtMediumTest.java index 6a4434ea5ef..06b87b1f43a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/debt/DebtMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/debt/DebtMediumTest.java @@ -44,14 +44,14 @@ public class DebtMediumTest { } @Test - public void find_characteristics() throws Exception { + public void find_default_characteristics() throws Exception { DebtModelService debtModelService = serverTester.get(DebtModelService.class); // Only root characteristics - assertThat(debtModelService.characteristics()).hasSize(8); + assertThat(debtModelService.characteristics()).hasSize(9); // Characteristics and sub-characteristics - assertThat(debtModelService.allCharacteristics()).hasSize(39); + assertThat(debtModelService.allCharacteristics()).hasSize(51); } @Test diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/do_nothing_when_already_migrated.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/do_nothing_when_already_migrated.xml new file mode 100644 index 00000000000..684c4d4abc0 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/do_nothing_when_already_migrated.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_as_characteristic.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_as_characteristic.xml new file mode 100644 index 00000000000..337697d4bae --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_as_characteristic.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_under_wrong_characteristic.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_under_wrong_characteristic.xml new file mode 100644 index 00000000000..a74b887e3b3 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_compliance_already_exists_under_wrong_characteristic.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_usability_exists_as_sub_characteristic.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_usability_exists_as_sub_characteristic.xml new file mode 100644 index 00000000000..18cb033a7eb --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/fail_if_usability_exists_as_sub_characteristic.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists-result.xml new file mode 100644 index 00000000000..0de66a6749d --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists-result.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists.xml new file mode 100644 index 00000000000..1ce991c6bff --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/insert_usability_at_the_top_if_security_does_exists.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate-result.xml new file mode 100644 index 00000000000..f0646db4c69 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate-result.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate.xml new file mode 100644 index 00000000000..b10cbbfadbe --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/migrate.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/schema.sql b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/schema.sql new file mode 100644 index 00000000000..9afaa00825b --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE "CHARACTERISTICS" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "KEE" VARCHAR(100), + "NAME" VARCHAR(100), + "PARENT_ID" INTEGER, + "CHARACTERISTIC_ORDER" INTEGER, + "ENABLED" BOOLEAN, + "CREATED_AT" TIMESTAMP, + "UPDATED_AT" TIMESTAMP +); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists-result.xml new file mode 100644 index 00000000000..c03ad0246df --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists-result.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists.xml new file mode 100644 index 00000000000..05303878913 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v453/AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigrationTest/update_usability_if_already_exists.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/606_add_characteristic_usability_and_sub_characteristics_compliance.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/606_add_characteristic_usability_and_sub_characteristics_compliance.rb new file mode 100644 index 00000000000..64bdac9a884 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/606_add_characteristic_usability_and_sub_characteristics_compliance.rb @@ -0,0 +1,31 @@ +# +# 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. +# + +# +# SonarQube 4.5.3 +# SONAR-6187 +# +class AddCharacteristicUsabilityAndSubCharacteristicsCompliance < ActiveRecord::Migration + + def self.up + execute_java_migration 'org.sonar.server.db.migrations.v453.AddCharacteristicUsabilityAndSubCharacteristicsComplianceMigration' + end + +end diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index 2b7f67bf040..f70b35baf10 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -33,7 +33,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 605; + public static final int LAST_VERSION = 606; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index 57093c0eb70..1ed44d1c26e 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -259,6 +259,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('601'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('603'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('604'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('605'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('606'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java index 75a5a2bf077..51759251272 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java @@ -293,6 +293,61 @@ public interface RulesDefinition extends ServerExtension { */ public static final String UNIT_TESTABILITY = "UNIT_TESTABILITY"; + /** + * Related to characteristic ACCESSIBILITY + */ + public static final String USABILITY_ACCESSIBILITY = "USABILITY_ACCESSIBILITY"; + + /** + * Related to characteristic ACCESSIBILITY + */ + public static final String USABILITY_COMPLIANCE = "USABILITY_COMPLIANCE"; + + /** + * Related to characteristic ACCESSIBILITY + */ + public static final String USABILITY_EASE_OF_USE = "USABILITY_EASE_OF_USE"; + + /** + * Related to characteristic REUSABILITY + */ + public static final String REUSABILITY_COMPLIANCE = "REUSABILITY_COMPLIANCE"; + + /** + * Related to characteristic PORTABILITY + */ + public static final String PORTABILITY_COMPLIANCE = "PORTABILITY_COMPLIANCE"; + + /** + * Related to characteristic MAINTAINABILITY + */ + public static final String MAINTAINABILITY_COMPLIANCE = "MAINTAINABILITY_COMPLIANCE"; + + /** + * Related to characteristic SECURITY + */ + public static final String SECURITY_COMPLIANCE = "SECURITY_COMPLIANCE"; + + /** + * Related to characteristic EFFICIENCY + */ + public static final String EFFICIENCY_COMPLIANCE = "EFFICIENCY_COMPLIANCE"; + + /** + * Related to characteristic CHANGEABILITY + */ + public static final String CHANGEABILITY_COMPLIANCE = "CHANGEABILITY_COMPLIANCE"; + + /** + * Related to characteristic RELIABILITY + */ + public static final String RELIABILITY_COMPLIANCE = "RELIABILITY_COMPLIANCE"; + + /** + * Related to characteristic TESTABILITY + */ + public static final String TESTABILITY_COMPLIANCE = "TESTABILITY_COMPLIANCE"; + private SubCharacteristics() { // only constants } -- 2.39.5