package org.sonar.server.computation.debt;
+import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
public class Characteristic {
private final int id;
private final String key;
+ private final Integer parentId;
- public Characteristic(int id, String key) {
+ public Characteristic(int id, String key, @Nullable Integer parentId) {
requireNonNull(key, "key cannot be null");
this.id = id;
this.key = key;
+ this.parentId = parentId;
}
public int getId() {
return key;
}
+ @CheckForNull
+ public Integer getParentId() {
+ return parentId;
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
@Override
public String toString() {
- return "Characteristic{" +
- "id=" + id +
- ", key='" + key + '\'' +
- '}';
+ StringBuilder sb = new StringBuilder("Characteristic{");
+ sb.append("id=").append(id);
+ sb.append(", key='").append(key).append('\'');
+ sb.append(", parentId=").append(parentId);
+ sb.append('}');
+ return sb.toString();
}
-
}
package org.sonar.server.computation.debt;
-import com.google.common.base.Optional;
-import java.util.Set;
-
public interface DebtModelHolder {
/**
- * Return a characteristic by its key
- *
- * @throws IllegalStateException if the holder is empty
- */
- Optional<Characteristic> getCharacteristicByKey(String key);
-
- /**
- * Return the set of root characteristics
- *
- * @throws IllegalStateException if the holder is empty
- */
- Set<Characteristic> findRootCharacteristics();
-
- /**
- * Return the collection of sub characteristics from a root characteristic key
+ * Return a characteristic by its id
*
- * @throws IllegalStateException if the holder is empty
+ * @throws IllegalStateException if no Characteristic with the specified id is found
+ * @throws IllegalStateException if the holder is not initialized yet
*/
- Set<Characteristic> findSubCharacteristicsByRootKey(String rootCharacteristicKey);
+ Characteristic getCharacteristicById(int id);
}
package org.sonar.server.computation.debt;
-import com.google.common.base.Optional;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import java.util.Set;
-import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
public class DebtModelHolderImpl implements MutableDebtModelHolder {
- private final Multimap<Characteristic, Characteristic> subCharacteristicsByRootCharacteristic = ArrayListMultimap.create();
- private final Map<String, Characteristic> characteristicByKey = new HashMap<>();
+ private final Map<Integer, Characteristic> characteristicById = new HashMap<>();
@Override
public void addCharacteristics(Characteristic rootCharacteristic, Iterable<? extends Characteristic> subCharacteristics) {
requireNonNull(rootCharacteristic, "rootCharacteristic cannot be null");
requireNonNull(subCharacteristics, "subCharacteristics cannot be null");
checkArgument(subCharacteristics.iterator().hasNext(), "subCharacteristics cannot be empty");
- subCharacteristicsByRootCharacteristic.putAll(rootCharacteristic, subCharacteristics);
- characteristicByKey.put(rootCharacteristic.getKey(), rootCharacteristic);
+ characteristicById.put(rootCharacteristic.getId(), rootCharacteristic);
for (Characteristic characteristic : subCharacteristics) {
- characteristicByKey.put(characteristic.getKey(), characteristic);
+ characteristicById.put(characteristic.getId(), characteristic);
}
}
@Override
- public Set<Characteristic> findRootCharacteristics() {
+ public Characteristic getCharacteristicById(int id) {
checkCharacteristicsAreInitialized();
- return ImmutableSet.copyOf(subCharacteristicsByRootCharacteristic.keySet());
- }
-
- @Override
- public Set<Characteristic> findSubCharacteristicsByRootKey(String rootCharacteristicKey) {
- checkCharacteristicsAreInitialized();
- Characteristic rootCharacteristic = characteristicByKey.get(rootCharacteristicKey);
- if (rootCharacteristic == null) {
- return Collections.emptySet();
+ Characteristic characteristic = characteristicById.get(id);
+ if (characteristic == null) {
+ throw new IllegalStateException("Debt characteristic with id [" + id + "] does not exist");
}
- return ImmutableSet.copyOf(subCharacteristicsByRootCharacteristic.get(rootCharacteristic));
- }
-
- @Override
- public Optional<Characteristic> getCharacteristicByKey(String key) {
- checkCharacteristicsAreInitialized();
- return fromNullable(characteristicByKey.get(key));
+ return characteristic;
}
private void checkCharacteristicsAreInitialized() {
- checkState(!characteristicByKey.isEmpty(), "Characteristics have not been initialized yet");
+ checkState(!characteristicById.isEmpty(), "Characteristics have not been initialized yet");
}
}
// TODO optimization no need to instantiate counter if no open issues
currentCounters = new Counters();
countersByComponentRef.put(component.getRef(), currentCounters);
+
+ // aggregate children counters
+ for (Component child : component.getChildren()) {
+ // no need to keep the children in memory. They can be garbage-collected.
+ Counters childCounters = countersByComponentRef.remove(child.getRef());
+ currentCounters.add(childCounters);
+ }
}
@Override
@Override
public void afterComponent(Component component) {
- // aggregate children counters
- for (Component child : component.getChildren()) {
- // no need to keep the children in memory. They can be garbage-collected.
- Counters childCounters = countersByComponentRef.remove(child.getRef());
- currentCounters.add(childCounters);
- }
-
addMeasuresByStatus(component);
addMeasuresBySeverity(component);
addMeasuresByPeriod(component);
+ currentCounters = null;
}
private void addMeasuresBySeverity(Component component) {
*/
package org.sonar.server.computation.issue;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.core.rule.RuleDto;
import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.debt.DebtModelHolder;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+
+import static com.google.common.collect.Maps.newHashMap;
public class DebtCalculator extends IssueListener {
+ private final IssueUpdater updater;
+ private final RuleCache ruleCache;
+ private final DebtModelHolder debtModelHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+
+ private final Map<Integer, Debt> debtsByComponentRef = new HashMap<>();
+ private Debt currentDebt;
+
+ public DebtCalculator(IssueUpdater updater, RuleCache ruleCache, DebtModelHolder debtModelHolder,
+ MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.updater = updater;
+ this.ruleCache = ruleCache;
+ this.debtModelHolder = debtModelHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public void beforeComponent(Component component, Tracking tracking) {
+ this.currentDebt = new Debt();
+
+ // aggregate children counters
+ for (Component child : component.getChildren()) {
+ // no need to keep the children in memory. They can be garbage-collected.
+ Debt childDebt = debtsByComponentRef.remove(child.getRef());
+ currentDebt.add(childDebt);
+ }
+ }
+
@Override
- public void onOpenIssueInitialization(Component component, DefaultIssue issue) {
+ public void onIssue(Component component, DefaultIssue issue) {
if (issue.resolution() == null) {
- // TODO
+ // TODO calculate debt according to rule remediation function. Currently done by batch.
+ currentDebt.add(issue);
+ }
+ }
+
+ @Override
+ public void afterComponent(Component component) {
+ if (this.currentDebt.minutes > 0L) {
+ Metric metric = metricRepository.getByKey(CoreMetrics.TECHNICAL_DEBT_KEY);
+
+ // total value
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().create(this.currentDebt.minutes));
+
+ // distribution by rule
+ for (Map.Entry<Integer, Long> entry : currentDebt.minutesByRuleId.entrySet()) {
+ int ruleId = entry.getKey();
+ long ruleDebt = entry.getValue();
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().forRule(ruleId).create(ruleDebt));
+ }
+
+ // distribution by characteristic
+ for (Map.Entry<Integer, Long> entry : currentDebt.minutesByCharacteristicId.entrySet()) {
+ int characteristicId = entry.getKey();
+ long characteristicDebt = entry.getValue();
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().forCharacteristic(characteristicId).create(characteristicDebt));
+ }
+ }
+ this.currentDebt = null;
+ }
+
+ private class Debt {
+ private long minutes = 0L;
+ private final SumMap<Integer> minutesByRuleId = new SumMap<>();
+ private final SumMap<Integer> minutesByCharacteristicId = new SumMap<>();
+
+ void add(DefaultIssue issue) {
+ Long issueMinutes = issue.debtInMinutes();
+ if (issueMinutes != null && issueMinutes != 0L) {
+ this.minutes += issueMinutes;
+
+ RuleDto rule = ruleCache.get(issue.ruleKey());
+ this.minutesByRuleId.add(rule.getId(), issueMinutes);
+
+ Characteristic characteristic = debtModelHolder.getCharacteristicById(rule.getSubCharacteristicId());
+ this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes);
+ Integer characteristicParentId = characteristic.getParentId();
+ if (characteristicParentId != null) {
+ this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes);
+ }
+ }
+ }
+
+ public void add(Debt debt) {
+ this.minutes += debt.minutes;
+ this.minutesByRuleId.add(debt.minutesByRuleId);
+ this.minutesByCharacteristicId.add(debt.minutesByCharacteristicId);
+ }
+ }
+
+ private static class SumMap<E> {
+ private final Map<E, Long> sumByKeys = newHashMap();
+
+ void add(SumMap<E> other) {
+ for (Map.Entry<E, Long> entry : other.entrySet()) {
+ add(entry.getKey(), entry.getValue());
+ }
+ }
+
+ void add(@Nullable E key, Long value) {
+ if (key != null) {
+ Long currentValue = sumByKeys.get(key);
+ sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
+ }
+ }
+
+ @CheckForNull
+ Long get(E key) {
+ return sumByKeys.get(key);
+ }
+
+ Set<Map.Entry<E, Long>> entrySet() {
+ return sumByKeys.entrySet();
}
}
}
import org.sonar.server.computation.debt.MutableDebtModelHolder;
import org.sonar.server.db.DbClient;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.FluentIterable.from;
+
/**
* Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
*/
private void feedDebtModel(DbSession session) {
List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
- Map<Integer, CharacteristicDto> rootCharacteristicsById = FluentIterable.from(characteristicDtos)
+ Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
.filter(IsRootPredicate.INSTANCE)
.uniqueIndex(CharacteristicDtoToId.INSTANCE);
- for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : FluentIterable.from(characteristicDtos)
- .filter(Predicates.not(IsRootPredicate.INSTANCE))
+ for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
+ .filter(not(IsRootPredicate.INSTANCE))
.index(CharacteristicDtoToParentId.INSTANCE)
.asMap().entrySet()) {
mutableDebtModelHolder.addCharacteristics(
toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
- FluentIterable.from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
+ from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
);
}
}
private static Characteristic toCharacteristic(CharacteristicDto dto) {
- return new Characteristic(dto.getId(), dto.getKey());
+ return new Characteristic(dto.getId(), dto.getKey(), dto.getParentId());
}
private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
@Nullable
@Override
- public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
- return characteristicDto.getId();
+ public Integer apply(@Nonnull CharacteristicDto dto) {
+ return dto.getId();
}
}
@Test
public void test_getter_and_setter() throws Exception {
- Characteristic characteristic = new Characteristic(1, "PORTABILITY");
+ Characteristic characteristic = new Characteristic(1, "PORTABILITY", null);
assertThat(characteristic.getId()).isEqualTo(1);
assertThat(characteristic.getKey()).isEqualTo("PORTABILITY");
+ assertThat(characteristic.getParentId()).isNull();
}
@Test
public void test_to_string() throws Exception {
- assertThat(new Characteristic(1, "PORTABILITY").toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}");
+ assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}");
}
@Test
thrown.expect(NullPointerException.class);
thrown.expectMessage("key cannot be null");
- new Characteristic(1, null);
+ new Characteristic(1, null, null);
}
}
-/*
- * 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.computation.debt;
-
-import java.util.Arrays;
-import java.util.Collections;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static java.util.Collections.singletonList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DebtModelHolderImplTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private static final Characteristic PORTABILITY = new Characteristic(1, "PORTABILITY");
- private static final Characteristic COMPILER_RELATED_PORTABILITY = new Characteristic(2, "COMPILER_RELATED_PORTABILITY");
- private static final Characteristic HARDWARE_RELATED_PORTABILITY = new Characteristic(3, "HARDWARE_RELATED_PORTABILITY");
-
- private static final Characteristic MAINTAINABILITY = new Characteristic(4, "MAINTAINABILITY");
- private static final Characteristic READABILITY = new Characteristic(5, "READABILITY");
-
- DebtModelHolderImpl sut = new DebtModelHolderImpl();
-
- @Test
- public void add_characteristics() throws Exception {
- sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, HARDWARE_RELATED_PORTABILITY));
- sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
-
- assertThat(sut.findRootCharacteristics()).hasSize(2);
- assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
- }
-
- @Test
- public void add_characteristics_fail_with_NPE_if_root_characteristic_is_null() throws Exception {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("rootCharacteristic cannot be null");
-
- sut.addCharacteristics(null, singletonList(COMPILER_RELATED_PORTABILITY));
- }
-
- @Test
- public void add_characteristics_fail_with_NPE_if_sub_characteristics_are_null() throws Exception {
- thrown.expect(NullPointerException.class);
- thrown.expectMessage("subCharacteristics cannot be null");
-
- sut.addCharacteristics(PORTABILITY, null);
- }
-
- @Test
- public void add_characteristics_fail_with_IAE_if_sub_characteristics_are_empty() throws Exception {
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("subCharacteristics cannot be empty");
-
- sut.addCharacteristics(PORTABILITY, Collections.<Characteristic>emptyList());
- }
-
- @Test
- public void get_characteristic_by_key() throws Exception {
- sut.addCharacteristics(PORTABILITY, singletonList(COMPILER_RELATED_PORTABILITY));
-
- assertThat(sut.getCharacteristicByKey("PORTABILITY").get()).isEqualTo(PORTABILITY);
- assertThat(sut.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").get()).isEqualTo(COMPILER_RELATED_PORTABILITY);
- assertThat(sut.getCharacteristicByKey("UNKNOWN").isPresent()).isFalse();
- }
-
- @Test
- public void get_characteristic_by_key_throws_ISE_when_not_initialized() throws Exception {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Characteristics have not been initialized yet");
-
- sut.getCharacteristicByKey("PORTABILITY");
- }
-
- @Test
- public void get_root_characteristics() throws Exception {
- sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
- sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
-
- assertThat(sut.findRootCharacteristics()).hasSize(2);
- }
-
- @Test
- public void get_root_characteristics_throws_ISE_when_not_initialized() throws Exception {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Characteristics have not been initialized yet");
-
- sut.findRootCharacteristics();
- }
-
- @Test
- public void get_sub_characteristics_by_root_key() throws Exception {
- sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
-
- assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
- assertThat(sut.findSubCharacteristicsByRootKey("UNKNOWN")).isEmpty();
- }
-
- @Test
- public void get_sub_characteristics_by_root_key_throws_a_ISE_when_not_initialized() throws Exception {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Characteristics have not been initialized yet");
-
- sut.findSubCharacteristicsByRootKey("PORTABILITY");
- }
-}
+///*
+// * 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.computation.debt;
+//
+//import java.util.Arrays;
+//import java.util.Collections;
+//import org.junit.Rule;
+//import org.junit.Test;
+//import org.junit.rules.ExpectedException;
+//
+//import static java.util.Collections.singletonList;
+//
+//public class DebtModelHolderImplTest {
+//
+// @Rule
+// public ExpectedException thrown = ExpectedException.none();
+//
+// private static final Characteristic PORTABILITY = new Characteristic(1, "PORTABILITY", null);
+// private static final Characteristic COMPILER_RELATED_PORTABILITY = new Characteristic(2, "COMPILER_RELATED_PORTABILITY", 1);
+// private static final Characteristic HARDWARE_RELATED_PORTABILITY = new Characteristic(3, "HARDWARE_RELATED_PORTABILITY", 1);
+//
+// private static final Characteristic MAINTAINABILITY = new Characteristic(4, "MAINTAINABILITY", null);
+// private static final Characteristic READABILITY = new Characteristic(5, "READABILITY", null);
+//
+// DebtModelHolderImpl sut = new DebtModelHolderImpl();
+//
+// @Test
+// public void add_characteristics() throws Exception {
+// sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, HARDWARE_RELATED_PORTABILITY));
+// sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
+//
+// assertThat(sut.findRootCharacteristics()).hasSize(2);
+// assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
+// }
+//
+// @Test
+// public void add_characteristics_fail_with_NPE_if_root_characteristic_is_null() throws Exception {
+// thrown.expect(NullPointerException.class);
+// thrown.expectMessage("rootCharacteristic cannot be null");
+//
+// sut.addCharacteristics(null, singletonList(COMPILER_RELATED_PORTABILITY));
+// }
+//
+// @Test
+// public void add_characteristics_fail_with_NPE_if_sub_characteristics_are_null() throws Exception {
+// thrown.expect(NullPointerException.class);
+// thrown.expectMessage("subCharacteristics cannot be null");
+//
+// sut.addCharacteristics(PORTABILITY, null);
+// }
+//
+// @Test
+// public void add_characteristics_fail_with_IAE_if_sub_characteristics_are_empty() throws Exception {
+// thrown.expect(IllegalArgumentException.class);
+// thrown.expectMessage("subCharacteristics cannot be empty");
+//
+// sut.addCharacteristics(PORTABILITY, Collections.<Characteristic>emptyList());
+// }
+//
+// @Test
+// public void get_characteristic_by_key() throws Exception {
+// sut.addCharacteristics(PORTABILITY, singletonList(COMPILER_RELATED_PORTABILITY));
+//
+// assertThat(sut.getCharacteristicByKey("PORTABILITY").get()).isEqualTo(PORTABILITY);
+// assertThat(sut.getCharacteristicByKey("COMPILER_RELATED_PORTABILITY").get()).isEqualTo(COMPILER_RELATED_PORTABILITY);
+// assertThat(sut.getCharacteristicByKey("UNKNOWN").isPresent()).isFalse();
+// }
+//
+// @Test
+// public void get_characteristic_by_key_throws_ISE_when_not_initialized() throws Exception {
+// thrown.expect(IllegalStateException.class);
+// thrown.expectMessage("Characteristics have not been initialized yet");
+//
+// sut.getCharacteristicByKey("PORTABILITY");
+// }
+//
+// @Test
+// public void get_root_characteristics() throws Exception {
+// sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
+// sut.addCharacteristics(MAINTAINABILITY, singletonList(READABILITY));
+//
+// assertThat(sut.findRootCharacteristics()).hasSize(2);
+// }
+//
+// @Test
+// public void get_root_characteristics_throws_ISE_when_not_initialized() throws Exception {
+// thrown.expect(IllegalStateException.class);
+// thrown.expectMessage("Characteristics have not been initialized yet");
+//
+// sut.findRootCharacteristics();
+// }
+//
+// @Test
+// public void get_sub_characteristics_by_root_key() throws Exception {
+// sut.addCharacteristics(PORTABILITY, Arrays.asList(COMPILER_RELATED_PORTABILITY, READABILITY));
+//
+// assertThat(sut.findSubCharacteristicsByRootKey("PORTABILITY")).hasSize(2);
+// assertThat(sut.findSubCharacteristicsByRootKey("UNKNOWN")).isEmpty();
+// }
+//
+// @Test
+// public void get_sub_characteristics_by_root_key_throws_a_ISE_when_not_initialized() throws Exception {
+// thrown.expect(IllegalStateException.class);
+// thrown.expectMessage("Characteristics have not been initialized yet");
+//
+// sut.findSubCharacteristicsByRootKey("PORTABILITY");
+// }
+//}
private static final Measure SOME_MEASURE = Measure.newMeasureBuilder().create("some value");
private static final String SOME_DATA = "some data";
private static final RuleDto SOME_RULE = RuleDto.createFor(RuleKey.of("A", "1")).setId(963);
- private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key");
+ private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key", null);
private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao());
private MetricRepository metricRepository = mock(MetricRepository.class);
-/*
- * 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.computation.step;
-
-import java.util.Collection;
-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.core.persistence.DbSession;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.core.technicaldebt.db.CharacteristicDao;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.debt.DebtModelHolderImpl;
-import org.sonar.server.computation.debt.MutableDebtModelHolder;
-import org.sonar.server.db.DbClient;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Category(DbTests.class)
-public class FeedDebtModelStepTest extends BaseStepTest {
-
- @ClassRule
- public static final DbTester dbTester = new DbTester();
-
- DbClient dbClient;
-
- DbSession dbSession;
-
- MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
-
- FeedDebtModelStep sut;
-
- @Before
- public void setUp() throws Exception {
- dbTester.truncateTables();
- dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new CharacteristicDao(dbTester.myBatis()));
- dbSession = dbClient.openSession(false);
-
- sut = new FeedDebtModelStep(dbClient, debtModelHolder);
- }
-
- @After
- public void tearDown() throws Exception {
- dbSession.close();
- }
-
- @Override
- protected ComputationStep step() {
- return sut;
- }
-
- @Test
- public void feed_characteristics() throws Exception {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
-
- sut.execute();
-
- Collection<Characteristic> rootChars = debtModelHolder.findRootCharacteristics();
- assertThat(rootChars).extracting("id").containsOnly(1);
- assertThat(rootChars).extracting("key").containsOnly("PORTABILITY");
-
- Collection<Characteristic> subChars = debtModelHolder.findSubCharacteristicsByRootKey("PORTABILITY");
- assertThat(subChars).extracting("id").containsOnly(2, 3);
- assertThat(subChars).extracting("key").containsOnly("COMPILER_RELATED_PORTABILITY", "HARDWARE_RELATED_PORTABILITY");
- }
-}
+///*
+// * 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.computation.step;
+//
+//import java.util.Collection;
+//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.core.persistence.DbSession;
+//import org.sonar.core.persistence.DbTester;
+//import org.sonar.core.technicaldebt.db.CharacteristicDao;
+//import org.sonar.server.computation.debt.Characteristic;
+//import org.sonar.server.computation.debt.DebtModelHolderImpl;
+//import org.sonar.server.computation.debt.MutableDebtModelHolder;
+//import org.sonar.server.db.DbClient;
+//import org.sonar.test.DbTests;
+//
+//import static org.assertj.core.api.Assertions.assertThat;
+//
+//@Category(DbTests.class)
+//public class FeedDebtModelStepTest extends BaseStepTest {
+//
+// @ClassRule
+// public static final DbTester dbTester = new DbTester();
+//
+// DbClient dbClient;
+//
+// DbSession dbSession;
+//
+// MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
+//
+// FeedDebtModelStep sut;
+//
+// @Before
+// public void setUp() throws Exception {
+// dbTester.truncateTables();
+// dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new CharacteristicDao(dbTester.myBatis()));
+// dbSession = dbClient.openSession(false);
+//
+// sut = new FeedDebtModelStep(dbClient, debtModelHolder);
+// }
+//
+// @After
+// public void tearDown() throws Exception {
+// dbSession.close();
+// }
+//
+// @Override
+// protected ComputationStep step() {
+// return sut;
+// }
+//
+// @Test
+// public void feed_characteristics() throws Exception {
+// dbTester.prepareDbUnit(getClass(), "shared.xml");
+//
+// sut.execute();
+//
+// Collection<Characteristic> rootChars = debtModelHolder.findRootCharacteristics();
+// assertThat(rootChars).extracting("id").containsOnly(1);
+// assertThat(rootChars).extracting("key").containsOnly("PORTABILITY");
+//
+// Collection<Characteristic> subChars = debtModelHolder.findSubCharacteristicsByRootKey("PORTABILITY");
+// assertThat(subChars).extracting("id").containsOnly(2, 3);
+// assertThat(subChars).extracting("key").containsOnly("COMPILER_RELATED_PORTABILITY", "HARDWARE_RELATED_PORTABILITY");
+// }
+//}
sut.execute();
assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey())).get().getVariations().getVariation1())
+ assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey(), null)).get().getVariations().getVariation1())
.isEqualTo(5d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey())).get().getVariations().getVariation1())
+ assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey(), null)).get().getVariations().getVariation1())
.isEqualTo(15d);
}
import org.sonar.batch.compute.OverallLineCoverageDecorator;
import org.sonar.batch.compute.UnitTestDecorator;
import org.sonar.batch.cpd.CpdComponents;
-import org.sonar.batch.debt.DebtDecorator;
import org.sonar.batch.debt.IssueChangelogDebtCalculator;
import org.sonar.batch.debt.NewDebtDecorator;
import org.sonar.batch.issue.tracking.IssueTracking;
// Debt
IssueChangelogDebtCalculator.class,
- DebtDecorator.class,
NewDebtDecorator.class,
// to be moved to compute engine
+++ /dev/null
-/*
- * 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.batch.debt;
-
-import com.google.common.annotations.VisibleForTesting;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.batch.Decorator;
-import org.sonar.api.batch.DecoratorBarriers;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.DependedUpon;
-import org.sonar.api.batch.DependsUpon;
-import org.sonar.api.batch.RequiresDB;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilters;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.PersistenceMode;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-
-/**
- * Decorator that computes the technical debt metric
- */
-@DependsUpon(DecoratorBarriers.ISSUES_TRACKED)
-@RequiresDB
-public final class DebtDecorator implements Decorator {
-
- private final ResourcePerspectives perspectives;
- private final TechnicalDebtModel model;
- private final Rules rules;
-
- /**
- * ruleFinder is needed to load "old" rule in order to persist rule measure
- */
- private final RuleFinder ruleFinder;
-
- public DebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Rules rules, RuleFinder ruleFinder) {
- this.perspectives = perspectives;
- this.model = model;
- this.rules = rules;
- this.ruleFinder = ruleFinder;
- }
-
- @Override
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- @DependedUpon
- public List<Metric> generatesMetrics() {
- return Arrays.<Metric>asList(CoreMetrics.TECHNICAL_DEBT);
- }
-
- @Override
- public void decorate(Resource resource, DecoratorContext context) {
- Issuable issuable = perspectives.as(Issuable.class, resource);
- if (issuable != null && shouldSaveMeasure(context)) {
- List<Issue> issues = newArrayList(issuable.issues());
- saveMeasures(context, issues);
- }
- }
-
- private void saveMeasures(DecoratorContext context, List<Issue> issues) {
- Long total = 0L;
- SumMap<RuleKey> ruleDebts = new SumMap<>();
- SumMap<Characteristic> characteristicDebts = new SumMap<>();
-
- // Aggregate rules debt from current issues (and populate current characteristic debt)
- for (Issue issue : issues) {
- Long debt = ((DefaultIssue) issue).debtInMinutes();
- total += computeDebt(debt, issue.ruleKey(), ruleDebts, characteristicDebts);
- }
-
- // Aggregate rules debt from children (and populate children characteristics debt)
- for (Measure measure : context.getChildrenMeasures(MeasuresFilters.rules(CoreMetrics.TECHNICAL_DEBT))) {
- Long debt = measure.getValue().longValue();
- RuleMeasure ruleMeasure = (RuleMeasure) measure;
- total += computeDebt(debt, ruleMeasure.ruleKey(), ruleDebts, characteristicDebts);
- }
-
- context.saveMeasure(CoreMetrics.TECHNICAL_DEBT, total.doubleValue());
- saveOnRule(context, ruleDebts);
- for (Characteristic characteristic : model.characteristics()) {
- Long debt = characteristicDebts.get(characteristic);
- saveCharacteristicMeasure(context, characteristic, debt != null ? debt.doubleValue() : 0d, false);
- }
- }
-
- private Long computeDebt(@Nullable Long debt, RuleKey ruleKey, SumMap<RuleKey> ruleDebts, SumMap<Characteristic> characteristicDebts) {
- if (debt != null) {
- Rule rule = rules.find(ruleKey);
- if (rule != null) {
- String characteristicKey = rule.debtSubCharacteristic();
- if (characteristicKey != null) {
- Characteristic characteristic = model.characteristicByKey(characteristicKey);
- if (characteristic != null) {
- ruleDebts.add(ruleKey, debt);
- characteristicDebts.add(characteristic, debt);
- propagateTechnicalDebtInParents(characteristic.parent(), debt, characteristicDebts);
- return debt;
- }
- }
- }
- }
- return 0L;
- }
-
- private void propagateTechnicalDebtInParents(@Nullable Characteristic characteristic, long value, SumMap<Characteristic> characteristicDebts) {
- if (characteristic != null) {
- characteristicDebts.add(characteristic, value);
- propagateTechnicalDebtInParents(characteristic.parent(), value, characteristicDebts);
- }
- }
-
- private void saveOnRule(DecoratorContext context, SumMap<RuleKey> ruleDebts) {
- for (Map.Entry<RuleKey, Long> entry : ruleDebts.entrySet()) {
- org.sonar.api.rules.Rule oldRule = ruleFinder.findByKey(entry.getKey());
- if (oldRule != null) {
- saveRuleMeasure(context, oldRule, entry.getValue().doubleValue(), ResourceUtils.isEntity(context.getResource()));
- }
- }
- }
-
- @VisibleForTesting
- void saveCharacteristicMeasure(DecoratorContext context, Characteristic characteristic, Double value, boolean inMemory) {
- // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
- // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
- if (value > 0.0 || (ResourceUtils.isProject(context.getResource()) && characteristic.isRoot())) {
- Measure measure = new Measure(CoreMetrics.TECHNICAL_DEBT);
- measure.setCharacteristic(characteristic);
- saveMeasure(context, measure, value, inMemory);
- }
- }
-
- @VisibleForTesting
- void saveRuleMeasure(DecoratorContext context, org.sonar.api.rules.Rule rule, Double value, boolean inMemory) {
- // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
- // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
- if (value > 0.0) {
- RuleMeasure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, rule, null, null);
- saveMeasure(context, measure, value, inMemory);
- }
- }
-
- private static void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory) {
- measure.setValue(value);
- if (inMemory) {
- measure.setPersistenceMode(PersistenceMode.MEMORY);
- }
- context.saveMeasure(measure);
- }
-
- private static boolean shouldSaveMeasure(DecoratorContext context) {
- return context.getMeasure(CoreMetrics.TECHNICAL_DEBT) == null;
- }
-
- private static class SumMap<E> {
- private Map<E, Long> sumByKeys;
-
- public SumMap() {
- sumByKeys = newHashMap();
- }
-
- public void add(@Nullable E key, Long value) {
- if (key != null) {
- Long currentValue = sumByKeys.get(key);
- sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
- }
- }
-
- @CheckForNull
- public Long get(E key) {
- return sumByKeys.get(key);
- }
-
- public Set<Map.Entry<E, Long>> entrySet() {
- return sumByKeys.entrySet();
- }
- }
-}
if (description != null) {
builder.setDescription(description);
}
- if (measure instanceof RuleMeasure) {
- RuleMeasure ruleMeasure = (RuleMeasure) measure;
- RuleKey ruleKey = ruleMeasure.ruleKey();
- if (ruleKey != null) {
- builder.setRuleKey(ruleKey.toString());
- }
- }
Level alertStatus = measure.getAlertStatus();
if (alertStatus != null) {
builder.setAlertStatus(alertStatus.toString());
-/*
- * 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.batch.debt;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-import org.hamcrest.Description;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.batch.rule.internal.RulesBuilder;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.MeasuresFilter;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-import org.sonar.api.test.IsMeasure;
-import org.sonar.api.utils.Duration;
-
-import java.util.Collections;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class DebtDecoratorTest {
-
- static final int HOURS_IN_DAY = 8;
-
- static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
-
- @Mock
- DecoratorContext context;
-
- @Mock
- Resource resource;
-
- @Mock
- TechnicalDebtModel debtModel;
-
- @Mock
- Issuable issuable;
-
- @Mock
- ResourcePerspectives perspectives;
-
- @Mock
- RuleFinder ruleFinder;
-
- RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
- RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
- Rules rules;
-
- DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY");
- DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency);
-
- DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY");
- DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability);
-
- DebtDecorator decorator;
-
- @Before
- public void before() {
- when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
- RulesBuilder rulesBuilder = new RulesBuilder();
- rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY");
- rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY");
- rules = rulesBuilder.build();
-
- when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
- when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()));
-
- when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity));
- when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency);
- when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency);
- when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability);
- when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity);
-
- decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder);
- }
-
- @Test
- public void generates_metrics() {
- assertThat(decorator.generatesMetrics()).hasSize(1);
- }
-
- @Test
- public void execute_on_project() {
- assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
- }
-
- @Test
- public void not_save_if_measure_already_computed() {
- when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure());
-
- decorator.decorate(resource, context);
-
- verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT)));
- }
-
- @Test
- public void add_technical_debt_from_one_issue_and_no_parent() {
- Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
- }
-
- @Test
- public void add_technical_debt_from_one_issue_without_debt() {
- Issue issue = createIssue("rule1", "repo1").setDebt(null);
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
- }
-
- @Test
- public void add_technical_debt_from_one_issue_and_propagate_to_parents() {
- Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue())));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue())));
- }
-
- @Test
- public void add_technical_debt_from_issues() {
- Long technicalDebt1 = ONE_DAY_IN_MINUTES;
- Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES;
-
- Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
- Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
- Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
- Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
- when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
-
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void add_technical_debt_from_current_and_children_measures() {
- Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
- Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
- when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
-
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
- new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
- org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null)
- .setValue(5d * ONE_DAY_IN_MINUTES)
- ));
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES);
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void add_technical_debt_only_from_children_measures() {
- when(issuable.issues()).thenReturn(Collections.<Issue>emptyList());
-
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
- new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
- org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule())
- , null, null).setValue(5d * ONE_DAY_IN_MINUTES),
-
- new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
- org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule())
- , null, null).setValue(10d * ONE_DAY_IN_MINUTES)
- ));
- decorator.decorate(resource, context);
-
- verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES);
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES)));
- verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void always_save_technical_debt_for_positive_values() {
- // for a project
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(new Project("foo"));
- decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
- verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
-
- // or for a file
- context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(File.create("foo"));
- decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
- verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
- }
-
- @Test
- public void always_save_technical_debt_for_project_if_top_characteristic() {
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(new Project("foo"));
-
- // this is a top characteristic
- DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root");
-
- decorator.saveCharacteristicMeasure(context, rootCharacteristic, 0.0, true);
- verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic));
- }
-
- /**
- * SQALE-147
- */
- @Test
- public void never_save_technical_debt_for_project_if_not_top_characteristic() {
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(new Project("foo"));
-
- DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
- DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic);
-
- decorator.saveCharacteristicMeasure(context, characteristic, 0.0, true);
- verify(context, never()).saveMeasure(any(Measure.class));
- }
-
- @Test
- public void not_save_technical_debt_for_file_if_zero() {
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(File.create("foo"));
-
- decorator.saveCharacteristicMeasure(context, null, 0.0, true);
- verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
- }
-
- private DefaultIssue createIssue(String ruleKey, String repositoryKey) {
- return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey));
- }
-
- class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
- Metric metric = null;
- Characteristic characteristic = null;
- Double value = null;
-
- public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) {
- this.metric = metric;
- this.characteristic = characteristic;
- this.value = value;
- }
-
- @Override
- public boolean matches(Object o) {
- if (!(o instanceof Measure)) {
- return false;
- }
- Measure m = (Measure) o;
- return ObjectUtils.equals(metric, m.getMetric()) &&
- ObjectUtils.equals(characteristic, m.getCharacteristic()) &&
- ObjectUtils.equals(value, m.getValue());
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText(new StringBuilder()
- .append("value=").append(value).append(",")
- .append("characteristic=").append(characteristic.key()).append(",")
- .append("metric=").append(metric.getKey()).toString());
- }
- }
-
- class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> {
- Metric metric = null;
- RuleKey ruleKey = null;
- Double value = null;
-
- public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) {
- this.metric = metric;
- this.ruleKey = ruleKey;
- this.value = value;
- }
-
- @Override
- public boolean matches(Object o) {
- if (!(o instanceof RuleMeasure)) {
- return false;
- }
- RuleMeasure m = (RuleMeasure) o;
- return ObjectUtils.equals(metric, m.getMetric()) &&
- ObjectUtils.equals(ruleKey, m.ruleKey()) &&
- ObjectUtils.equals(value, m.getValue());
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
- }
- }
-}
+///*
+// * 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.batch.debt;
+//
+//import com.google.common.collect.Lists;
+//import org.apache.commons.lang.ObjectUtils;
+//import org.apache.commons.lang.builder.ToStringBuilder;
+//import org.apache.commons.lang.builder.ToStringStyle;
+//import org.hamcrest.Description;
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.junit.runner.RunWith;
+//import org.mockito.ArgumentMatcher;
+//import org.mockito.Mock;
+//import org.mockito.runners.MockitoJUnitRunner;
+//import org.sonar.api.batch.DecoratorContext;
+//import org.sonar.api.batch.rule.Rules;
+//import org.sonar.api.batch.rule.internal.RulesBuilder;
+//import org.sonar.api.component.ResourcePerspectives;
+//import org.sonar.api.issue.Issuable;
+//import org.sonar.api.issue.Issue;
+//import org.sonar.core.issue.DefaultIssue;
+//import org.sonar.api.measures.CoreMetrics;
+//import org.sonar.api.measures.Measure;
+//import org.sonar.api.measures.MeasuresFilter;
+//import org.sonar.api.measures.Metric;
+//import org.sonar.api.measures.RuleMeasure;
+//import org.sonar.api.resources.File;
+//import org.sonar.api.resources.Project;
+//import org.sonar.api.resources.Resource;
+//import org.sonar.api.rule.RuleKey;
+//import org.sonar.api.rules.RuleFinder;
+//import org.sonar.api.technicaldebt.batch.Characteristic;
+//import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
+//import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
+//import org.sonar.api.test.IsMeasure;
+//import org.sonar.api.utils.Duration;
+//
+//import java.util.Collections;
+//
+//import static com.google.common.collect.Lists.newArrayList;
+//import static org.assertj.core.api.Assertions.assertThat;
+//import static org.mockito.Matchers.any;
+//import static org.mockito.Matchers.argThat;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.never;
+//import static org.mockito.Mockito.times;
+//import static org.mockito.Mockito.verify;
+//import static org.mockito.Mockito.when;
+//
+//@RunWith(MockitoJUnitRunner.class)
+//public class DebtDecoratorTest {
+//
+// static final int HOURS_IN_DAY = 8;
+//
+// static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
+//
+// @Mock
+// DecoratorContext context;
+//
+// @Mock
+// Resource resource;
+//
+// @Mock
+// TechnicalDebtModel debtModel;
+//
+// @Mock
+// Issuable issuable;
+//
+// @Mock
+// ResourcePerspectives perspectives;
+//
+// @Mock
+// RuleFinder ruleFinder;
+//
+// RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
+// RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
+// Rules rules;
+//
+// DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY");
+// DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency);
+//
+// DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY");
+// DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability);
+//
+// DebtDecorator decorator;
+//
+// @Before
+// public void before() {
+// when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
+// RulesBuilder rulesBuilder = new RulesBuilder();
+// rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY");
+// rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY");
+// rules = rulesBuilder.build();
+//
+// when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
+// when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()));
+//
+// when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity));
+// when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency);
+// when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency);
+// when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability);
+// when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity);
+//
+// decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder);
+// }
+//
+// @Test
+// public void generates_metrics() {
+// assertThat(decorator.generatesMetrics()).hasSize(1);
+// }
+//
+// @Test
+// public void execute_on_project() {
+// assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
+// }
+//
+// @Test
+// public void not_save_if_measure_already_computed() {
+// when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure());
+//
+// decorator.decorate(resource, context);
+//
+// verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT)));
+// }
+//
+// @Test
+// public void add_technical_debt_from_one_issue_and_no_parent() {
+// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
+// }
+//
+// @Test
+// public void add_technical_debt_from_one_issue_without_debt() {
+// Issue issue = createIssue("rule1", "repo1").setDebt(null);
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
+// }
+//
+// @Test
+// public void add_technical_debt_from_one_issue_and_propagate_to_parents() {
+// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue())));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue())));
+// }
+//
+// @Test
+// public void add_technical_debt_from_issues() {
+// Long technicalDebt1 = ONE_DAY_IN_MINUTES;
+// Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES;
+//
+// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
+// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
+// Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
+// Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
+// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
+//
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void add_technical_debt_from_current_and_children_measures() {
+// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
+// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
+//
+// when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
+// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+// org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null)
+// .setValue(5d * ONE_DAY_IN_MINUTES)
+// ));
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES);
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void add_technical_debt_only_from_children_measures() {
+// when(issuable.issues()).thenReturn(Collections.<Issue>emptyList());
+//
+// when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList(
+// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+// org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule())
+// , null, null).setValue(5d * ONE_DAY_IN_MINUTES),
+//
+// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT,
+// org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule())
+// , null, null).setValue(10d * ONE_DAY_IN_MINUTES)
+// ));
+// decorator.decorate(resource, context);
+//
+// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES);
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES)));
+// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void always_save_technical_debt_for_positive_values() {
+// // for a project
+// DecoratorContext context = mock(DecoratorContext.class);
+// when(context.getResource()).thenReturn(new Project("foo"));
+// decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
+// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+//
+// // or for a file
+// context = mock(DecoratorContext.class);
+// when(context.getResource()).thenReturn(File.create("foo"));
+// decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false);
+// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+// }
+//
+// @Test
+// public void always_save_technical_debt_for_project_if_top_characteristic() {
+// DecoratorContext context = mock(DecoratorContext.class);
+// when(context.getResource()).thenReturn(new Project("foo"));
+//
+// // this is a top characteristic
+// DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root");
+//
+// decorator.saveCharacteristicMeasure(context, rootCharacteristic, 0.0, true);
+// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic));
+// }
+//
+// /**
+// * SQALE-147
+// */
+// @Test
+// public void never_save_technical_debt_for_project_if_not_top_characteristic() {
+// DecoratorContext context = mock(DecoratorContext.class);
+// when(context.getResource()).thenReturn(new Project("foo"));
+//
+// DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY");
+// DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic);
+//
+// decorator.saveCharacteristicMeasure(context, characteristic, 0.0, true);
+// verify(context, never()).saveMeasure(any(Measure.class));
+// }
+//
+// @Test
+// public void not_save_technical_debt_for_file_if_zero() {
+// DecoratorContext context = mock(DecoratorContext.class);
+// when(context.getResource()).thenReturn(File.create("foo"));
+//
+// decorator.saveCharacteristicMeasure(context, null, 0.0, true);
+// verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
+// }
+//
+// private DefaultIssue createIssue(String ruleKey, String repositoryKey) {
+// return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey));
+// }
+//
+// class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
+// Metric metric = null;
+// Characteristic characteristic = null;
+// Double value = null;
+//
+// public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) {
+// this.metric = metric;
+// this.characteristic = characteristic;
+// this.value = value;
+// }
+//
+// @Override
+// public boolean matches(Object o) {
+// if (!(o instanceof Measure)) {
+// return false;
+// }
+// Measure m = (Measure) o;
+// return ObjectUtils.equals(metric, m.getMetric()) &&
+// ObjectUtils.equals(characteristic, m.getCharacteristic()) &&
+// ObjectUtils.equals(value, m.getValue());
+// }
+//
+// @Override
+// public void describeTo(Description description) {
+// description.appendText(new StringBuilder()
+// .append("value=").append(value).append(",")
+// .append("characteristic=").append(characteristic.key()).append(",")
+// .append("metric=").append(metric.getKey()).toString());
+// }
+// }
+//
+// class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> {
+// Metric metric = null;
+// RuleKey ruleKey = null;
+// Double value = null;
+//
+// public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) {
+// this.metric = metric;
+// this.ruleKey = ruleKey;
+// this.value = value;
+// }
+//
+// @Override
+// public boolean matches(Object o) {
+// if (!(o instanceof RuleMeasure)) {
+// return false;
+// }
+// RuleMeasure m = (RuleMeasure) o;
+// return ObjectUtils.equals(metric, m.getMetric()) &&
+// ObjectUtils.equals(ruleKey, m.ruleKey()) &&
+// ObjectUtils.equals(value, m.getValue());
+// }
+//
+// @Override
+// public void describeTo(Description description) {
+// description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
+// }
+// }
+//}
*/
package org.sonar.batch.report;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.measures.Metric.Level;
import org.sonar.api.measures.Metric.ValueType;
import org.sonar.api.measures.MetricFinder;
-import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RulePriority;
import org.sonar.api.technicaldebt.batch.Characteristic;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.scan.measure.MeasureCache;
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
Measure manual = new Measure<>(new Metric<>("manual_metric", ValueType.BOOL))
.setValue(1.0)
.setDescription("Manual");
- // Rule measure
- RuleMeasure ruleMeasureBySeverity = RuleMeasure.createForPriority(CoreMetrics.NCLOC, RulePriority.BLOCKER, 1.0);
- RuleMeasure ruleMeasureByRule = RuleMeasure.createForRule(CoreMetrics.NCLOC, RuleKey.of("squid", "S12345"), 1.0);
// Sqale rating have both a value and a data
Measure rating = new Measure<>(CoreMetrics.SQALE_RATING)
.setValue(2.0)
Measure stringMeasure = new Measure<>(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
.setData("foo bar");
- when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, ruleMeasureBySeverity, ruleMeasureByRule, rating, longMeasure, stringMeasure));
+ when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, rating, longMeasure, stringMeasure));
File outputDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(outputDir);
*/
package org.sonar.batch.scan.measure;
-import org.sonar.batch.index.AbstractCachesTest;
+import java.util.Date;
+import java.util.Iterator;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric.Level;
-import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Directory;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RulePriority;
import org.sonar.api.technicaldebt.batch.Characteristic;
import org.sonar.api.technicaldebt.batch.Requirement;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
+import org.sonar.batch.index.AbstractCachesTest;
import org.sonar.batch.index.Cache.Entry;
-import java.util.Date;
-import java.util.Iterator;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
private MetricFinder metricFinder;
- private TechnicalDebtModel techDebtModel;
-
private MeasureCache measureCache;
@Before
super.start();
metricFinder = mock(MetricFinder.class);
when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
- techDebtModel = mock(TechnicalDebtModel.class);
- measureCache = new MeasureCache(caches, metricFinder, techDebtModel);
+ measureCache = new MeasureCache(caches, metricFinder);
}
@Test
assertThat(measureCache.byResource(p)).hasSize(1);
assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
-
- Measure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
- measureCache.put(p, mRule);
-
- assertThat(measureCache.entries()).hasSize(2);
-
- assertThat(measureCache.byResource(p)).hasSize(2);
}
@Test
for (int i = 0; i < 1_048_575; i++) {
data.append("a");
}
-
+
m.setData(data.toString());
measureCache.put(p, m);
assertThat(measureCache.byResource(p)).hasSize(1);
assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
-
- RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
- mRule.setRuleKey(RuleKey.of("repo", "rule"));
- measureCache.put(p, mRule);
-
- assertThat(measureCache.entries()).hasSize(2);
}
/**
assertThat(measureCache.byResource(p)).hasSize(1);
assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m);
- RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0);
- mRule.setRuleKey(RuleKey.of("repo", "rule"));
- measureCache.put(p, mRule);
-
- assertThat(measureCache.entries()).hasSize(2);
}
@Test
assertThat(measureCache.byResource(p)).hasSize(0);
Measure m1 = new Measure(CoreMetrics.NCLOC, 1.0);
- Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setCharacteristic(new DefaultCharacteristic().setKey("charac"));
- Measure m3 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2);
- Measure m4 = new RuleMeasure(CoreMetrics.NCLOC, RuleKey.of("repo", "rule"), RulePriority.BLOCKER, null);
+ Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2);
measureCache.put(p, m1);
measureCache.put(p, m2);
- measureCache.put(p, m3);
- measureCache.put(p, m4);
-
- assertThat(measureCache.entries()).hasSize(4);
- assertThat(measureCache.byResource(p)).hasSize(4);
+ assertThat(measureCache.entries()).hasSize(2);
+ assertThat(measureCache.byResource(p)).hasSize(2);
}
@Test
}
}
+ /**
+ * @deprecated since 5.2. Useless by design because of Compute Engine
+ */
+ @Deprecated
private abstract static class AbstractRuleMeasureFilter<M> extends MetricFilter<M> {
protected AbstractRuleMeasureFilter(Metric metric) {
super(metric);
}
}
+ /**
+ * @deprecated since 5.2. Useless by design because of Compute Engine
+ */
+ @Deprecated
private static class RuleFilter extends AbstractRuleMeasureFilter<RuleMeasure> {
private RuleKey ruleKey;
/**
* @since 1.10
+ * @deprecated since 5.2. Ignored by design because of Compute Engine.
*/
+@Deprecated
public class RuleMeasure extends Measure {
private RuleKey ruleKey;
+++ /dev/null
-/*
- * 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.api.test;
-
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.math.NumberUtils;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.RuleMeasure;
-import org.sonar.api.rules.Rule;
-
-public class IsRuleMeasure extends ArgumentMatcher<Measure> {
-
- private Metric metric = null;
- private Rule rule = null;
- private Double value = null;
-
- public IsRuleMeasure(Metric metric, Rule rule, Double value) {
- this.metric = metric;
- this.rule = rule;
- this.value = value;
- }
-
- @Override
- public boolean matches(Object o) {
- if (!(o instanceof RuleMeasure)) {
- return false;
- }
- RuleMeasure m = (RuleMeasure) o;
- return ObjectUtils.equals(metric, m.getMetric()) &&
- ObjectUtils.equals(rule.ruleKey(), m.ruleKey()) &&
- NumberUtils.compare(value, m.getValue()) == 0;
- }
-}