1 // This file is part of OpenTSDB. 2 // Copyright (C) 2011-2012 The OpenTSDB Authors. 3 // 4 // This program is free software: you can redistribute it and/or modify it 5 // under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 2.1 of the License, or (at your 7 // option) any later version. This program is distributed in the hope that it 8 // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 9 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License for more details. You should have received a copy 11 // of the GNU Lesser General Public License along with this program. If not, 12 // see <http://www.gnu.org/licenses/>. 13 package net.opentsdb.tsd; 14 15 import static org.mockito.Matchers.any; 16 import static org.mockito.Mockito.when; 17 import static org.powermock.api.mockito.PowerMockito.mock; 18 19 import java.net.SocketAddress; 20 import java.nio.charset.Charset; 21 import java.util.HashMap; 22 23 import net.opentsdb.core.TSDB; 24 import net.opentsdb.utils.Config; 25 26 import org.jboss.netty.buffer.ChannelBuffer; 27 import org.jboss.netty.buffer.ChannelBuffers; 28 import org.jboss.netty.channel.Channel; 29 import org.jboss.netty.channel.ChannelFuture; 30 import org.jboss.netty.channel.DefaultChannelFuture; 31 import org.jboss.netty.channel.DefaultChannelPipeline; 32 import org.jboss.netty.handler.codec.http.DefaultHttpRequest; 33 import org.jboss.netty.handler.codec.http.HttpMethod; 34 import org.jboss.netty.handler.codec.http.HttpRequest; 35 import org.jboss.netty.handler.codec.http.HttpRequestDecoder; 36 import org.jboss.netty.handler.codec.http.HttpResponseEncoder; 37 import org.jboss.netty.handler.codec.http.HttpVersion; 38 import org.junit.Ignore; 39 import org.powermock.reflect.Whitebox; 40 41 /** 42 * Helper class that provides mockups for testing any OpenTSDB processes that 43 * deal with Netty. 44 */ 45 @Ignore 46 public final class NettyMocks { 47 48 /** 49 * Sets up a TSDB object for HTTP RPC tests that has a Config object 50 * @return A TSDB mock 51 */ getMockedHTTPTSDB()52 public static TSDB getMockedHTTPTSDB() { 53 final TSDB tsdb = mock(TSDB.class); 54 final Config config = mock(Config.class); 55 HashMap<String, String> properties = new HashMap<String, String>(); 56 properties.put("tsd.http.show_stack_trace", "true"); 57 Whitebox.setInternalState(config, "properties", properties); 58 when(tsdb.getConfig()).thenReturn(config); 59 return tsdb; 60 } 61 62 /** 63 * Returns a mocked Channel object that simply sets the name to 64 * [fake channel] 65 * @return A Channel mock 66 */ fakeChannel()67 public static Channel fakeChannel() { 68 final Channel chan = mock(Channel.class); 69 when(chan.toString()).thenReturn("[fake channel]"); 70 when(chan.isConnected()).thenReturn(true); 71 when(chan.isWritable()).thenReturn(true); 72 73 final SocketAddress socket = mock(SocketAddress.class); 74 when(socket.toString()).thenReturn("192.168.1.1:4243"); 75 when(chan.getRemoteAddress()).thenReturn(socket); 76 return chan; 77 } 78 79 /** 80 * Returns an HttpQuery object with the given URI and the following parameters: 81 * Method = GET 82 * Content = null 83 * Content-Type = null 84 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 85 * object set 86 * @param uri A URI to use 87 * @return an HttpQuery object 88 */ getQuery(final TSDB tsdb, final String uri)89 public static HttpQuery getQuery(final TSDB tsdb, final String uri) { 90 final Channel channelMock = NettyMocks.fakeChannel(); 91 final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, 92 HttpMethod.GET, uri); 93 return new HttpQuery(tsdb, req, channelMock); 94 } 95 96 /** 97 * Returns an HttpQuery object with the given uri, content and type 98 * Method = POST 99 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 100 * object set 101 * @param uri A URI to use 102 * @param content Content to POST (UTF-8 encoding) 103 * @return an HttpQuery object 104 */ postQuery(final TSDB tsdb, final String uri, final String content)105 public static HttpQuery postQuery(final TSDB tsdb, final String uri, 106 final String content) { 107 return postQuery(tsdb, uri, content, "application/json; charset=UTF-8"); 108 } 109 110 /** 111 * Returns an HttpQuery object with the given uri, content and type 112 * Method = POST 113 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 114 * object set 115 * @param uri A URI to use 116 * @param content Content to POST (UTF-8 encoding) 117 * @param type Content-Type value 118 * @return an HttpQuery object 119 */ postQuery(final TSDB tsdb, final String uri, final String content, final String type)120 public static HttpQuery postQuery(final TSDB tsdb, final String uri, 121 final String content, final String type) { 122 return contentQuery(tsdb, uri, content, type, HttpMethod.POST); 123 } 124 125 /** 126 * Returns an HttpQuery object with the given uri, content and type 127 * Method = PUT 128 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 129 * object set 130 * @param uri A URI to use 131 * @param content Content to POST (UTF-8 encoding) 132 * @return an HttpQuery object 133 */ putQuery(final TSDB tsdb, final String uri, final String content)134 public static HttpQuery putQuery(final TSDB tsdb, final String uri, 135 final String content) { 136 return putQuery(tsdb, uri, content, "application/json; charset=UTF-8"); 137 } 138 139 /** 140 * Returns an HttpQuery object with the given uri, content and type 141 * Method = PUT 142 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 143 * object set 144 * @param uri A URI to use 145 * @param content Content to POST (UTF-8 encoding) 146 * @param type Content-Type value 147 * @return an HttpQuery object 148 */ putQuery(final TSDB tsdb, final String uri, final String content, final String type)149 public static HttpQuery putQuery(final TSDB tsdb, final String uri, 150 final String content, final String type) { 151 return contentQuery(tsdb, uri, content, type, HttpMethod.PUT); 152 } 153 154 /** 155 * Returns an HttpQuery object with the given uri, content and type 156 * Method = DELETE 157 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 158 * object set 159 * @param uri A URI to use 160 * @param content Content to POST (UTF-8 encoding) 161 * @return an HttpQuery object 162 */ deleteQuery(final TSDB tsdb, final String uri, final String content)163 public static HttpQuery deleteQuery(final TSDB tsdb, final String uri, 164 final String content) { 165 return deleteQuery(tsdb, uri, content, "application/json; charset=UTF-8"); 166 } 167 168 /** 169 * Returns an HttpQuery object with the given uri, content and type 170 * Method = DELETE 171 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 172 * object set 173 * @param uri A URI to use 174 * @param content Content to POST (UTF-8 encoding) 175 * @param type Content-Type value 176 * @return an HttpQuery object 177 */ deleteQuery(final TSDB tsdb, final String uri, final String content, final String type)178 public static HttpQuery deleteQuery(final TSDB tsdb, final String uri, 179 final String content, final String type) { 180 return contentQuery(tsdb, uri, content, type, HttpMethod.DELETE); 181 } 182 183 /** 184 * Returns an HttpQuery object with the given settings 185 * @param tsdb The TSDB to associate with, needs to be mocked with the Config 186 * object set 187 * @param uri A URI to use 188 * @param content Content to POST (UTF-8 encoding) 189 * @param type Content-Type value 190 * @param method The HTTP method to use, GET, POST, etc. 191 * @return an HttpQuery object 192 */ contentQuery(final TSDB tsdb, final String uri, final String content, final String type, final HttpMethod method)193 public static HttpQuery contentQuery(final TSDB tsdb, final String uri, 194 final String content, final String type, final HttpMethod method) { 195 final Channel channelMock = NettyMocks.fakeChannel(); 196 final HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, 197 method, uri); 198 if (content != null) { 199 req.setContent(ChannelBuffers.copiedBuffer(content, 200 Charset.forName("UTF-8"))); 201 } 202 req.headers().set("Content-Type", type); 203 return new HttpQuery(tsdb, req, channelMock); 204 } 205 206 /** @param the query to mock a future callback for */ mockChannelFuture(final HttpQuery query)207 public static void mockChannelFuture(final HttpQuery query) { 208 final ChannelFuture future = new DefaultChannelFuture(query.channel(), false); 209 when(query.channel().write(any(ChannelBuffer.class))).thenReturn(future); 210 future.setSuccess(); 211 } 212 213 /** 214 * Returns a simple pipeline with an HttpRequestDecoder and an 215 * HttpResponseEncoder. No mocking, returns an actual pipeline 216 * @return The pipeline 217 */ createHttpPipeline()218 private DefaultChannelPipeline createHttpPipeline() { 219 DefaultChannelPipeline pipeline = new DefaultChannelPipeline(); 220 pipeline.addLast("requestDecoder", new HttpRequestDecoder()); 221 pipeline.addLast("responseEncoder", new HttpResponseEncoder()); 222 return pipeline; 223 } 224 } 225