From 455c2922640c42a504caf3e32beb38ba5c64905b Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 19 Apr 2013 10:23:04 +0200 Subject: [PATCH] SONAR-3755 new sonar-ws-client API for issues --- sonar-ws-client/pom.xml | 52 ++++++-- .../java/org/sonar/wsclient/SonarClient.java | 73 +++++++++++ .../wsclient/internal/EncodingUtils.java | 55 +++++++++ .../wsclient/internal/HttpRequestFactory.java | 68 +++++++++++ .../sonar/wsclient/internal/package-info.java | 21 ++++ .../wsclient/issue/DefaultIssueClient.java | 78 ++++++++++++ .../java/org/sonar/wsclient/issue/Issue.java | 113 ++++++++++++++++++ .../org/sonar/wsclient/issue/IssueChange.java | 81 +++++++++++++ .../org/sonar/wsclient/issue/IssueClient.java | 37 ++++++ .../org/sonar/wsclient/issue/IssueParser.java | 37 ++++++ .../org/sonar/wsclient/issue/IssueQuery.java | 110 +++++++++++++++++ .../java/org/sonar/wsclient/issue/Issues.java | 39 ++++++ .../org/sonar/wsclient/issue/NewIssue.java | 85 +++++++++++++ .../sonar/wsclient/issue/package-info.java | 21 ++++ .../org/sonar/wsclient/MockHttpServer.java | 96 +++++++++++++++ .../wsclient/MockHttpServerInterceptor.java | 52 ++++++++ .../org/sonar/wsclient/SonarClientTest.java | 54 +++++++++ .../wsclient/internal/EncodingUtilsTest.java | 42 +++++++ .../internal/HttpRequestFactoryTest.java | 72 +++++++++++ .../issue/DefaultIssueClientTest.java | 91 ++++++++++++++ .../sonar/wsclient/issue/IssueChangeTest.java | 54 +++++++++ .../sonar/wsclient/issue/IssueParserTest.java | 65 ++++++++++ .../sonar/wsclient/issue/IssueQueryTest.java | 67 +++++++++++ .../sonar/wsclient/issue/NewIssueTest.java | 56 +++++++++ .../issue/IssueParserTest/search.json | 32 +++++ 25 files changed, 1543 insertions(+), 8 deletions(-) create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/internal/package-info.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueChange.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java create mode 100644 sonar-ws-client/src/main/java/org/sonar/wsclient/issue/package-info.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServer.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServerInterceptor.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/internal/EncodingUtilsTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueChangeTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java create mode 100644 sonar-ws-client/src/test/java/org/sonar/wsclient/issue/NewIssueTest.java create mode 100644 sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json diff --git a/sonar-ws-client/pom.xml b/sonar-ws-client/pom.xml index e0b7dc6febb..7bb9caf1129 100644 --- a/sonar-ws-client/pom.xml +++ b/sonar-ws-client/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.codehaus.sonar @@ -16,8 +17,8 @@ - + com.googlecode.json-simple json-simple @@ -26,13 +27,22 @@ commons-httpclient commons-httpclient 3.1 - true + provided org.apache.httpcomponents httpclient ${httpclient4.version} - true + provided + + + com.github.kevinsawicki + http-request + + + com.google.code.findbugs + jsr305 + provided @@ -85,6 +95,32 @@ + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + true + true + + + com.github.kevinsawicki.http + org.sonar.wsclient.kevinsawicki + + + org.json.simple + org.sonar.wsclient.jsonsimple + + + + + + org.apache.felix maven-bundle-plugin @@ -95,12 +131,12 @@ !* org.apache.httpcomponents.httpclient;bundle-version="${httpclient4.version}";optional="true", org.apache.httpcomponents.httpcore;bundle-version="${httpclient4.version}";optional="true", - com.googlecode.json-simple !.,org.sonar.wsclient, org.sonar.wsclient.connectors, - org.sonar.wsclient.services - J2SE-1.5 + org.sonar.wsclient.services + + J2SE-1.6 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 new file mode 100644 index 00000000000..2a2555fcd07 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/SonarClient.java @@ -0,0 +1,73 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient; + +import org.sonar.wsclient.internal.HttpRequestFactory; +import org.sonar.wsclient.issue.DefaultIssueClient; +import org.sonar.wsclient.issue.IssueClient; + +/** + * @since 3.6 + */ +public class SonarClient { + + private final HttpRequestFactory requestFactory; + + private SonarClient(Builder builder) { + requestFactory = new HttpRequestFactory(builder.url, builder.login, builder.password); + } + + public IssueClient issueClient() { + return new DefaultIssueClient(requestFactory); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String login, password, url; + + private Builder() { + } + + public Builder login(String login) { + this.login = login; + return this; + } + + public Builder password(String password) { + this.password = password; + return this; + } + + public Builder url(String url) { + this.url = url; + return this; + } + + public SonarClient build() { + if (url == null || "".equals(url)) { + throw new IllegalStateException("Server URL must be set"); + } + return new SonarClient(this); + } + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java new file mode 100644 index 00000000000..0fa31de57c9 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/EncodingUtils.java @@ -0,0 +1,55 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.internal; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Not an API, please do not directly use this class. + */ +public class EncodingUtils { + + private static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ"; + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + private EncodingUtils() { + // only static methods + } + + public static String toQueryParam(String[] strings) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String string : strings) { + if (!first) { + sb.append(','); + } + sb.append(string); + first = false; + } + return sb.toString(); + } + + public static String toQueryParam(Date d, boolean includeTime) { + String format = (includeTime ? DATETIME_FORMAT : DATE_FORMAT); + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + return dateFormat.format(d); + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java new file mode 100644 index 00000000000..4b23653ea68 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/HttpRequestFactory.java @@ -0,0 +1,68 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.internal; + +import com.github.kevinsawicki.http.HttpRequest; + +import java.util.Map; + +/** + * Not an API, please do not directly use this class. + */ +public class HttpRequestFactory { + + static final int CONNECT_TIMEOUT_MILLISECONDS = 30000; + static final int READ_TIMEOUT_MILLISECONDS = 60000; + + private final String baseURl; + private final String login, password; + + public HttpRequestFactory(String baseURl, String login, String password) { + this.baseURl = baseURl; + this.login = login; + this.password = password; + } + + public HttpRequest get(String wsUrl, Map queryParams) { + HttpRequest request = HttpRequest.get(baseURl + wsUrl, queryParams, true); + return prepare(request); + } + + public HttpRequest post(String wsUrl, Map queryParams) { + HttpRequest request = HttpRequest.post(baseURl + wsUrl, queryParams, true); + return prepare(request); + } + + private HttpRequest prepare(HttpRequest request) { + request + .acceptGzipEncoding() + .uncompress(true) + .acceptJson() + .acceptCharset(HttpRequest.CHARSET_UTF8) + .connectTimeout(CONNECT_TIMEOUT_MILLISECONDS) + .readTimeout(READ_TIMEOUT_MILLISECONDS) + .trustAllCerts() + .trustAllCerts(); + if (login != null) { + request.basic(login, password); + } + return request; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/package-info.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/package-info.java new file mode 100644 index 00000000000..81ddb1053dc --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/internal/package-info.java @@ -0,0 +1,21 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 02 + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.wsclient.internal; \ No newline at end of file diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java new file mode 100644 index 00000000000..f9a93ee3a77 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/DefaultIssueClient.java @@ -0,0 +1,78 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import com.github.kevinsawicki.http.HttpRequest; +import org.sonar.wsclient.internal.HttpRequestFactory; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Do not instantiate this class, but use {@link org.sonar.wsclient.SonarClient#issueClient()}. + */ +public class DefaultIssueClient implements IssueClient { + + private final HttpRequestFactory requestFactory; + private final IssueParser parser; + + /** + * For internal use. Use {@link org.sonar.wsclient.SonarClient} to get an instance. + */ + public DefaultIssueClient(HttpRequestFactory requestFactory) { + this.requestFactory = requestFactory; + this.parser = new IssueParser(); + } + + public Issues find(IssueQuery query) { + HttpRequest request = requestFactory.get(IssueQuery.BASE_URL, query.urlParams()); + if (!request.ok()) { + throw new IllegalStateException("Fail to search for issues. Bad HTTP response status: " + request.code()); + } + String json = request.body("UTF-8"); + return parser.parseIssues(json); + } + + @Override + public void apply(String issueKey, IssueChange change) { + if (!change.urlParams().isEmpty()) { + Map queryParams = new LinkedHashMap(change.urlParams()); + queryParams.put("key", issueKey); + HttpRequest request = requestFactory.post(IssueChange.BASE_URL, queryParams); + if (!request.ok()) { + throw new IllegalStateException("Fail to change issue " + issueKey + ".Bad HTTP response status: " + request.code()); + } + } + } + + @Override + public void create(NewIssue newIssue) { + HttpRequest request = requestFactory.post(NewIssue.BASE_URL, newIssue.urlParams()); + if (!request.ok()) { + throw new IllegalStateException("Fail to create issue. Bad HTTP response status: " + request.code()); + } + } + + @Override + public void comment(String issueKey, String comment) { + apply(issueKey, IssueChange.create().comment(comment)); + } + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java new file mode 100644 index 00000000000..f7149189477 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issue.java @@ -0,0 +1,113 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar{} if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.sonar.wsclient.unmarshallers.JsonUtils; + +import java.util.Collections; +import java.util.Date; +import java.util.Map; + +/** + * @since 3.6 + */ +public class Issue { + + private final Map json; + + Issue(Map json) { + this.json = json; + } + + /** + * Unique key + */ + public String key() { + return JsonUtils.getString(json, "key"); + } + + public String componentKey() { + return JsonUtils.getString(json, "component"); + } + + public String ruleKey() { + return JsonUtils.getString(json, "rule"); + } + + public String severity() { + return JsonUtils.getString(json, "severity"); + } + + public String title() { + return JsonUtils.getString(json, "title"); + } + + public String description() { + return JsonUtils.getString(json, "desc"); + } + + public Integer line() { + return JsonUtils.getInteger(json, "line"); + } + + public Double cost() { + return JsonUtils.getDouble(json, "cost"); + } + + public String status() { + return JsonUtils.getString(json, "status"); + } + + public String resolution() { + return JsonUtils.getString(json, "resolution"); + } + + public String userLogin() { + return JsonUtils.getString(json, "userLogin"); + } + + public String assignee() { + return JsonUtils.getString(json, "assignee"); + } + + public Date createdAt() { + return JsonUtils.getDateTime(json, "createdAt"); + } + + public Date updatedAt() { + return JsonUtils.getDateTime(json, "updatedAt"); + } + + public Date closedAt() { + return JsonUtils.getDateTime(json, "closedAt"); + } + + public String attribute(String key) { + return attributes().get(key); + } + + public Map attributes() { + Map attr = (Map) json.get("attr"); + if (attr == null) { + return Collections.emptyMap(); + } + return attr; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueChange.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueChange.java new file mode 100644 index 00000000000..5179770d966 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueChange.java @@ -0,0 +1,81 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import javax.annotation.Nullable; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @since 3.6 + */ +public class IssueChange { + static final String BASE_URL = "/api/issues/change"; + private final Map params = new LinkedHashMap(); + + private IssueChange() { + } + + public static IssueChange create() { + return new IssueChange(); + } + + Map urlParams() { + return params; + } + + public IssueChange severity(String s) { + params.put("newSeverity", s); + return this; + } + + /** + * Add a comment + */ + public IssueChange comment(String s) { + params.put("newComment", s); + return this; + } + + public IssueChange cost(Double d) { + params.put("newCost", d); + return this; + } + + public IssueChange resolution(String s) { + params.put("newResolution", s); + return this; + } + + public IssueChange assignee(String login) { + params.put("newAssignee", login); + return this; + } + + public IssueChange attribute(String key, @Nullable String value) { + if (value == null) { + params.put("newAttr[" + key + "]", ""); + } else { + params.put("newAttr[" + key + "]", value); + } + return this; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java new file mode 100644 index 00000000000..56498620408 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueClient.java @@ -0,0 +1,37 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +/** + * @since 3.6 + */ +public interface IssueClient { + + Issues find(IssueQuery query); + + void apply(String issueKey, IssueChange change); + + void create(NewIssue issue); + + /** + * Shortcut for {@code #apply(issueKey, IssueChange.create().comment(comment)} + */ + void comment(String issueKey, String comment); +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java new file mode 100644 index 00000000000..c763e1899f1 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueParser.java @@ -0,0 +1,37 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.json.simple.JSONValue; + +import java.util.List; +import java.util.Map; + +class IssueParser { + Issues parseIssues(String json) { + Issues result = new Issues(); + Map jRoot = (Map) JSONValue.parse(json); + List jIssues = (List) jRoot.get("issues"); + for (Map jIssue : jIssues) { + result.add(new Issue(jIssue)); + } + return result; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java new file mode 100644 index 00000000000..baa177b59cf --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java @@ -0,0 +1,110 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.sonar.wsclient.internal.EncodingUtils; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @since 3.6 + */ +public class IssueQuery { + + static final String BASE_URL = "/api/issues/search"; + private final Map params = new HashMap(); + + private IssueQuery() { + } + + public static IssueQuery create() { + return new IssueQuery(); + } + + Map urlParams() { + return params; + } + + public IssueQuery keys(String... keys) { + return addParam("keys", keys); + } + + public IssueQuery severities(String... severities) { + return addParam("severities", severities); + } + + public IssueQuery statuses(String... statuses) { + return addParam("statuses", statuses); + } + + public IssueQuery resolutions(String... resolutions) { + return addParam("resolutions", resolutions); + } + + public IssueQuery components(String... components) { + return addParam("components", components); + } + + public IssueQuery componentRoots(String... componentRoots) { + return addParam("componentRoots", componentRoots); + } + + public IssueQuery rules(String... s) { + return addParam("rules", s); + } + + public IssueQuery userLogins(String... s) { + return addParam("userLogins", s); + } + + public IssueQuery assignees(String... s) { + return addParam("assignees", s); + } + + public IssueQuery createdAfter(Date d) { + params.put("createdAfter", EncodingUtils.toQueryParam(d, true)); + return this; + } + + public IssueQuery createdBefore(Date d) { + params.put("createdBefore", EncodingUtils.toQueryParam(d, true)); + return this; + } + + public IssueQuery limit(int limit) { + params.put("limit", limit); + return this; + } + + public IssueQuery offset(int offset) { + params.put("offset", offset); + return this; + } + + private IssueQuery addParam(String key, String[] values) { + if (values != null) { + params.put(key, EncodingUtils.toQueryParam(values)); + } + return this; + } + +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java new file mode 100644 index 00000000000..51ff417cf60 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/Issues.java @@ -0,0 +1,39 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import java.util.ArrayList; +import java.util.List; + +/** + * @since 3.6 + */ +public class Issues { + + private final List list = new ArrayList(); + + Issues add(Issue issue) { + list.add(issue); + return this; + } + public List list() { + return list; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java new file mode 100644 index 00000000000..ce6d7cd0abb --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/NewIssue.java @@ -0,0 +1,85 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import java.util.HashMap; +import java.util.Map; + +/** + * @since 3.6 + */ +public class NewIssue { + static final String BASE_URL = "/api/issues/create"; + private final Map params = new HashMap(); + + private NewIssue() { + } + + public static NewIssue create() { + return new NewIssue(); + } + + Map urlParams() { + return params; + } + + public NewIssue severity(String s) { + params.put("severity", s); + return this; + } + + public NewIssue component(String s) { + params.put("component", s); + return this; + } + + public NewIssue rule(String s) { + params.put("rule", s); + return this; + } + + /** + * Optional line + */ + public NewIssue line(int i) { + params.put("line", i); + return this; + } + + public NewIssue description(String s) { + params.put("desc", s); + return this; + } + + public NewIssue title(String s) { + params.put("title", s); + return this; + } + + public NewIssue cost(Double d) { + params.put("cost", d); + return this; + } + + public NewIssue attribute(String key, String value) { + params.put("attr[" + key + "]", value); + return this; + } +} diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/package-info.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/package-info.java new file mode 100644 index 00000000000..fdc9b467a58 --- /dev/null +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/package-info.java @@ -0,0 +1,21 @@ +/* + * Sonar Runner - Implementation + * Copyright (C) 2011 SonarSource + * dev@sonar.codehaus.org + * + * This program 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. + * + * This program 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 02 + */ +@javax.annotation.ParametersAreNonnullByDefault +package org.sonar.wsclient.issue; \ No newline at end of file diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServer.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServer.java new file mode 100644 index 00000000000..f39cdf55c0d --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServer.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.wsclient; + +import org.apache.commons.io.IOUtils; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.apache.commons.io.IOUtils.write; + +public class MockHttpServer { + private Server server; + private String responseBody; + private int responseStatus = SC_OK; + private String requestBody, requestPath; + private Map requestHeaders = new HashMap(); + + public void start() throws Exception { + // 0 is random available port + server = new Server(0); + server.setHandler(getMockHandler()); + server.start(); + } + + public Handler getMockHandler() { + Handler handler = new AbstractHandler() { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException { + requestPath = baseRequest.getUri().toString(); + requestBody = IOUtils.toString(baseRequest.getInputStream()); + requestHeaders.clear(); + Enumeration headerNames = baseRequest.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String headerName = (String)headerNames.nextElement(); + requestHeaders.put(headerName, baseRequest.getHeader(headerName)); + } + response.setStatus(responseStatus); + response.setContentType("application/json;charset=utf-8"); + write(responseBody, response.getOutputStream()); + baseRequest.setHandled(true); + } + }; + return handler; + } + + public void stop() { + try { + if (server != null) { + server.stop(); + } + } catch (Exception e) { + throw new IllegalStateException("Fail to stop HTTP server", e); + } + } + + public MockHttpServer doReturnBody(String responseBody) { + this.responseBody = responseBody; + return this; + } + + public MockHttpServer doReturnStatus(int status) { + this.responseStatus = status; + return this; + } + + public String requestBody() { + return requestBody; + } + + public String requestPath() { + return requestPath; + } + + public Map requestHeaders() { + return requestHeaders; + } + + public int getPort() { + return server.getConnectors()[0].getLocalPort(); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServerInterceptor.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServerInterceptor.java new file mode 100644 index 00000000000..bdebb27d399 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/MockHttpServerInterceptor.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011-2013 SonarSource SA + * All rights reserved + * mailto:contact AT sonarsource DOT com + */ +package org.sonar.wsclient; + +import org.junit.rules.ExternalResource; + +import java.util.Map; + +public final class MockHttpServerInterceptor extends ExternalResource { + + private MockHttpServer server; + + @Override + protected final void before() throws Throwable { + server = new MockHttpServer(); + server.start(); + } + + @Override + protected void after() { + server.stop(); + } + + public MockHttpServerInterceptor doReturnBody(String body) { + server.doReturnBody(body); + return this; + } + + public MockHttpServerInterceptor doReturnStatus(int status) { + server.doReturnStatus(status); + return this; + } + + public String requestedPath() { + return server.requestPath(); + } + + public Map requestHeaders() { + return server.requestHeaders(); + } + + public int port() { + return server.getPort(); + } + + public String url() { + return "http://localhost:" + port(); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000000..2f406482939 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/SonarClientTest.java @@ -0,0 +1,54 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient; + +import org.junit.Test; +import org.sonar.wsclient.issue.DefaultIssueClient; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class SonarClientTest { + @Test + public void should_build_client() { + SonarClient client = SonarClient.builder().url("http://localhost:9000").build(); + assertThat(client.issueClient()).isNotNull().isInstanceOf(DefaultIssueClient.class); + } + + @Test + public void url_should_not_be_null() { + try { + SonarClient.builder().build(); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Server URL must be set"); + } + } + + @Test + public void url_should_not_be_empty() { + try { + SonarClient.builder().url("").build(); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Server URL must be set"); + } + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/EncodingUtilsTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/EncodingUtilsTest.java new file mode 100644 index 00000000000..c01d16e9e75 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/EncodingUtilsTest.java @@ -0,0 +1,42 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.internal; + +import org.junit.Test; + +import java.util.Date; + +import static org.fest.assertions.Assertions.assertThat; + +public class EncodingUtilsTest { + @Test + public void test_date_param() { + + assertThat(EncodingUtils.toQueryParam(new Date(), false)).isNotEmpty().matches("\\d{4}-\\d{2}-\\d{2}"); + assertThat(EncodingUtils.toQueryParam(new Date(), true)).isNotEmpty(); + } + + @Test + public void test_string_array_param() { + assertThat(EncodingUtils.toQueryParam(new String[]{"foo", "bar"})).isEqualTo("foo,bar"); + assertThat(EncodingUtils.toQueryParam(new String[]{"foo"})).isEqualTo("foo"); + assertThat(EncodingUtils.toQueryParam(new String[]{""})).isEqualTo(""); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java new file mode 100644 index 00000000000..5a5164e8eab --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/internal/HttpRequestFactoryTest.java @@ -0,0 +1,72 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.internal; + +import com.github.kevinsawicki.http.HttpRequest; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.wsclient.MockHttpServerInterceptor; + +import java.util.Collections; + +import static org.fest.assertions.Assertions.assertThat; + +public class HttpRequestFactoryTest { + @Rule + public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor(); + + @Test + public void test_get() { + httpServer.doReturnStatus(200).doReturnBody("list of issues"); + + HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), null, null); + HttpRequest request = factory.get("/api/issues", Collections.emptyMap()); + + assertThat(request.method()).isEqualTo("GET"); + assertThat(request.body()).isEqualTo("list of issues"); + assertThat(request.code()).isEqualTo(200); + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues"); + } + + @Test + public void test_post() { + httpServer.doReturnStatus(200); + + HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), null, null); + HttpRequest request = factory.post("/api/issues/change", Collections.emptyMap()); + + assertThat(request.method()).isEqualTo("POST"); + assertThat(request.code()).isEqualTo(200); + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/change"); + } + + @Test + public void test_authentication() { + httpServer.doReturnStatus(200).doReturnBody("list of issues"); + + HttpRequestFactory factory = new HttpRequestFactory(httpServer.url(), "karadoc", "legrascestlavie"); + HttpRequest request = factory.get("/api/issues", Collections.emptyMap()); + + assertThat(request.body()).isEqualTo("list of issues"); + assertThat(request.code()).isEqualTo(200); + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues"); + assertThat(httpServer.requestHeaders().get("Authorization")).isEqualTo("Basic a2FyYWRvYzpsZWdyYXNjZXN0bGF2aWU="); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java new file mode 100644 index 00000000000..d37710094e4 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/DefaultIssueClientTest.java @@ -0,0 +1,91 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.junit.Rule; +import org.junit.Test; +import org.sonar.wsclient.MockHttpServerInterceptor; +import org.sonar.wsclient.internal.HttpRequestFactory; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class DefaultIssueClientTest { + @Rule + public MockHttpServerInterceptor httpServer = new MockHttpServerInterceptor(); + + @Test + public void should_find_issues() { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null); + httpServer.doReturnBody("{\"issues\": [{\"key\": \"ABCDE\"}]}"); + + IssueClient client = new DefaultIssueClient(requestFactory); + IssueQuery query = IssueQuery.create().keys("ABCDE"); + Issues issues = client.find(query); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/search?keys=ABCDE"); + assertThat(issues.list()).hasSize(1); + assertThat(issues.list().get(0).key()).isEqualTo("ABCDE"); + } + + @Test + public void should_fail_to_find_issues() { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null); + httpServer.doReturnStatus(500); + + IssueClient client = new DefaultIssueClient(requestFactory); + try { + client.find(IssueQuery.create()); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Fail to search for issues. Bad HTTP response status: 500"); + } + } + + @Test + public void should_apply_change() { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null); + + IssueClient client = new DefaultIssueClient(requestFactory); + client.apply("ABCDE", IssueChange.create().severity("BLOCKER").comment("because!")); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/change?newSeverity=BLOCKER&newComment=because!&key=ABCDE"); + } + + @Test + public void should_not_apply_empty_change() { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null); + + IssueClient client = new DefaultIssueClient(requestFactory); + client.apply("ABCDE", IssueChange.create()); + + assertThat(httpServer.requestedPath()).isNull(); + } + + @Test + public void should_create_issue() { + HttpRequestFactory requestFactory = new HttpRequestFactory(httpServer.url(), null, null); + + IssueClient client = new DefaultIssueClient(requestFactory); + client.create(NewIssue.create().component("Action.java").rule("squid:AvoidCycle")); + + assertThat(httpServer.requestedPath()).isEqualTo("/api/issues/create?component=Action.java&rule=squid:AvoidCycle"); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueChangeTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueChangeTest.java new file mode 100644 index 00000000000..4d3be57b38d --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueChangeTest.java @@ -0,0 +1,54 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; + +public class IssueChangeTest { + @Test + public void should_create_empty_change() { + IssueChange change = IssueChange.create(); + assertThat(change.urlParams()).isEmpty(); + } + + @Test + public void should_create_change() { + IssueChange change = IssueChange.create() + .comment("this is a comment") + .assignee("lancelot") + .attribute("JIRA", "FOO-1234") + .attribute("LINK", null) + .cost(4.2) + .resolution("FIXED") + .severity("BLOCKER"); + assertThat(change.urlParams()).hasSize(7).includes( + entry("newComment", "this is a comment"), + entry("newAssignee", "lancelot"), + entry("newAttr[JIRA]", "FOO-1234"), + entry("newAttr[LINK]", ""), + entry("newCost", 4.2), + entry("newResolution", "FIXED"), + entry("newSeverity", "BLOCKER") + ); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java new file mode 100644 index 00000000000..46d714e3bf1 --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueParserTest.java @@ -0,0 +1,65 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class IssueParserTest { + @Test + public void test_GET_search() throws Exception { + String json = IOUtils.toString(getClass().getResourceAsStream("/org/sonar/wsclient/issue/IssueParserTest/search.json")); + Issues issues = new IssueParser().parseIssues(json); + assertThat(issues).isNotNull(); + List list = issues.list(); + assertThat(list).hasSize(2); + Issue first = list.get(0); + assertThat(first.key()).isEqualTo("ABCDE"); + assertThat(first.componentKey()).isEqualTo("Action.java"); + assertThat(first.ruleKey()).isEqualTo("squid:AvoidCycle"); + assertThat(first.severity()).isEqualTo("CRITICAL"); + assertThat(first.line()).isEqualTo(10); + assertThat(first.resolution()).isEqualTo("FIXED"); + assertThat(first.status()).isEqualTo("OPEN"); + assertThat(first.assignee()).isEqualTo("karadoc"); + assertThat(first.description()).isEqualTo("the desc"); + assertThat(first.cost()).isEqualTo(4.2); + assertThat(first.title()).isEqualTo("the title"); + assertThat(first.userLogin()).isEqualTo("perceval"); + assertThat(first.createdAt()).isNotNull(); + assertThat(first.updatedAt()).isNotNull(); + assertThat(first.closedAt()).isNotNull(); + assertThat(first.attribute("JIRA")).isEqualTo("FOO-1234"); + assertThat(first.attribute("OTHER")).isNull(); + assertThat(first.attributes()).hasSize(1); + + Issue second = list.get(1); + assertThat(second.key()).isEqualTo("FGHIJ"); + assertThat(second.line()).isNull(); + assertThat(second.cost()).isNull(); + assertThat(second.description()).isNull(); + assertThat(second.attribute("JIRA")).isNull(); + assertThat(second.attributes()).isEmpty(); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java new file mode 100644 index 00000000000..429ce551fab --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java @@ -0,0 +1,67 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; + +public class IssueQueryTest { + @Test + public void get_all_issues() { + IssueQuery query = IssueQuery.create(); + assertThat(query.urlParams()).isEmpty(); + } + + @Test + public void get_all_issues_by_parameter() { + IssueQuery query = IssueQuery.create() + .keys("ABCDE", "FGHIJ") + .assignees("arthur", "perceval") + .components("Action.java", "Filter.java") + .componentRoots("struts") + .resolutions("FIXED", "FALSE-POSITIVE") + .rules("squid:AvoidCycle") + .statuses("OPEN", "CLOSED") + .severities("BLOCKER", "INFO") + .userLogins("login1", "login2") + .limit(5) + .offset(4); + + assertThat(query.urlParams()).hasSize(11); + assertThat(query.urlParams()).includes(entry("keys", "ABCDE,FGHIJ")); + assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval")); + assertThat(query.urlParams()).includes(entry("components", "Action.java,Filter.java")); + assertThat(query.urlParams()).includes(entry("componentRoots", "struts")); + assertThat(query.urlParams()).includes(entry("resolutions", "FIXED,FALSE-POSITIVE")); + assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED")); + assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO")); + assertThat(query.urlParams()).includes(entry("userLogins", "login1,login2")); + assertThat(query.urlParams()).includes(entry("limit", 5)); + assertThat(query.urlParams()).includes(entry("offset", 4)); + } + + @Test + public void should_ignore_null_values() { + IssueQuery query = IssueQuery.create().severities(null); + assertThat(query.urlParams()).isEmpty(); + } +} diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/NewIssueTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/NewIssueTest.java new file mode 100644 index 00000000000..af6d105541f --- /dev/null +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/NewIssueTest.java @@ -0,0 +1,56 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.wsclient.issue; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.MapAssert.entry; + +public class NewIssueTest { + @Test + public void test_create_empty() { + assertThat(NewIssue.create().urlParams()).isEmpty(); + } + + @Test + public void test_create() { + NewIssue newIssue = NewIssue.create() + .component("Action.java") + .cost(4.2) + .description("the desc") + .line(123) + .rule("squid:AvoidCycle") + .severity("BLOCKER") + .title("the title") + .attribute("JIRA", "FOO-123"); + + assertThat(newIssue.urlParams()).hasSize(8).includes( + entry("component", "Action.java"), + entry("cost", 4.2), + entry("desc", "the desc"), + entry("line", 123), + entry("rule", "squid:AvoidCycle"), + entry("severity", "BLOCKER"), + entry("title", "the title"), + entry("attr[JIRA]", "FOO-123") + ); + } +} diff --git a/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json new file mode 100644 index 00000000000..85b84cea03c --- /dev/null +++ b/sonar-ws-client/src/test/resources/org/sonar/wsclient/issue/IssueParserTest/search.json @@ -0,0 +1,32 @@ +{ + "issues": [ + { + "key": "ABCDE", + "component": "Action.java", + "rule": "squid:AvoidCycle", + "severity": "CRITICAL", + "line": 10, + "resolution": "FIXED", + "status": "OPEN", + "assignee": "karadoc", + "cost": 4.2, + "desc": "the desc", + "title": "the title", + "userLogin": "perceval", + "createdAt": "2013-05-18T12:45:34+0200", + "updatedAt": "2013-05-18T13:45:34+0200", + "closedAt": "2013-05-18T14:45:34+0200", + "attr": { + "JIRA": "FOO-1234" + } + }, + { + "key": "FGHIJ", + "component": "Filter.java", + "rule": "squid:NullRef", + "severity": "BLOCKER", + "resolution": "FIXED", + "status": "OPEN" + } + ] +} \ No newline at end of file -- 2.39.5