From: Julien Lancelot Date: Mon, 26 May 2014 12:39:29 +0000 (+0200) Subject: SONAR-5338 Create Java client for tests WS X-Git-Tag: 4.4-RC1~826 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5997da24804c4a095bd7cbe6c50ad50ae2121e94;p=sonarqube.git SONAR-5338 Create Java client for tests WS --- diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java index 51b594321dd..71a87213e74 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java @@ -41,7 +41,9 @@ import org.sonar.wsclient.source.internal.DefaultSourceClient; import org.sonar.wsclient.system.SystemClient; import org.sonar.wsclient.system.internal.DefaultSystemClient; import org.sonar.wsclient.test.CoverageClient; +import org.sonar.wsclient.test.TestClient; import org.sonar.wsclient.test.internal.DefaultCoverageClient; +import org.sonar.wsclient.test.internal.DefaultTestClient; import org.sonar.wsclient.user.UserClient; import org.sonar.wsclient.user.internal.DefaultUserClient; @@ -157,6 +159,13 @@ public class SonarClient { return new DefaultDuplicationClient(requestFactory); } + /** + * New client to interact with web services related to test + */ + public TestClient testClient() { + return new DefaultTestClient(requestFactory); + } + public SystemClient systemClient() { return new DefaultSystemClient(requestFactory); } diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/CoveredFile.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/CoveredFile.java new file mode 100644 index 00000000000..4eaadd3e603 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/CoveredFile.java @@ -0,0 +1,39 @@ +/* + * 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.wsclient.test; + +import javax.annotation.CheckForNull; + +/** + * @since 4.4 + */ +public interface CoveredFile { + + @CheckForNull + String key(); + + @CheckForNull + String longName(); + + @CheckForNull + Integer coveredLines(); + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestCase.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestCase.java new file mode 100644 index 00000000000..5dd4b8cfd3c --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestCase.java @@ -0,0 +1,42 @@ +/* + * 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.wsclient.test; + +import javax.annotation.CheckForNull; + +/** + * @since 4.4 + */ +public interface TestCase { + + @CheckForNull + String name(); + + @CheckForNull + String status(); + + @CheckForNull + Long durationInMs(); + + @CheckForNull + Integer coveredLines(); + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestClient.java new file mode 100644 index 00000000000..adf070c7151 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestClient.java @@ -0,0 +1,46 @@ +/* + * 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.wsclient.test; + +import java.util.List; + +/** + * Get test information + * + * @since 4.4 + */ +public interface TestClient { + + /** + * Return list of test cases of a test plan + */ + List show(String testPlanKey); + + /** + * Return list of test cases covering a files' line + */ + TestableTestCases testable(String fileKey, Integer line); + + /** + * Return the list of files covered by a test plan's test case + */ + List plan(String testPlanKey, String testCase); +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestableTestCases.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestableTestCases.java new file mode 100644 index 00000000000..0ca5f9f5715 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/TestableTestCases.java @@ -0,0 +1,57 @@ +/* + * 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.wsclient.test; + +import javax.annotation.CheckForNull; + +import java.util.List; + +/** + * @since 4.4 + */ +public interface TestableTestCases { + + List files(); + + List tests(); + + File fileByTest(String testName); + + interface TestCase { + @CheckForNull + String name(); + + @CheckForNull + String status(); + + @CheckForNull + Long durationInMs(); + } + + interface File { + @CheckForNull + String key(); + + @CheckForNull + String longName(); + } + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestClient.java new file mode 100644 index 00000000000..737b8f3fe42 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestClient.java @@ -0,0 +1,167 @@ +/* + * 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.wsclient.test.internal; + +import org.json.simple.JSONValue; +import org.sonar.wsclient.internal.EncodingUtils; +import org.sonar.wsclient.internal.HttpRequestFactory; +import org.sonar.wsclient.test.CoveredFile; +import org.sonar.wsclient.test.TestCase; +import org.sonar.wsclient.test.TestClient; +import org.sonar.wsclient.test.TestableTestCases; +import org.sonar.wsclient.unmarshallers.JsonUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class DefaultTestClient implements TestClient { + + private final HttpRequestFactory requestFactory; + + public DefaultTestClient(HttpRequestFactory requestFactory) { + this.requestFactory = requestFactory; + } + + @Override + public List show(String testPlanKey) { + Map params = EncodingUtils.toMap("key", testPlanKey); + String jsonResult = requestFactory.get("/api/tests/show", params); + + List testCases = new ArrayList(); + Map jRoot = (Map) JSONValue.parse(jsonResult); + List maps = (List) jRoot.get("tests"); + if (maps != null) { + for (final Map json : maps) { + testCases.add(new TestCase() { + @Override + public String name() { + return JsonUtils.getString(json, "name"); + } + + @Override + public String status() { + return JsonUtils.getString(json, "status"); + } + + @Override + public Long durationInMs() { + return JsonUtils.getLong(json, "durationInMs"); + } + + @Override + public Integer coveredLines() { + return JsonUtils.getInteger(json, "coveredLines"); + } + }); + } + } + return testCases; + } + + @Override + public List plan(String testPlanKey, String testCase) { + Map params = EncodingUtils.toMap("key", testPlanKey, "test", testCase); + String jsonResult = requestFactory.get("/api/tests/plan", params); + + List files = new ArrayList(); + Map jRoot = (Map) JSONValue.parse(jsonResult); + List maps = (List) jRoot.get("files"); + if (maps != null) { + for (final Map json : maps) { + files.add(new CoveredFile() { + @Override + public String key() { + return JsonUtils.getString(json, "key"); + } + + @Override + public String longName() { + return JsonUtils.getString(json, "longName"); + } + + @Override + public Integer coveredLines() { + return JsonUtils.getInteger(json, "coveredLines"); + } + }); + } + } + return files; + } + + @Override + public TestableTestCases testable(String fileKey, Integer line) { + Map params = EncodingUtils.toMap("key", fileKey); + params.put("line", line); + String jsonResult = requestFactory.get("/api/tests/testable", params); + + Map jRoot = (Map) JSONValue.parse(jsonResult); + DefaultTestableTestCases coveringTestCases = new DefaultTestableTestCases(); + + List tests = (List) jRoot.get("tests"); + if (tests != null) { + for (final Map json : tests) { + String fileRef = JsonUtils.getString(json, "_ref"); + coveringTestCases.addTest(fileRef, new TestableTestCases.TestCase() { + @Override + public String name() { + return JsonUtils.getString(json, "name"); + } + + @Override + public String status() { + return JsonUtils.getString(json, "status"); + } + + @Override + public Long durationInMs() { + return JsonUtils.getLong(json, "durationInMs"); + } + + }); + } + } + + Map jsonFiles = (Map) jRoot.get("files"); + if (jsonFiles != null) { + for (Map.Entry entry : jsonFiles.entrySet()) { + String ref = entry.getKey(); + final Map file = entry.getValue(); + if (ref != null && file != null) { + coveringTestCases.addFile(ref, new TestableTestCases.File() { + @Override + public String key() { + return JsonUtils.getString(file, "key"); + } + + @Override + public String longName() { + return JsonUtils.getString(file, "longName"); + } + + }); + } + } + } + return coveringTestCases; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestableTestCases.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestableTestCases.java new file mode 100644 index 00000000000..b4beacac2cd --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/test/internal/DefaultTestableTestCases.java @@ -0,0 +1,63 @@ +/* + * 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.wsclient.test.internal; + +import org.sonar.wsclient.test.TestableTestCases; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DefaultTestableTestCases implements TestableTestCases { + + private final List tests = new ArrayList(); + private final Map filesByRef = new HashMap(); + private final Map refsByTest = new HashMap(); + + @Override + public List tests() { + return tests; + } + + @Override + public List files() { + return new ArrayList(filesByRef.values()); + } + + @Override + public File fileByTest(String testName) { + String ref = refsByTest.get(testName); + return ref != null ? filesByRef.get(ref) : null; + } + + public DefaultTestableTestCases addTest(String ref, TestCase testCase) { + tests.add(testCase); + refsByTest.put(testCase.name(), ref); + return this; + } + + public DefaultTestableTestCases addFile(String ref, File file) { + filesByRef.put(ref, file); + return this; + } + +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java index 4a461b9ba7d..0b04d799b51 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java @@ -31,6 +31,7 @@ import org.sonar.wsclient.rule.internal.DefaultRuleClient; import org.sonar.wsclient.source.internal.DefaultSourceClient; import org.sonar.wsclient.system.internal.DefaultSystemClient; import org.sonar.wsclient.test.internal.DefaultCoverageClient; +import org.sonar.wsclient.test.internal.DefaultTestClient; import org.sonar.wsclient.user.internal.DefaultUserClient; import static org.fest.assertions.Assertions.assertThat; @@ -51,6 +52,7 @@ public class SonarClientTest { assertThat(client.sourceClient()).isNotNull().isInstanceOf(DefaultSourceClient.class); assertThat(client.coverageClient()).isNotNull().isInstanceOf(DefaultCoverageClient.class); assertThat(client.duplicationClient()).isNotNull().isInstanceOf(DefaultDuplicationClient.class); + assertThat(client.testClient()).isNotNull().isInstanceOf(DefaultTestClient.class); assertThat(client.systemClient()).isNotNull().isInstanceOf(DefaultSystemClient.class); } diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/test/internal/DefaultTestClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/test/internal/DefaultTestClientTest.java new file mode 100644 index 00000000000..ace79a5cca7 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/test/internal/DefaultTestClientTest.java @@ -0,0 +1,101 @@ +/* + * 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.wsclient.test.internal; + +import com.google.common.base.Charsets; +import com.google.common.io.Resources; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.wsclient.MockHttpServerInterceptor; +import org.sonar.wsclient.internal.HttpRequestFactory; +import org.sonar.wsclient.test.CoveredFile; +import org.sonar.wsclient.test.TestCase; +import org.sonar.wsclient.test.TestClient; +import org.sonar.wsclient.test.TestableTestCases; + +import java.io.IOException; +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class DefaultTestClientTest { + + @Rule + public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor(); + + @Test + public void show_test_cases() throws IOException { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url()); + httpServer.stubResponseBody(Resources.toString(Resources.getResource(this.getClass(), "DefaultTestClientTest/show_test_case.json"), Charsets.UTF_8)); + + TestClient client = new DefaultTestClient(requestFactory); + List tests = client.show("MyTestFile"); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/tests/show?key=MyTestFile"); + assertThat(tests).hasSize(2); + assertThat(tests.get(0).name()).isEqualTo("find_by_params"); + assertThat(tests.get(0).status()).isEqualTo("OK"); + assertThat(tests.get(0).durationInMs()).isEqualTo(10L); + assertThat(tests.get(0).coveredLines()).isEqualTo(89); + } + + @Test + public void show_testable() throws IOException { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url()); + httpServer.stubResponseBody(Resources.toString(Resources.getResource(this.getClass(), "DefaultTestClientTest/show_testable.json"), Charsets.UTF_8)); + + TestClient client = new DefaultTestClient(requestFactory); + TestableTestCases coveringTestCases = client.testable("MyFile", 10); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/tests/testable?key=MyFile&line=10"); + assertThat(coveringTestCases.tests()).hasSize(1); + assertThat(coveringTestCases.files()).hasSize(1); + + TestableTestCases.TestCase testCase = coveringTestCases.tests().get(0); + assertThat(testCase.name()).isEqualTo("find_by_params"); + assertThat(testCase.status()).isEqualTo("OK"); + assertThat(testCase.durationInMs()).isEqualTo(10L); + + TestableTestCases.File file = coveringTestCases.fileByTest("find_by_params"); + assertThat(file.key()).isEqualTo("org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java"); + assertThat(file.longName()).isEqualTo("src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java"); + + assertThat(coveringTestCases.fileByTest("unknown")).isNull(); + } + + @Test + public void show_plan() throws IOException { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url()); + httpServer.stubResponseBody(Resources.toString(Resources.getResource(this.getClass(), "DefaultTestClientTest/show_plan.json"), Charsets.UTF_8)); + + TestClient client = new DefaultTestClient(requestFactory); + List files = client.plan("MyTestFile", "find_by_params"); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/tests/plan?key=MyTestFile&test=find_by_params"); + assertThat(files).hasSize(2); + + CoveredFile file = files.get(0); + assertThat(file.key()).isEqualTo("org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/paging/PagedResult.java"); + assertThat(file.longName()).isEqualTo("src/main/java/org/sonar/server/paging/PagedResult.java"); + assertThat(file.coveredLines()).isEqualTo(5); + } + +} diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_plan.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_plan.json new file mode 100644 index 00000000000..ce75518aefa --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_plan.json @@ -0,0 +1,14 @@ +{ + "files": [ + { + "key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/paging/PagedResult.java", + "longName": "src/main/java/org/sonar/server/paging/PagedResult.java", + "coveredLines": 5 + }, + { + "key": "org.codehaus.sonar:sonar-server:src/main/java/org/sonar/server/rule/RuleDocumentParser.java", + "longName": "src/main/java/org/sonar/server/rule/RuleDocumentParser.java", + "coveredLines": 38 + } + ] +} diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_test_case.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_test_case.json new file mode 100644 index 00000000000..fd6076387e6 --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_test_case.json @@ -0,0 +1,16 @@ +{ + "tests": [ + { + "name": "find_by_params", + "status": "OK", + "durationInMs": 10, + "coveredLines" : 89 + }, + { + "name": "find_rules_by_characteristics", + "status": "ERROR", + "durationInMs": 97, + "coveredLines" : 0 + } + ] +} diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_testable.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_testable.json new file mode 100644 index 00000000000..fd00ccea046 --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/test/internal/DefaultTestClientTest/show_testable.json @@ -0,0 +1,16 @@ +{ + "tests": [ + { + "_ref": "1", + "name": "find_by_params", + "status": "OK", + "durationInMs": 10 + } + ], + "files": { + "1": { + "key": "org.codehaus.sonar:sonar-server:src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java", + "longName": "src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java" + } + } +}