001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.server.ws;
021
022 import org.apache.commons.io.Charsets;
023 import org.apache.commons.io.IOUtils;
024 import org.skyscreamer.jsonassert.JSONAssert;
025 import org.sonar.api.utils.text.JsonWriter;
026 import org.sonar.api.utils.text.XmlWriter;
027
028 import javax.annotation.CheckForNull;
029
030 import java.io.ByteArrayOutputStream;
031 import java.io.OutputStream;
032 import java.io.OutputStreamWriter;
033 import java.net.URL;
034 import java.util.HashMap;
035 import java.util.Map;
036
037 /**
038 * @since 4.2
039 */
040 public class WsTester {
041
042 public static class TestRequest extends Request {
043
044 private final WebService.Controller controller;
045 private final WebService.Action action;
046 private String method = "GET";
047 private Map<String, String> params = new HashMap<String, String>();
048
049 private TestRequest(WebService.Controller controller, WebService.Action action) {
050 this.controller = controller;
051 this.action = action;
052 }
053
054 @Override
055 public WebService.Action action() {
056 return action;
057 }
058
059 @Override
060 public String method() {
061 return method;
062 }
063
064 public TestRequest setMethod(String s) {
065 this.method = s;
066 return this;
067 }
068
069 public TestRequest setParams(Map<String, String> m) {
070 this.params = m;
071 return this;
072 }
073
074 public TestRequest setParam(String key, @CheckForNull String value) {
075 if (value != null) {
076 params.put(key, value);
077 }
078 return this;
079 }
080
081 @Override
082 @CheckForNull
083 public String param(String key) {
084 return params.get(key);
085 }
086
087 public Result execute() {
088 TestResponse response = new TestResponse();
089 action.handler().handle(this, response);
090 return new Result(response);
091 }
092 }
093
094 public static class TestResponse implements Response {
095
096 public class TestStream implements Response.Stream {
097 private String mediaType;
098 private int status;
099
100 @CheckForNull
101 public String mediaType() {
102 return mediaType;
103 }
104
105 public int status() {
106 return status;
107 }
108
109 @Override
110 public Response.Stream setMediaType(String s) {
111 this.mediaType = s;
112 return this;
113 }
114
115 @Override
116 public Response.Stream setStatus(int i) {
117 this.status = i;
118 return this;
119 }
120
121 @Override
122 public OutputStream output() {
123 return output;
124 }
125 }
126
127 private final ByteArrayOutputStream output = new ByteArrayOutputStream();
128
129 @Override
130 public JsonWriter newJsonWriter() {
131 return JsonWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
132 }
133
134 @Override
135 public XmlWriter newXmlWriter() {
136 return XmlWriter.of(new OutputStreamWriter(output, Charsets.UTF_8));
137 }
138
139 @Override
140 public Stream stream() {
141 return new TestStream();
142 }
143
144
145 @Override
146 public Response noContent() {
147 IOUtils.closeQuietly(output);
148 return this;
149 }
150 }
151
152
153 public static class Result {
154 private final TestResponse response;
155
156 private Result(TestResponse response) {
157 this.response = response;
158 }
159
160 public Result assertNoContent() {
161 //FIXME
162 return this;
163 }
164
165 public String outputAsString() {
166 return new String(response.output.toByteArray(), Charsets.UTF_8);
167 }
168
169 public Result assertJson(String expectedJson) throws Exception {
170 String json = outputAsString();
171 JSONAssert.assertEquals(expectedJson, json, true);
172 return this;
173 }
174
175 /**
176 * Compares JSON response with JSON file available in classpath. For example if class
177 * is org.foo.BarTest and filename is index.json, then file must be located
178 * at src/test/resources/org/foo/BarTest/index.json.
179 *
180 * @param clazz the test class
181 * @param jsonResourceFilename name of the file containing the expected JSON
182 */
183 public Result assertJson(Class clazz, String expectedJsonFilename) throws Exception {
184 String path = clazz.getSimpleName() + "/" + expectedJsonFilename;
185 URL url = clazz.getResource(path);
186 if (url == null) {
187 throw new IllegalStateException("Cannot find " + path);
188 }
189 String json = outputAsString();
190 JSONAssert.assertEquals(IOUtils.toString(url), json, true);
191 return this;
192 }
193 }
194
195 private final WebService.Context context = new WebService.Context();
196
197 public WsTester(WebService... webServices) {
198 for (WebService webService : webServices) {
199 webService.define(context);
200 }
201 }
202
203 public WebService.Context context() {
204 return context;
205 }
206
207 @CheckForNull
208 public WebService.Controller controller(String path) {
209 return context.controller(path);
210 }
211
212 public TestRequest newRequest(String actionKey) {
213 if (context.controllers().size() != 1) {
214 throw new IllegalStateException("The method newRequest(String) requires to define one, and only one, controller");
215 }
216 WebService.Controller controller = context.controllers().get(0);
217 WebService.Action action = controller.action(actionKey);
218 if (action == null) {
219 throw new IllegalArgumentException("Action not found: " + actionKey);
220 }
221 return new TestRequest(controller, action);
222 }
223
224 public TestRequest newRequest(String controllerPath, String actionKey) {
225 WebService.Controller controller = context.controller(controllerPath);
226 WebService.Action action = controller.action(actionKey);
227 return new TestRequest(controller, action);
228 }
229 }