]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5285 Return the number of covered lines
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 14 May 2014 10:29:08 +0000 (12:29 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 14 May 2014 10:29:30 +0000 (12:29 +0200)
sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java
sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java
sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java
sonar-server/src/main/java/org/sonar/server/test/CoverageService.java
sonar-server/src/main/java/org/sonar/server/test/ws/CoverageShowAction.java
sonar-server/src/test/java/org/sonar/server/test/CoverageServiceTest.java
sonar-server/src/test/java/org/sonar/server/test/ws/CoverageShowActionTest.java
sonar-server/src/test/resources/org/sonar/server/test/ws/CoverageShowActionTest/show_coverage.json
sonar-server/src/test/resources/org/sonar/server/test/ws/CoverageShowActionTest/show_coverage_with_from_and_to.json

index 43a51a93553a1e03569dea0dfa30ae5b14b40b11..82298fa43d89556dc27d8e6a40d26897fa224715 100644 (file)
@@ -35,8 +35,11 @@ import org.sonar.core.graph.BeanVertex;
 import org.sonar.core.graph.GraphUtil;
 
 import java.util.List;
+import java.util.Map;
 import java.util.SortedSet;
 
+import static com.google.common.collect.Maps.newHashMap;
+
 public class DefaultTestable extends BeanVertex implements MutableTestable {
 
   private static final String COVERS = "covers";
@@ -73,6 +76,14 @@ public class DefaultTestable extends BeanVertex implements MutableTestable {
     return number;
   }
 
+  public Map<Integer, Integer> testCasesByLines() {
+    Map<Integer, Integer> testCasesByLines = newHashMap();
+    for (Integer line : testedLines()) {
+      testCasesByLines.put(line, countTestCasesOfLine(line));
+    }
+    return testCasesByLines;
+  }
+
   public List<TestCase> testCasesOfLine(int line) {
     ImmutableList.Builder<TestCase> cases = ImmutableList.builder();
     for (Edge edge : coverEdges()) {
index 09a5b86300136295fb81d739395d640ffebe1a75..18bf9b76946b1784d1c0f2bbe18fe6b74c530dca 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.core.test;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import org.junit.Test;
 import org.sonar.api.component.mock.MockSourceFile;
@@ -32,8 +33,9 @@ import java.util.Arrays;
 import static org.fest.assertions.Assertions.assertThat;
 
 public class DefaultTestableTest {
+
   @Test
-  public void should_not_have_tested_lines() {
+  public void not_have_tested_lines() {
     BeanGraph beanGraph = BeanGraph.createInMemory();
 
     DefaultTestable testable = beanGraph.createVertex(DefaultTestable.class);
@@ -41,7 +43,7 @@ public class DefaultTestableTest {
   }
 
   @Test
-  public void should_have_tested_lines() {
+  public void tested_lines() {
     BeanGraph beanGraph = BeanGraph.createInMemory();
 
     DefaultTestable testable = beanGraph.createVertex(DefaultTestable.class);
@@ -57,7 +59,7 @@ public class DefaultTestableTest {
   }
 
   @Test
-  public void should_get_test_cases() {
+  public void get_test_cases() {
     BeanGraph beanGraph = BeanGraph.createInMemory();
 
     DefaultTestable testable = beanGraph.createVertex(DefaultTestable.class);
@@ -73,7 +75,7 @@ public class DefaultTestableTest {
   }
 
   @Test
-  public void should_get_test_case_by_key() {
+  public void get_test_case_by_key() {
     BeanGraph beanGraph = BeanGraph.createInMemory();
 
     DefaultTestPlan plan = beanGraph.createVertex(DefaultTestPlan.class);
@@ -92,7 +94,7 @@ public class DefaultTestableTest {
   }
 
   @Test
-  public void should_return_cover_of_testCase(){
+  public void return_cover_of_testCase(){
     BeanGraph beanGraph = BeanGraph.createInMemory();
 
     ScanGraph graph = ScanGraph.create();
@@ -112,4 +114,17 @@ public class DefaultTestableTest {
     assertThat(testable1.coverageBlock(testCase).testable()).isEqualTo(testable1);
     assertThat(testable2.coverageBlock(testCase)).isNull();
   }
+
+  @Test
+  public void test_cases_by_lines() {
+    BeanGraph beanGraph = BeanGraph.createInMemory();
+
+    DefaultTestable testable = beanGraph.createVertex(DefaultTestable.class);
+    DefaultTestCase testCase1 = beanGraph.createVertex(DefaultTestCase.class);
+    testCase1.setCoverageBlock(testable, Arrays.asList(10, 11, 12));
+    DefaultTestCase testCase2 = beanGraph.createVertex(DefaultTestCase.class);
+    testCase2.setCoverageBlock(testable, Arrays.asList(12, 48, 49));
+
+    assertThat(testable.testCasesByLines()).isEqualTo(ImmutableMap.of(49, 1, 48, 1, 10, 1, 11, 1, 12, 2));
+  }
 }
index cfa3572020ab6bd7eaeb7a86048d6e8ea2d5f868..7091b6bee8666abbb2f62ad8c20dcd55cdf23a23 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.api.test;
 import org.sonar.api.component.Perspective;
 
 import java.util.List;
+import java.util.Map;
 import java.util.SortedSet;
 
 public interface Testable extends Perspective {
@@ -32,6 +33,8 @@ public interface Testable extends Perspective {
 
   int countTestCasesOfLine(Integer line);
 
+  Map<Integer, Integer> testCasesByLines();
+
   List<TestCase> testCasesOfLine(int line);
 
   SortedSet<Integer> testedLines();
index 872a14596c9dcac9a7680a58d2a33c83d47e5498..ef24e83abd73312aaae33bb03ede438a06e05d1b 100644 (file)
@@ -22,19 +22,26 @@ package org.sonar.server.test;
 
 import org.sonar.api.ServerComponent;
 import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.test.MutableTestable;
+import org.sonar.api.test.Testable;
 import org.sonar.api.web.UserRole;
+import org.sonar.core.component.SnapshotPerspectives;
 import org.sonar.core.measure.db.MeasureDataDao;
 import org.sonar.core.measure.db.MeasureDataDto;
 import org.sonar.server.user.UserSession;
 
 import javax.annotation.CheckForNull;
 
+import java.util.Map;
+
 public class CoverageService implements ServerComponent {
 
   private final MeasureDataDao measureDataDao;
+  private final SnapshotPerspectives snapshotPerspectives;
 
-  public CoverageService(MeasureDataDao measureDataDao) {
+  public CoverageService(MeasureDataDao measureDataDao, SnapshotPerspectives snapshotPerspectives) {
     this.measureDataDao = measureDataDao;
+    this.snapshotPerspectives = snapshotPerspectives;
   }
 
   public void checkPermission(String fileKey) {
@@ -65,6 +72,18 @@ public class CoverageService implements ServerComponent {
     return findDataFromComponent(fileKey, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
   }
 
+  /**
+   * Warning - does not check permission
+   */
+  @CheckForNull
+  public Map<Integer, Integer> getCoveredLines(String fileKey) {
+    Testable testable = snapshotPerspectives.as(MutableTestable.class, fileKey);
+    if (testable != null) {
+      return testable.testCasesByLines();
+    }
+    return null;
+  }
+
   @CheckForNull
   private String findDataFromComponent(String fileKey, String metricKey) {
     MeasureDataDto data = measureDataDao.findByComponentKeyAndMetricKey(fileKey, metricKey);
index ff2f4c93eb9ee2a9812d75a76e416398fd51d358..dbb1d3d0a1b547c814cbeef213337ebb6892ee67 100644 (file)
@@ -30,6 +30,8 @@ import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.utils.text.JsonWriter;
 import org.sonar.server.test.CoverageService;
 
+import javax.annotation.Nullable;
+
 import java.util.Map;
 
 public class CoverageShowAction implements RequestHandler {
@@ -86,15 +88,16 @@ public class CoverageShowAction implements RequestHandler {
     JsonWriter json = response.newJsonWriter().beginObject();
 
     String hits = coverageService.getHitsData(fileKey);
+    Map<Integer, Integer> coveredLines = coverageService.getCoveredLines(fileKey);
     if (hits != null) {
-      Map<Integer, Integer> hitsByLine =  KeyValueFormat.parseIntInt(hits);
-    writeCoverage(hitsByLine, from, to, json);
+      Map<Integer, Integer> hitsByLine = KeyValueFormat.parseIntInt(hits);
+      writeCoverage(fileKey, hitsByLine, coveredLines, from, to, json);
     }
 
     json.endObject().close();
   }
 
-  private void writeCoverage(Map<Integer, Integer> hitsByLine, int from, int to, JsonWriter json) {
+  private void writeCoverage(String fileKey, Map<Integer, Integer> hitsByLine, @Nullable Map<Integer, Integer> coveredLines, int from, int to, JsonWriter json) {
     json.name("coverage").beginArray();
     for (Map.Entry<Integer, Integer> entry : hitsByLine.entrySet()) {
       Integer line = entry.getKey();
@@ -103,6 +106,7 @@ public class CoverageShowAction implements RequestHandler {
         json.beginArray();
         json.value(line);
         json.value(hits > 0);
+        json.value(coveredLines != null ? coveredLines.get(line) : null);
         json.endArray();
       }
     }
index dcd96412117ad3581579fc1e4ae981f509370ea3..95a61a9965949d3d6245ad0da0525c39a6a5d1be 100644 (file)
@@ -27,15 +27,16 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.test.MutableTestable;
 import org.sonar.api.web.UserRole;
+import org.sonar.core.component.SnapshotPerspectives;
 import org.sonar.core.measure.db.MeasureDataDao;
 import org.sonar.server.user.MockUserSession;
 
 import static org.fest.assertions.Assertions.assertThat;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 @RunWith(MockitoJUnitRunner.class)
 public class CoverageServiceTest {
@@ -46,13 +47,16 @@ public class CoverageServiceTest {
   @Mock
   MeasureDataDao measureDataDao;
 
+  @Mock
+  SnapshotPerspectives snapshotPerspectives;
+
   static final String COMPONENT_KEY = "org.sonar.sample:Sample";
 
   CoverageService service;
 
   @Before
   public void setUp() throws Exception {
-    service = new CoverageService(measureDataDao);
+    service = new CoverageService(measureDataDao, snapshotPerspectives);
   }
 
   @Test
@@ -88,4 +92,20 @@ public class CoverageServiceTest {
     verify(measureDataDao).findByComponentKeyAndMetricKey(COMPONENT_KEY, CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY);
   }
 
+  @Test
+  public void get_coverered_lines() throws Exception {
+    MutableTestable testable = mock(MutableTestable.class);
+    when(snapshotPerspectives.as(MutableTestable.class, COMPONENT_KEY)).thenReturn(testable);
+
+    service.getCoveredLines(COMPONENT_KEY);
+    verify(testable).testCasesByLines();
+  }
+
+  @Test
+  public void not_get_coverered_lines_if_no_testable() throws Exception {
+    when(snapshotPerspectives.as(MutableTestable.class, COMPONENT_KEY)).thenReturn(null);
+
+    assertThat(service.getCoveredLines(COMPONENT_KEY)).isNull();
+  }
+
 }
index 3ac301e3f77e99a64478fa3d1200099d5c0d8587..dd16d3e694e627ce08b518861211b43750885dc2 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.sonar.server.test.ws;
 
+import com.google.common.collect.ImmutableMap;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,6 +48,7 @@ public class CoverageShowActionTest {
   public void show_coverage() throws Exception {
     String fileKey = "src/Foo.java";
     when(coverageService.getHitsData(fileKey)).thenReturn("1=1;2=1;3=0;4=1;5=1");
+    when(coverageService.getCoveredLines(fileKey)).thenReturn(ImmutableMap.of(4, 8, 1, 2));
 
     WsTester.TestRequest request = tester.newGetRequest("api/coverage", "show").setParam("key", fileKey);
 
@@ -57,6 +59,7 @@ public class CoverageShowActionTest {
   public void show_coverage_with_from_and_to() throws Exception {
     String fileKey = "src/Foo.java";
     when(coverageService.getHitsData(fileKey)).thenReturn("1=1;2=1;3=0;4=1;5=1");
+    when(coverageService.getCoveredLines(fileKey)).thenReturn(ImmutableMap.of(4, 8, 1, 2));
 
     WsTester.TestRequest request = tester.newGetRequest("api/coverage", "show").setParam("key", fileKey).setParam("from", "3").setParam("to", "4");
 
index fb7da2f35627cead6c2de46b2ae8257dd62aa5d8..55c59edcc085ce04e52384da427d28e091e6a727 100644 (file)
@@ -1,9 +1,9 @@
 {
   "coverage": [
-    [1, true],
-    [2, true],
-    [3, false],
-    [4, true],
-    [5, true]
+    [1, true, 2],
+    [2, true, null],
+    [3, false, null],
+    [4, true, 8],
+    [5, true, null]
   ]
 }