--- /dev/null
+{
+"tests": [
+ {
+ "name": "test1",
+ "status": "OK",
+ "durationInMs": 10,
+ "coveredLines": 32
+ },
+ {
+ "name": "test2",
+ "status": "ERROR",
+ "durationInMs": 97,
+ "coveredLines": 21,
+ "message": "expected:<true> but was:<false>",
+ "stackTrace" : "java.lang.AssertionError: expected:<true> but was:<false>\n\tat org.junit.Assert.fail(Assert.java:91)\n\tat org.junit.Assert.failNotEquals(Assert.java:645)\n\tat org.junit.Assert.assertEquals(Assert.java:126)\n\tat org.junit.Assert.assertEquals(Assert.java:145)\n"
+ }
+ ]
+}
import org.apache.ibatis.annotations.Param;
+import javax.annotation.CheckForNull;
+
import java.util.List;
public interface MeasureMapper {
List<MeasureDto> selectByComponentAndMetrics(@Param("componentKey") String componentKey, @Param("metricKeys") List<String> metricKeys);
+ @CheckForNull
+ MeasureDto selectByComponentAndMetric(@Param("componentKey") String componentKey, @Param("metricKey") String metricKey);
+
long countByKey(@Param("key") MeasureKey key);
}
</where>
</select>
+ <select id="selectByComponentAndMetric" parameterType="map" resultType="Measure">
+ SELECT metric.name as metric_name,
+ <include refid="measureColumns"/>
+ FROM project_measures pm
+ INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true}
+ INNER JOIN projects p ON p.id=s.project_id AND p.enabled=${_true}
+ INNER JOIN metrics metric ON metric.id=pm.metric_id
+ <where>
+ AND p.kee = #{componentKey}
+ AND metric.name=#{metricKey}
+ AND pm.rule_id IS NULL
+ AND pm.characteristic_id IS NULL
+ AND pm.person_id IS NULL
+ </where>
+ </select>
+
<select id="countByKey" parameterType="map" resultType="long">
SELECT count(pm.id)
FROM project_measures pm
return dtos;
}
+ public MeasureDto findByComponentKeyAndMetricKey(String componentKey, String metricKey, DbSession session) {
+ return session.getMapper(MeasureMapper.class).selectByComponentAndMetric(componentKey, metricKey);
+ }
+
@Override
protected MeasureDto doInsert(DbSession session, MeasureDto item) {
throw notImplemented();
package org.sonar.server.test.ws;
import com.google.common.io.Resources;
+import org.codehaus.staxmate.SMInputFactory;
+import org.codehaus.staxmate.in.SMHierarchicCursor;
+import org.codehaus.staxmate.in.SMInputCursor;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.component.SnapshotPerspectives;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
import org.sonar.server.user.UserSession;
+import javax.annotation.CheckForNull;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+
+import java.io.StringReader;
+
public class TestsShowAction implements RequestHandler {
private static final String KEY = "key";
+ private final DbClient dbClient;
private final SnapshotPerspectives snapshotPerspectives;
- public TestsShowAction(SnapshotPerspectives snapshotPerspectives) {
+ public TestsShowAction(DbClient dbClient, SnapshotPerspectives snapshotPerspectives) {
+ this.dbClient = dbClient;
this.snapshotPerspectives = snapshotPerspectives;
}
String fileKey = request.mandatoryParam(KEY);
UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
- MutableTestPlan testPlan = snapshotPerspectives.as(MutableTestPlan.class, fileKey);
+ String testData = findTestData(fileKey);
JsonWriter json = response.newJsonWriter().beginObject();
- if (testPlan != null) {
- writeTests(testPlan, json);
+ if (testData != null) {
+ writeFromTestData(testData, json);
+ } else {
+ MutableTestPlan testPlan = snapshotPerspectives.as(MutableTestPlan.class, fileKey);
+ if (testPlan != null) {
+ writeFromTestable(testPlan, json);
+ }
}
json.endObject().close();
}
- private void writeTests(MutableTestPlan testPlan, JsonWriter json) {
+ private void writeFromTestable(MutableTestPlan testPlan, JsonWriter json) {
json.name("tests").beginArray();
for (TestCase testCase : testPlan.testCases()) {
json.beginObject();
json.endArray();
}
+ private void writeFromTestData(String data, JsonWriter json) {
+ SMInputFactory inputFactory = initStax();
+ try {
+ SMHierarchicCursor root = inputFactory.rootElementCursor(new StringReader(data));
+ root.advance(); // tests-details
+ SMInputCursor cursor = root.childElementCursor();
+ json.name("tests").beginArray();
+ while (cursor.getNext() != null) {
+ json.beginObject();
+
+ json.prop("name", cursor.getAttrValue("name"));
+ json.prop("status", cursor.getAttrValue("status").toUpperCase());
+ json.prop("durationInMs", cursor.getAttrValue("time"));
+
+ SMInputCursor errorCursor = cursor.childElementCursor();
+ if (errorCursor.getNext() != null) {
+ json.prop("message", errorCursor.getAttrValue("message"));
+
+ SMInputCursor stackTraceCursor = cursor.childElementCursor();
+ if (stackTraceCursor.getNext() != null) {
+// json.prop("stackTrace", stackTraceCursor.getAttrValue(""));
+ }
+ }
+
+ json.endObject();
+ }
+ json.endArray();
+ } catch (XMLStreamException e) {
+ throw new IllegalStateException("XML is not valid: " + e.getMessage(), e);
+ }
+ }
+
+ @CheckForNull
+ private String findTestData(String fileKey) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ MeasureDto testData = dbClient.measureDao().findByComponentKeyAndMetricKey(fileKey, CoreMetrics.TEST_DATA_KEY, session);
+ if (testData != null) {
+ return testData.getData();
+ }
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ return null;
+ }
+
+ private SMInputFactory initStax() {
+ XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
+ xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
+ xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
+ // just so it won't try to load DTD in if there's DOCTYPE
+ xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
+ xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
+ return new SMInputFactory(xmlFactory);
+ }
+
}
assertThat(result.getVariation(5)).isEqualTo(-5d);
}
+ @Test
+ public void find_by_component_key_and_metric() throws Exception {
+ setupData("shared");
+
+ MeasureDto result = dao.findByComponentKeyAndMetricKey("org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc", session);
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getKey()).isEqualTo(MeasureKey.of("org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc"));
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+
+ assertThat(dao.findByComponentKeyAndMetricKey("org.struts:struts-core:src/org/struts/RequestContext.java", "unknown", session)).isNull();
+ }
+
@Test
public void exists_by_key() throws Exception {
setupData("shared");
package org.sonar.server.test.ws;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.sonar.api.test.TestCase;
import org.sonar.api.web.UserRole;
import org.sonar.core.component.SnapshotPerspectives;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.measure.db.MeasureKey;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
static final String TEST_PLAN_KEY = "src/test/java/org/foo/BarTest.java";
+ @Mock
+ DbSession session;
+
+ @Mock
+ MeasureDao measureDao;
+
@Mock
MutableTestPlan testPlan;
+ @Mock
+ SnapshotPerspectives snapshotPerspectives;
+
WsTester tester;
@Before
public void setUp() throws Exception {
- SnapshotPerspectives snapshotPerspectives = mock(SnapshotPerspectives.class);
- when(snapshotPerspectives.as(MutableTestPlan.class, TEST_PLAN_KEY)).thenReturn(testPlan);
- tester = new WsTester(new TestsWs(new TestsShowAction(snapshotPerspectives), mock(TestsTestCasesAction.class), mock(TestsCoveredFilesAction.class)));
+ DbClient dbClient = mock(DbClient.class);
+ when(dbClient.openSession(false)).thenReturn(session);
+ when(dbClient.measureDao()).thenReturn(measureDao);
+
+ tester = new WsTester(new TestsWs(new TestsShowAction(dbClient, snapshotPerspectives), mock(TestsTestCasesAction.class), mock(TestsCoveredFilesAction.class)));
}
@Test
public void show() throws Exception {
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "SonarQube", TEST_PLAN_KEY);
+ when(snapshotPerspectives.as(MutableTestPlan.class, TEST_PLAN_KEY)).thenReturn(testPlan);
+
MutableTestCase testCase1 = testCase("test1", TestCase.Status.OK, 10L, 32, null, null);
MutableTestCase testCase2 = testCase("test2", TestCase.Status.ERROR, 97L, 21, "expected:<true> but was:<false>",
"java.lang.AssertionError: expected:<true> but was:<false>\n\t" +
- "at org.junit.Assert.fail(Assert.java:91)\n\t" +
- "at org.junit.Assert.failNotEquals(Assert.java:645)\n\t" +
- "at org.junit.Assert.assertEquals(Assert.java:126)\n\t" +
- "at org.junit.Assert.assertEquals(Assert.java:145)\n");
+ "at org.junit.Assert.fail(Assert.java:91)\n\t" +
+ "at org.junit.Assert.failNotEquals(Assert.java:645)\n\t" +
+ "at org.junit.Assert.assertEquals(Assert.java:126)\n\t" +
+ "at org.junit.Assert.assertEquals(Assert.java:145)\n");
when(testPlan.testCases()).thenReturn(newArrayList(testCase1, testCase2));
WsTester.TestRequest request = tester.newGetRequest("api/tests", "show").setParam("key", TEST_PLAN_KEY);
request.execute().assertJson(getClass(), "show.json");
}
+ @Test
+ @Ignore
+ public void show_from_test_data() throws Exception {
+ MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, "SonarQube", TEST_PLAN_KEY);
+
+ when(measureDao.findByComponentKeyAndMetricKey(TEST_PLAN_KEY, "test_data", session)).thenReturn(MeasureDto.createFor(MeasureKey.of(TEST_PLAN_KEY, "test_data"))
+ .setTextValue("<tests-details>" +
+ "<testcase status=\"ok\" time=\"10\" name=\"test1\"/>" +
+ "<testcase status=\"error\" time=\"97\" name=\"test2\">" +
+ "<error message=\"expected:<true> but was:<false>\">" +
+ "<![CDATA[" +
+ "java.lang.AssertionError: expected:<true> but was:<false>\n\t" +
+ "at org.junit.Assert.fail(Assert.java:91)\n\t" +
+ "at org.junit.Assert.failNotEquals(Assert.java:645)\n\t" +
+ "at org.junit.Assert.assertEquals(Assert.java:126)\n\t" +
+ "at org.junit.Assert.assertEquals(Assert.java:145)\n" +
+ "]]>" +
+ "</error>" +
+ "</testcase>" +
+ "</tests-details>"));
+
+ // TODO failure
+
+ WsTester.TestRequest request = tester.newGetRequest("api/tests", "show").setParam("key", TEST_PLAN_KEY);
+
+ request.execute().assertJson(getClass(), "show_from_test_data.json");
+ }
+
private MutableTestCase testCase(String name, TestCase.Status status, Long durationInMs, int coveredLines, @Nullable String message, @Nullable String stackTrace) {
MutableTestCase testCase = mock(MutableTestCase.class);
when(testCase.name()).thenReturn(name);
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.component.SnapshotPerspectives;
+import org.sonar.server.db.DbClient;
import org.sonar.server.ws.WsTester;
import static org.fest.assertions.Assertions.assertThat;
@Before
public void setUp() throws Exception {
SnapshotPerspectives snapshotPerspectives = mock(SnapshotPerspectives.class);
- WsTester tester = new WsTester(new TestsWs(new TestsShowAction(snapshotPerspectives), new TestsTestCasesAction(snapshotPerspectives), new TestsCoveredFilesAction(snapshotPerspectives)));
+ WsTester tester = new WsTester(new TestsWs(new TestsShowAction(mock(DbClient.class), snapshotPerspectives), new TestsTestCasesAction(snapshotPerspectives), new TestsCoveredFilesAction(snapshotPerspectives)));
controller = tester.controller("api/tests");
}