001/* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2013 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 */ 020package org.sonar.api.server.ws; 021 022import org.apache.commons.io.Charsets; 023import org.apache.commons.io.IOUtils; 024import org.skyscreamer.jsonassert.JSONAssert; 025import org.sonar.api.utils.text.JsonWriter; 026import org.sonar.api.utils.text.XmlWriter; 027 028import javax.annotation.CheckForNull; 029 030import java.io.ByteArrayOutputStream; 031import java.io.OutputStream; 032import java.io.OutputStreamWriter; 033import java.net.URL; 034import java.util.HashMap; 035import java.util.Map; 036 037/** 038 * @since 4.2 039 */ 040public 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}