aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java7
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleRequest.java59
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleResponse.java64
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java106
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/server/ws/SimpleRequestTest.java44
-rw-r--r--sonar-server/pom.xml5
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java8
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java41
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java4
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/filter/IssueFilterWsTest.java21
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java55
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java2
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule/RuleTagsWsTest.java26
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule/RulesWsTest.java6
-rw-r--r--sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java18
-rw-r--r--sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java127
-rw-r--r--sonar-server/src/test/java/org/sonar/server/ws/WsTester.java98
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/ws/ListingWsTest/index.json (renamed from sonar-server/src/test/resources/org/sonar/server/ws/ListingWebServiceTest/index.json)0
-rw-r--r--sonar-testing-harness/pom.xml30
-rw-r--r--sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java216
21 files changed, 565 insertions, 383 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java
index a3e00fdc02a..3892b275ebc 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Request.java
@@ -65,4 +65,15 @@ public abstract class Request {
String s = param(key);
return s == null ? defaultValue : Integer.parseInt(s);
}
+
+ @CheckForNull
+ public Boolean booleanParam(String key) {
+ String s = param(key);
+ return s == null ? null : Boolean.parseBoolean(s);
+ }
+
+ public boolean booleanParam(String key, boolean defaultValue) {
+ String s = param(key);
+ return s == null ? defaultValue : Boolean.parseBoolean(s);
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java
index 6ca4184bd17..b22d92d1455 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/Response.java
@@ -31,6 +31,11 @@ import java.io.OutputStream;
*/
public interface Response {
+ interface Stream {
+ Stream setMediaType(String s);
+ OutputStream output();
+ }
+
int status();
Response setStatus(int httpStatus);
@@ -39,6 +44,6 @@ public interface Response {
XmlWriter newXmlWriter();
- OutputStream stream();
+ Stream stream();
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleRequest.java
deleted file mode 100644
index 9689d060db6..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleRequest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.api.server.ws;
-
-import com.google.common.collect.Maps;
-
-import javax.annotation.CheckForNull;
-import java.util.Map;
-
-public class SimpleRequest extends Request {
-
- private String method = "GET";
- private Map<String, String> params = Maps.newHashMap();
-
- @Override
- public String method() {
- return method;
- }
-
- public SimpleRequest setMethod(String s) {
- this.method = s;
- return this;
- }
-
- public SimpleRequest setParams(Map<String, String> m) {
- this.params = m;
- return this;
- }
-
- public SimpleRequest setParam(String key, @CheckForNull String value) {
- if (value != null) {
- params.put(key, value);
- }
- return this;
- }
-
- @Override
- @CheckForNull
- public String param(String key) {
- return params.get(key);
- }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleResponse.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleResponse.java
deleted file mode 100644
index d2de13b9f63..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/SimpleResponse.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.api.server.ws;
-
-import org.apache.commons.io.Charsets;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.utils.text.XmlWriter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-public class SimpleResponse implements Response {
- private int httpStatus = 200;
- private final ByteArrayOutputStream output = new ByteArrayOutputStream();
-
- @Override
- public JsonWriter newJsonWriter() {
- return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
- }
-
- @Override
- public XmlWriter newXmlWriter() {
- return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
- }
-
- @Override
- public OutputStream stream() {
- return output;
- }
-
- // for unit testing
- public String outputAsString() {
- return new String(output.toByteArray(), Charsets.UTF_8);
- }
-
- @Override
- public int status() {
- return httpStatus;
- }
-
- @Override
- public Response setStatus(int httpStatus) {
- this.httpStatus = httpStatus;
- return this;
- }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java
new file mode 100644
index 00000000000..f7f4f8f738d
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/RequestTest.java
@@ -0,0 +1,106 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.ws;
+
+import org.junit.Test;
+
+import javax.annotation.CheckForNull;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class RequestTest {
+
+ static class SimpleRequest extends Request {
+
+ private final Map<String, String> params = new HashMap<String, String>();
+
+ @Override
+ public String method() {
+ return "GET";
+ }
+
+ public SimpleRequest setParam(String key, @CheckForNull String value) {
+ if (value != null) {
+ params.put(key, value);
+ }
+ return this;
+ }
+
+ @Override
+ @CheckForNull
+ public String param(String key) {
+ return params.get(key);
+ }
+ }
+
+
+ SimpleRequest request = new SimpleRequest();
+
+ @Test
+ public void required_param_is_missing() throws Exception {
+ try {
+ request.requiredParam("foo");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Parameter 'foo' is missing");
+ }
+ }
+
+ @Test
+ public void required_param_is_set() throws Exception {
+ String value = request.setParam("foo", "bar").requiredParam("foo");
+ assertThat(value).isEqualTo("bar");
+ }
+
+ @Test
+ public void default_value_of_optional_param() throws Exception {
+ String value = request.param("foo", "bar");
+ assertThat(value).isEqualTo("bar");
+ }
+
+ @Test
+ public void string_param() throws Exception {
+ String value = request.setParam("foo", "bar").param("foo", "default");
+ assertThat(value).isEqualTo("bar");
+ }
+
+ @Test
+ public void int_param() throws Exception {
+ assertThat(request.setParam("foo", "123").intParam("foo")).isEqualTo(123);
+ assertThat(request.setParam("foo", "123").intParam("xxx")).isNull();
+ assertThat(request.setParam("foo", "123").intParam("foo", 456)).isEqualTo(123);
+ assertThat(request.setParam("foo", "123").intParam("xxx", 456)).isEqualTo(456);
+ }
+
+ @Test
+ public void boolean_param() throws Exception {
+ assertThat(request.setParam("foo", "true").booleanParam("foo")).isTrue();
+ assertThat(request.setParam("foo", "false").booleanParam("foo")).isFalse();
+ assertThat(request.setParam("foo", "true").booleanParam("xxx")).isNull();
+
+ assertThat(request.setParam("foo", "true").booleanParam("foo", true)).isTrue();
+ assertThat(request.setParam("foo", "true").booleanParam("foo", false)).isTrue();
+ assertThat(request.setParam("foo", "true").booleanParam("xxx", true)).isTrue();
+ assertThat(request.setParam("foo", "true").booleanParam("xxx", false)).isFalse();
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/SimpleRequestTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/SimpleRequestTest.java
deleted file mode 100644
index d9e5bcafa38..00000000000
--- a/sonar-plugin-api/src/test/java/org/sonar/api/server/ws/SimpleRequestTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.api.server.ws;
-
-import com.google.common.collect.ImmutableMap;
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class SimpleRequestTest {
- @Test
- public void string_params() {
- Request request = new SimpleRequest().setParams(ImmutableMap.of("foo", "bar"));
- assertThat(request.param("none")).isNull();
- assertThat(request.param("foo")).isEqualTo("bar");
- }
-
- @Test
- public void int_params() {
- Request request = new SimpleRequest().setParams(ImmutableMap.of("foo", "123"));
- assertThat(request.intParam("none")).isNull();
- assertThat(request.intParam("foo")).isEqualTo(123);
-
- assertThat(request.intParam("none", 456)).isEqualTo(456);
- assertThat(request.intParam("foo", 456)).isEqualTo(123);
- }
-}
diff --git a/sonar-server/pom.xml b/sonar-server/pom.xml
index 78efac7d53b..234bad82b26 100644
--- a/sonar-server/pom.xml
+++ b/sonar-server/pom.xml
@@ -167,11 +167,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.skyscreamer</groupId>
- <artifactId>jsonassert</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-testing-harness</artifactId>
<scope>test</scope>
diff --git a/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java b/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java
index 488b7b78353..aefdf0501b4 100644
--- a/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java
+++ b/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java
@@ -23,10 +23,10 @@ import org.sonar.api.server.ws.WebService;
public class IssuesWs implements WebService {
- private final IssueShowWsHandler detailHandler;
+ private final IssueShowWsHandler showHandler;
- public IssuesWs(IssueShowWsHandler detailHandler) {
- this.detailHandler = detailHandler;
+ public IssuesWs(IssueShowWsHandler showHandler) {
+ this.showHandler = showHandler;
}
@Override
@@ -38,7 +38,7 @@ public class IssuesWs implements WebService {
.setDescription("Detail of issue")
.setSince("4.2")
.setPrivate(true)
- .setHandler(detailHandler)
+ .setHandler(showHandler)
.newParam("key", "Issue key");
controller.done();
diff --git a/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java b/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java
index 0a2354f87b7..cabb16ba9a3 100644
--- a/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java
+++ b/sonar-server/src/main/java/org/sonar/server/ws/ServletResponse.java
@@ -34,6 +34,24 @@ import java.io.StringWriter;
public class ServletResponse implements Response {
+ private class ServletStream implements Stream {
+
+ @Override
+ public Stream setMediaType(String s) {
+ source.setContentType(s);
+ return this;
+ }
+
+ @Override
+ public OutputStream output() {
+ try {
+ return source.getOutputStream();
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to get servlet output stream", e);
+ }
+ }
+ }
+
private final HttpServletResponse source;
private int httpStatus = 200;
@@ -43,25 +61,17 @@ public class ServletResponse implements Response {
@Override
public JsonWriter newJsonWriter() {
- return JsonWriter.of(new Buffer());
+ return JsonWriter.of(new Buffer("application/json"));
}
@Override
public XmlWriter newXmlWriter() {
- try {
- return XmlWriter.of(source.getWriter());
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
+ return XmlWriter.of(new Buffer("application/xml"));
}
@Override
- public OutputStream stream() {
- try {
- return source.getOutputStream();
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
+ public Stream stream() {
+ return new ServletStream();
}
@Override
@@ -76,11 +86,18 @@ public class ServletResponse implements Response {
}
private class Buffer extends StringWriter {
+ private final String mediaType;
+
+ private Buffer(String mediaType) {
+ this.mediaType = mediaType;
+ }
+
@Override
public void close() throws IOException {
super.close();
source.setStatus(httpStatus);
+ source.setContentType(mediaType);
ServletOutputStream stream = null;
try {
stream = source.getOutputStream();
diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
index f0a92d9b4dc..83ba59bdcf1 100644
--- a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
+++ b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
@@ -111,7 +111,9 @@ public class WebServiceEngine implements ServerComponent, Startable {
// Reset response by directly using the stream. Response#newJsonWriter()
// must not be used because it potentially contains some partial response
- JsonWriter json = JsonWriter.of(new OutputStreamWriter(response.stream()));
+ Response.Stream stream = response.stream();
+ stream.setMediaType("application/json");
+ JsonWriter json = JsonWriter.of(new OutputStreamWriter(stream.output()));
json.beginObject();
json.name("errors").beginArray();
json.beginObject().prop("msg", message).endObject();
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/filter/IssueFilterWsTest.java b/sonar-server/src/test/java/org/sonar/server/issue/filter/IssueFilterWsTest.java
index 250a1009a73..d8033bf565c 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/filter/IssueFilterWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/filter/IssueFilterWsTest.java
@@ -20,11 +20,10 @@
package org.sonar.server.issue.filter;
import org.junit.Test;
-import org.sonar.api.server.ws.SimpleRequest;
import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WsTester;
import org.sonar.core.issue.DefaultIssueFilter;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.ws.WsTester;
import java.util.Arrays;
@@ -55,16 +54,14 @@ public class IssueFilterWsTest {
@Test
public void anonymous_page() throws Exception {
MockUserSession.set().setLogin(null);
- SimpleRequest request = new SimpleRequest();
- tester.execute("page", request).assertJson(getClass(), "anonymous_page.json");
+ tester.newRequest("page").execute().assertJson(getClass(), "anonymous_page.json");
}
@Test
public void logged_in_page() throws Exception {
MockUserSession.set().setLogin("eric").setUserId(123);
- SimpleRequest request = new SimpleRequest();
- tester.execute("page", request)
- .assertHttpStatus(200)
+ tester.newRequest("page").execute()
+ .assertStatus(200)
.assertJson(getClass(), "logged_in_page.json");
}
@@ -75,9 +72,8 @@ public class IssueFilterWsTest {
new DefaultIssueFilter().setId(6L).setName("My issues"),
new DefaultIssueFilter().setId(13L).setName("Blocker issues")
));
- SimpleRequest request = new SimpleRequest();
- tester.execute("page", request)
- .assertHttpStatus(200)
+ tester.newRequest("page").execute()
+ .assertStatus(200)
.assertJson(getClass(), "logged_in_page_with_favorites.json");
}
@@ -88,9 +84,8 @@ public class IssueFilterWsTest {
new DefaultIssueFilter().setId(13L).setName("Blocker issues").setData("severity=BLOCKER")
);
- SimpleRequest request = new SimpleRequest().setParam("id", "13");
- tester.execute("page", request)
- .assertHttpStatus(200)
+ tester.newRequest("page").setParam("id", "13").execute()
+ .assertStatus(200)
.assertJson(getClass(), "logged_in_page_with_selected_filter.json");
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
index 7c8285bd316..1b145086fea 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowWsHandlerTest.java
@@ -38,7 +38,7 @@ import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.issue.internal.WorkDayDuration;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
-import org.sonar.api.server.ws.SimpleRequest;
+import org.sonar.api.server.ws.WsTester;
import org.sonar.api.user.User;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.web.UserRole;
@@ -53,7 +53,6 @@ import org.sonar.server.issue.IssueService;
import org.sonar.server.technicaldebt.TechnicalDebtFormatter;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.WsTester;
import java.util.ArrayList;
import java.util.Date;
@@ -133,8 +132,8 @@ public class IssueShowWsHandlerTest {
issues.add(issue);
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issueKey);
- tester.execute("show", request).assertJson(getClass(), "show_issue.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issueKey);
+ request.execute().assertJson(getClass(), "show_issue.json");
}
@Test
@@ -146,8 +145,8 @@ public class IssueShowWsHandlerTest {
result.addActionPlans(newArrayList((ActionPlan) new DefaultActionPlan().setKey("AP-ABCD").setName("Version 4.2")));
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_action_plan.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_action_plan.json");
}
@Test
@@ -164,8 +163,8 @@ public class IssueShowWsHandlerTest {
));
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_users.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_users.json");
}
@Test
@@ -178,8 +177,8 @@ public class IssueShowWsHandlerTest {
when(technicalDebtFormatter.format(any(Locale.class), eq(technicalDebt))).thenReturn("2 hours 1 minutes");
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_technical_debt.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_technical_debt.json");
}
@Test
@@ -199,8 +198,8 @@ public class IssueShowWsHandlerTest {
when(i18n.formatDateTime(any(Locale.class), eq(closedDate))).thenReturn("Jan 24, 2014 10:03 AM");
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_dates.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_dates.json");
}
@Test
@@ -232,8 +231,8 @@ public class IssueShowWsHandlerTest {
when(i18n.instant(any(Locale.class), eq(date2))).thenReturn("10 days");
MockUserSession.set().setLogin("arthur");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_comments.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_comments.json");
}
@Test
@@ -246,8 +245,8 @@ public class IssueShowWsHandlerTest {
when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
MockUserSession.set().setLogin("john");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_transitions.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_transitions.json");
}
@Test
@@ -257,8 +256,8 @@ public class IssueShowWsHandlerTest {
issues.add(issue);
MockUserSession.set().setLogin("john");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_actions.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_actions.json");
}
@Test
@@ -268,8 +267,8 @@ public class IssueShowWsHandlerTest {
issues.add(issue);
MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ISSUE_ADMIN, issue.projectKey());
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_severity_action.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_severity_action.json");
}
@Test
@@ -279,8 +278,8 @@ public class IssueShowWsHandlerTest {
issues.add(issue);
MockUserSession.set().setLogin("john");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_assign_to_me_action.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_assign_to_me_action.json");
}
@Test
@@ -295,8 +294,8 @@ public class IssueShowWsHandlerTest {
));
MockUserSession.set().setLogin("john");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_without_assign_to_me_action.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_without_assign_to_me_action.json");
}
@Test
@@ -310,8 +309,8 @@ public class IssueShowWsHandlerTest {
when(actionService.listAvailableActions(issue)).thenReturn(newArrayList(action));
MockUserSession.set().setLogin("john");
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_actions_defined_by_plugins.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_actions_defined_by_plugins.json");
}
@Test
@@ -339,8 +338,8 @@ public class IssueShowWsHandlerTest {
when(i18n.formatDateTime(any(Locale.class), eq(date2))).thenReturn("Fev 23, 2014 10:03 AM");
MockUserSession.set();
- SimpleRequest request = new SimpleRequest().setParam("key", issue.key());
- tester.execute("show", request).assertJson(getClass(), "show_issue_with_changelog.json");
+ WsTester.TestRequest request = tester.newRequest("show").setParam("key", issue.key());
+ request.execute().assertJson(getClass(), "show_issue_with_changelog.json");
}
private DefaultIssue createStandardIssue() {
diff --git a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java
index bf66f868edf..d985ac3530c 100644
--- a/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java
@@ -21,7 +21,7 @@ package org.sonar.server.issue.ws;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.ws.WsTester;
+import org.sonar.api.server.ws.WsTester;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RuleTagsWsTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RuleTagsWsTest.java
index 252bed2a329..af9004fff34 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule/RuleTagsWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule/RuleTagsWsTest.java
@@ -25,15 +25,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.server.ws.SimpleRequest;
import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WsTester;
import org.sonar.core.rule.RuleTagDto;
-import org.sonar.server.ws.WsTester;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class RuleTagsWsTest {
@@ -75,8 +73,7 @@ public class RuleTagsWsTest {
@Test
public void list_tags() throws Exception {
when(ruleTags.listAllTags()).thenReturn(ImmutableList.of("tag1", "tag2", "tag3"));
- SimpleRequest request = new SimpleRequest();
- tester.execute("list", request).assertJson(getClass(), "list.json");
+ tester.newRequest("list").execute().assertJson(getClass(), "list.json");
verify(ruleTags).listAllTags();
}
@@ -86,18 +83,19 @@ public class RuleTagsWsTest {
Long tagId = 42L;
RuleTagDto newTag = new RuleTagDto().setId(tagId).setTag(tag);
when(ruleTags.create("newtag")).thenReturn(newTag);
- SimpleRequest request = new SimpleRequest();
- request.setParam("tag", tag);
- tester.execute("create", request).assertJson(getClass(), "create_ok.json");
+
+ WsTester.TestRequest request = tester.newRequest("create").setParam("tag", tag);
+ request.execute().assertJson(getClass(), "create_ok.json");
verify(ruleTags).create(tag);
}
- @Test(expected=IllegalArgumentException.class)
+ @Test
public void create_missing_parameter() throws Exception {
- SimpleRequest request = new SimpleRequest();
+ WsTester.TestRequest request = tester.newRequest("create");
try {
- tester.execute("create", request);
- } finally {
+ request.execute();
+ fail();
+ } catch (IllegalArgumentException e) {
verifyZeroInteractions(ruleTags);
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule/RulesWsTest.java b/sonar-server/src/test/java/org/sonar/server/rule/RulesWsTest.java
index 8487236a966..7484d6cda5e 100644
--- a/sonar-server/src/test/java/org/sonar/server/rule/RulesWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/rule/RulesWsTest.java
@@ -20,9 +20,8 @@
package org.sonar.server.rule;
import org.junit.Test;
-import org.sonar.api.server.ws.SimpleRequest;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.ws.WsTester;
+import org.sonar.api.server.ws.WsTester;
import static org.fest.assertions.Assertions.assertThat;
@@ -47,7 +46,6 @@ public class RulesWsTest {
@Test
public void search_for_rules() throws Exception {
- SimpleRequest request = new SimpleRequest();
- tester.execute("search", request).assertJson(getClass(), "search.json");
+ tester.newRequest("search").execute().assertJson(getClass(), "search.json");
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java b/sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java
index de28438d8fe..0e73f856202 100644
--- a/sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/ws/ListingWsTest.java
@@ -19,9 +19,7 @@
*/
package org.sonar.server.ws;
-import org.apache.commons.io.IOUtils;
import org.junit.Test;
-import org.skyscreamer.jsonassert.JSONAssert;
import org.sonar.api.server.ws.*;
import static org.fest.assertions.Assertions.assertThat;
@@ -29,10 +27,10 @@ import static org.fest.assertions.Assertions.assertThat;
public class ListingWsTest {
ListingWs ws = new ListingWs();
- WsTester tester = new WsTester(ws);
@Test
public void define_ws() throws Exception {
+ WsTester tester = new WsTester(ws);
WebService.Controller controller = tester.controller("api/webservices");
assertThat(controller).isNotNull();
assertThat(controller.path()).isEqualTo("api/webservices");
@@ -51,18 +49,8 @@ public class ListingWsTest {
@Test
public void index() throws Exception {
- // register web services, including itself
- WebService.Context context = new WebService.Context();
- ws.define(context);
- new MetricWebService().define(context);
-
- SimpleResponse response = new SimpleResponse();
- ws.list(context.controllers(), response);
-
- JSONAssert.assertEquals(
- IOUtils.toString(getClass().getResource("/org/sonar/server/ws/ListingWebServiceTest/index.json")),
- response.outputAsString(), true
- );
+ WsTester tester = new WsTester(ws, new MetricWebService());
+ tester.newRequest("api/webservices", "index").execute().assertJson(getClass(), "index.json");
}
static class MetricWebService implements WebService {
diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
index e681e2a44fe..a5aff474302 100644
--- a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
@@ -19,25 +19,128 @@
*/
package org.sonar.server.ws;
+import org.apache.commons.io.Charsets;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.sonar.api.server.ws.*;
+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.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.utils.text.XmlWriter;
+
+import javax.annotation.CheckForNull;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+import java.util.Map;
import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
public class WebServiceEngineTest {
+ private static class SimpleRequest extends Request {
+ private String method = "GET";
+ private Map<String, String> params = new HashMap<String, String>();
+
+ @Override
+ public String method() {
+ return method;
+ }
+
+ public SimpleRequest setMethod(String s) {
+ this.method = s;
+ return this;
+ }
+
+ public SimpleRequest setParams(Map<String, String> m) {
+ this.params = m;
+ return this;
+ }
+
+ public SimpleRequest setParam(String key, @CheckForNull String value) {
+ if (value != null) {
+ params.put(key, value);
+ }
+ return this;
+ }
+
+ @Override
+ @CheckForNull
+ public String param(String key) {
+ return params.get(key);
+ }
+
+ }
+
+ private static class SimpleResponse implements Response {
+ public class SimpleStream implements Response.Stream {
+ private String mediaType;
+
+ @CheckForNull
+ public String mediaType() {
+ return mediaType;
+ }
+
+ @Override
+ public Response.Stream setMediaType(String s) {
+ this.mediaType = s;
+ return this;
+ }
+
+ @Override
+ public OutputStream output() {
+ return output;
+ }
+ }
+
+ private int status = 200;
+ private final ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+ @Override
+ public JsonWriter newJsonWriter() {
+ return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
+ }
+
+ @Override
+ public XmlWriter newXmlWriter() {
+ return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
+ }
+
+ @Override
+ public Stream stream() {
+ return new SimpleStream();
+ }
+
+ @Override
+ public int status() {
+ return status;
+ }
+
+ @Override
+ public Response setStatus(int httpStatus) {
+ this.status = httpStatus;
+ return this;
+ }
+
+ public String outputAsString() {
+ return new String(output.toByteArray(), Charsets.UTF_8);
+ }
+ }
+
WebServiceEngine engine = new WebServiceEngine(new WebService[]{new SystemWebService()});
@Before
- public void before() {
+ public void start() {
engine.start();
}
@After
- public void after() {
+ public void stop() {
engine.stop();
}
@@ -78,7 +181,7 @@ public class WebServiceEngineTest {
}
@Test
- public void method_not_allowed() throws Exception {
+ public void method_get_not_allowed() throws Exception {
Request request = new SimpleRequest();
SimpleResponse response = new SimpleResponse();
engine.execute(request, response, "api/system", "ping");
@@ -88,6 +191,16 @@ public class WebServiceEngineTest {
}
@Test
+ public void method_post_required() throws Exception {
+ Request request = new SimpleRequest().setMethod("POST");
+ SimpleResponse response = new SimpleResponse();
+ engine.execute(request, response, "api/system", "ping");
+
+ assertThat(response.status()).isEqualTo(200);
+ assertThat(response.outputAsString()).isEqualTo("pong");
+ }
+
+ @Test
public void required_parameter_is_not_set() throws Exception {
Request request = new SimpleRequest();
SimpleResponse response = new SimpleResponse();
@@ -137,7 +250,7 @@ public class WebServiceEngineTest {
.setHandler(new RequestHandler() {
@Override
public void handle(Request request, Response response) throws Exception {
- response.stream().write("good".getBytes());
+ response.stream().output().write("good".getBytes());
}
});
newController.newAction("ping")
@@ -145,7 +258,7 @@ public class WebServiceEngineTest {
.setHandler(new RequestHandler() {
@Override
public void handle(Request request, Response response) throws Exception {
- response.stream().write("pong".getBytes());
+ response.stream().output().write("pong".getBytes());
}
});
newController.newAction("fail")
@@ -164,7 +277,7 @@ public class WebServiceEngineTest {
@Override
public void handle(Request request, Response response) throws Exception {
IOUtils.write(
- request.requiredParam("message") + " by " + request.param("author", "-"), response.stream());
+ request.requiredParam("message") + " by " + request.param("author", "-"), response.stream().output());
}
});
newController.done();
diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java b/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java
deleted file mode 100644
index 27810226172..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/ws/WsTester.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.ws;
-
-import org.apache.commons.io.IOUtils;
-import org.skyscreamer.jsonassert.JSONAssert;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.SimpleResponse;
-import org.sonar.api.server.ws.WebService;
-
-import javax.annotation.CheckForNull;
-
-import java.net.URL;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * TODO move to sonar-plugin-api with type "test-jar"
- */
-public class WsTester {
-
- private final WebService.Context context = new WebService.Context();
- private String wsPath = null;
-
- public WsTester(WebService ws) {
- ws.define(context);
- if (!context.controllers().isEmpty()) {
- wsPath = context.controllers().get(0).path();
- }
- }
-
- public WebService.Context context() {
- return context;
- }
-
- @CheckForNull
- public WebService.Controller controller(String path) {
- return context.controller(path);
- }
-
- public Result execute(String actionKey, Request request) throws Exception {
- if (wsPath == null) {
- throw new IllegalStateException("Ws path is not defined");
- }
- SimpleResponse response = new SimpleResponse();
- RequestHandler handler = context.controller(wsPath).action(actionKey).handler();
- handler.handle(request, response);
- return new Result(response);
- }
-
- public static class Result {
- private final SimpleResponse response;
-
- private Result(SimpleResponse response) {
- this.response = response;
- }
-
- public Result assertHttpStatus(int httpStatus) {
- assertEquals(httpStatus, response.status());
- return this;
- }
-
- public Result assertJson(String expectedJson) throws Exception {
- String json = response.outputAsString();
- JSONAssert.assertEquals(expectedJson, json, true);
- return this;
- }
-
- public Result assertJson(Class clazz, String jsonResourcePath) throws Exception {
- String json = response.outputAsString();
- String path = clazz.getSimpleName() + "/" + jsonResourcePath;
- URL url = clazz.getResource(path);
- if (url == null) {
- throw new IllegalStateException("Cannot find " + path);
- }
- JSONAssert.assertEquals(IOUtils.toString(url), json, true);
- return this;
- }
- }
-}
diff --git a/sonar-server/src/test/resources/org/sonar/server/ws/ListingWebServiceTest/index.json b/sonar-server/src/test/resources/org/sonar/server/ws/ListingWsTest/index.json
index 6ee68a24252..6ee68a24252 100644
--- a/sonar-server/src/test/resources/org/sonar/server/ws/ListingWebServiceTest/index.json
+++ b/sonar-server/src/test/resources/org/sonar/server/ws/ListingWsTest/index.json
diff --git a/sonar-testing-harness/pom.xml b/sonar-testing-harness/pom.xml
index 777d2790c72..e32a3a72f43 100644
--- a/sonar-testing-harness/pom.xml
+++ b/sonar-testing-harness/pom.xml
@@ -13,42 +13,46 @@
<dependencies>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.easytesting</groupId>
+ <artifactId>fest-assert</artifactId>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
</dependency>
<dependency>
- <groupId>org.easytesting</groupId>
- <artifactId>fest-assert</artifactId>
+ <groupId>org.skyscreamer</groupId>
+ <artifactId>jsonassert</artifactId>
</dependency>
<dependency>
- <groupId>xmlunit</groupId>
- <artifactId>xmlunit</artifactId>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
</dependency>
<dependency>
+ <!-- used only for org.sonar.test.channel classes -->
<groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-plugin-api</artifactId>
+ <artifactId>sonar-channel</artifactId>
<version>${project.version}</version>
+ <optional>true</optional>
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-plugin-api</artifactId>
<version>${project.version}</version>
- <type>test-jar</type>
</dependency>
<dependency>
- <!-- used only for org.sonar.test.channel classes -->
<groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-channel</artifactId>
+ <artifactId>sonar-plugin-api</artifactId>
<version>${project.version}</version>
- <optional>true</optional>
+ <type>test-jar</type>
</dependency>
<dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
+ <groupId>xmlunit</groupId>
+ <artifactId>xmlunit</artifactId>
</dependency>
</dependencies>
</project>
diff --git a/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java b/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java
new file mode 100644
index 00000000000..aad0844ea5c
--- /dev/null
+++ b/sonar-testing-harness/src/main/java/org/sonar/api/server/ws/WsTester.java
@@ -0,0 +1,216 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.api.server.ws;
+
+import org.apache.commons.io.Charsets;
+import org.apache.commons.io.IOUtils;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.utils.text.XmlWriter;
+
+import javax.annotation.CheckForNull;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+/**
+ * @since 4.2
+ */
+public class WsTester {
+
+ public static class TestRequest extends Request {
+
+ private final WebService.Controller controller;
+ private final String actionKey;
+ private String method = "GET";
+ private Map<String, String> params = new HashMap<String, String>();
+
+ private TestRequest(WebService.Controller controller, String actionKey) {
+ this.controller = controller;
+ this.actionKey = actionKey;
+ }
+
+ @Override
+ public String method() {
+ return method;
+ }
+
+ public TestRequest setMethod(String s) {
+ this.method = s;
+ return this;
+ }
+
+ public TestRequest setParams(Map<String, String> m) {
+ this.params = m;
+ return this;
+ }
+
+ public TestRequest setParam(String key, @CheckForNull String value) {
+ if (value != null) {
+ params.put(key, value);
+ }
+ return this;
+ }
+
+ @Override
+ @CheckForNull
+ public String param(String key) {
+ return params.get(key);
+ }
+
+ public Result execute() throws Exception {
+ WebService.Action action = controller.action(actionKey);
+ if (action == null) {
+ throw new IllegalArgumentException("Action not found: " + actionKey);
+ }
+ TestResponse response = new TestResponse();
+ action.handler().handle(this, response);
+ return new Result(response);
+ }
+ }
+
+ public static class TestResponse implements Response {
+
+ public class TestStream implements Response.Stream {
+ private String mediaType;
+
+ @CheckForNull
+ public String mediaType() {
+ return mediaType;
+ }
+
+ @Override
+ public Response.Stream setMediaType(String s) {
+ this.mediaType = s;
+ return this;
+ }
+
+ @Override
+ public OutputStream output() {
+ return output;
+ }
+ }
+
+ private int status = 200;
+ private final ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+ @Override
+ public JsonWriter newJsonWriter() {
+ return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
+ }
+
+ @Override
+ public XmlWriter newXmlWriter() {
+ return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
+ }
+
+ @Override
+ public Stream stream() {
+ return new TestStream();
+ }
+
+ @Override
+ public int status() {
+ return status;
+ }
+
+ @Override
+ public Response setStatus(int httpStatus) {
+ this.status = httpStatus;
+ return this;
+ }
+ }
+
+
+ public static class Result {
+ private final TestResponse response;
+
+ private Result(TestResponse response) {
+ this.response = response;
+ }
+
+ public Result assertStatus(int httpStatus) {
+ assertThat(httpStatus).isEqualTo(response.status());
+ return this;
+ }
+
+ public String outputAsString() {
+ return new String(response.output.toByteArray(), Charsets.UTF_8);
+ }
+
+ public Result assertJson(String expectedJson) throws Exception {
+ String json = outputAsString();
+ JSONAssert.assertEquals(expectedJson, json, true);
+ return this;
+ }
+
+ /**
+ * Compares JSON response with JSON file available in classpath. For example if class
+ * is org.foo.BarTest and filename is index.json, then file must be located
+ * at src/test/resources/org/foo/BarTest/index.json.
+ *
+ * @param clazz the test class
+ * @param jsonResourceFilename name of the file containing the expected JSON
+ */
+ public Result assertJson(Class clazz, String expectedJsonFilename) throws Exception {
+ String path = clazz.getSimpleName() + "/" + expectedJsonFilename;
+ URL url = clazz.getResource(path);
+ if (url == null) {
+ throw new IllegalStateException("Cannot find " + path);
+ }
+ String json = outputAsString();
+ JSONAssert.assertEquals(IOUtils.toString(url), json, true);
+ return this;
+ }
+ }
+
+ private final WebService.Context context = new WebService.Context();
+
+ public WsTester(WebService... webServices) {
+ for (WebService webService : webServices) {
+ webService.define(context);
+ }
+ }
+
+ public WebService.Context context() {
+ return context;
+ }
+
+ @CheckForNull
+ public WebService.Controller controller(String path) {
+ return context.controller(path);
+ }
+
+ public TestRequest newRequest(String actionKey) {
+ if (context.controllers().size() != 1) {
+ throw new IllegalStateException("The method newRequest(String) requires to define one, and only one, controller");
+ }
+ return new TestRequest(context.controllers().get(0), actionKey);
+ }
+
+ public TestRequest newRequest(String controllerPath, String actionKey) {
+ return new TestRequest(context.controller(controllerPath), actionKey);
+ }
+}