forked from alibaba/Sentinel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add some unit test for sentinel-transport-netty-http module (alibaba#321
- Loading branch information
Showing
4 changed files
with
403 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
212 changes: 212 additions & 0 deletions
212
...src/test/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerHandlerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
/* | ||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.alibaba.csp.sentinel.transport.command.netty; | ||
|
||
import com.alibaba.csp.sentinel.Constants; | ||
import com.alibaba.csp.sentinel.config.SentinelConfig; | ||
import com.alibaba.csp.sentinel.init.InitExecutor; | ||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | ||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; | ||
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; | ||
import com.alibaba.csp.sentinel.transport.CommandCenter; | ||
import com.alibaba.csp.sentinel.transport.command.NettyHttpCommandCenter; | ||
import io.netty.buffer.ByteBuf; | ||
import io.netty.buffer.Unpooled; | ||
import io.netty.channel.embedded.EmbeddedChannel; | ||
import io.netty.handler.codec.http.*; | ||
import org.junit.Before; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
||
import java.lang.reflect.Field; | ||
import java.nio.charset.Charset; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST; | ||
import static io.netty.handler.codec.http.HttpResponseStatus.OK; | ||
import static org.junit.Assert.assertEquals; | ||
|
||
/** | ||
* Test cases for {@link HttpServerHandler}. | ||
* | ||
* @author cdfive | ||
* @date 2018-12-17 | ||
*/ | ||
public class HttpServerHandlerTest { | ||
|
||
private static String CRLF = "\r\n"; | ||
|
||
private static String SENTINEL_CHARSET_NAME = SentinelConfig.charset(); | ||
|
||
private static Charset SENTINEL_CHARSET = Charset.forName(SENTINEL_CHARSET_NAME); | ||
|
||
private static EmbeddedChannel embeddedChannel; | ||
|
||
@BeforeClass | ||
public static void beforeClass() throws Exception { | ||
// don't execute InitExecutor.doInit, to avoid CommandCenter SPI loaded | ||
Field[] declaredFields = InitExecutor.class.getDeclaredFields(); | ||
for (Field declaredField : declaredFields) { | ||
if (declaredField.getName().equals("initialized")) { | ||
declaredField.setAccessible(true); | ||
((AtomicBoolean)declaredField.get(InitExecutor.class)).set(true); | ||
} | ||
} | ||
|
||
// create NettyHttpCommandCenter to create HttpServer | ||
CommandCenter commandCenter = new NettyHttpCommandCenter(); | ||
// call beforeStart to register handlers | ||
commandCenter.beforeStart(); | ||
} | ||
|
||
@Before | ||
public void before() { | ||
// the same Handlers in order as the ChannelPipeline in HttpServerInitializer | ||
HttpRequestDecoder httpRequestDecoder = new HttpRequestDecoder(); | ||
HttpObjectAggregator httpObjectAggregator = new HttpObjectAggregator(1024 * 1024); | ||
HttpResponseEncoder httpResponseEncoder = new HttpResponseEncoder(); | ||
|
||
HttpServerHandler httpServerHandler = new HttpServerHandler(); | ||
|
||
// create new EmbeddedChannel every method call | ||
embeddedChannel = new EmbeddedChannel(httpRequestDecoder, httpObjectAggregator, httpResponseEncoder, httpServerHandler); | ||
} | ||
|
||
@Test | ||
public void testInvalidCommand() { | ||
String httpRequestStr = "GET / HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = "Invalid command"; | ||
|
||
processError(httpRequestStr, body); | ||
} | ||
|
||
@Test | ||
public void testUnknownCommand() { | ||
String httpRequestStr = "GET /aaa HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = String.format("Unknown command \"%s\"", "aaa"); | ||
|
||
processError(httpRequestStr, body); | ||
} | ||
|
||
@Test | ||
public void testVersionCommand() { | ||
String httpRequestStr = "GET /version HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = Constants.SENTINEL_VERSION; | ||
|
||
processSuccess(httpRequestStr, body); | ||
} | ||
|
||
@Test | ||
public void testGetRuleCommandInvalidType() { | ||
String httpRequestStr = "GET /getRules HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = "invalid type"; | ||
|
||
processFailed(httpRequestStr, body); | ||
} | ||
|
||
@Test | ||
public void testGetRuleCommandFlowEmptyRule() { | ||
String httpRequestStr = "GET /getRules?type=flow HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = "[]"; | ||
|
||
processSuccess(httpRequestStr, body); | ||
} | ||
|
||
// FIXME byteBuf.toString can't get body response now, need to find another way | ||
// @Test | ||
public void testGetRuleCommandFlowSomeRules() { | ||
List<FlowRule> rules = new ArrayList<FlowRule>(); | ||
FlowRule rule1 = new FlowRule(); | ||
rule1.setResource("key"); | ||
rule1.setCount(20); | ||
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); | ||
rule1.setLimitApp("default"); | ||
rules.add(rule1); | ||
FlowRuleManager.loadRules(rules); | ||
|
||
String httpRequestStr = "GET /getRules?type=flow HTTP/1.1" + CRLF | ||
+ "Host: localhost:8719" + CRLF | ||
+ CRLF; | ||
String body = ""; | ||
|
||
processSuccess(httpRequestStr, body); | ||
} | ||
|
||
private void processError(String httpRequestStr, String body) { | ||
processError(httpRequestStr, BAD_REQUEST, body); | ||
} | ||
|
||
private void processError(String httpRequestStr, HttpResponseStatus status, String body) { | ||
String httpResponseStr = processResponse(httpRequestStr); | ||
assertErrorStatusAndBody(status, body, httpResponseStr); | ||
} | ||
|
||
private void processSuccess(String httpRequestStr, String body) { | ||
process(httpRequestStr, OK, body); | ||
} | ||
|
||
private void processFailed(String httpRequestStr, String body) { | ||
process(httpRequestStr, BAD_REQUEST, body); | ||
} | ||
|
||
private void process(String httpRequestStr, HttpResponseStatus status, String body) { | ||
String responseStr = processResponse(httpRequestStr); | ||
assertStatusAndBody(status, body, responseStr); | ||
} | ||
|
||
private String processResponse(String httpRequestStr) { | ||
embeddedChannel.writeInbound(Unpooled.wrappedBuffer(httpRequestStr.getBytes(SENTINEL_CHARSET))); | ||
|
||
ByteBuf byteBuf = embeddedChannel.readOutbound(); | ||
|
||
String responseStr = byteBuf.toString(SENTINEL_CHARSET); | ||
return responseStr; | ||
} | ||
|
||
private void assertErrorStatusAndBody(HttpResponseStatus status, String body, String httpResponseStr) { | ||
StringBuilder text = new StringBuilder(); | ||
text.append(HttpVersion.HTTP_1_1.toString()).append(' ').append(status.toString()).append(CRLF); | ||
text.append("Content-Type: text/plain; charset=").append(SENTINEL_CHARSET_NAME).append(CRLF); | ||
text.append(CRLF); | ||
text.append(body); | ||
|
||
assertEquals(text.toString(), httpResponseStr); | ||
} | ||
|
||
private void assertStatusAndBody(HttpResponseStatus status, String body, String httpResponseStr) { | ||
StringBuilder text = new StringBuilder(); | ||
text.append(HttpVersion.HTTP_1_1.toString()).append(' ').append(status.toString()).append(CRLF); | ||
text.append("Content-Type: text/plain; charset=").append(SENTINEL_CHARSET_NAME).append(CRLF); | ||
text.append("content-length: " + body.length()).append(CRLF); | ||
text.append("connection: close").append(CRLF); | ||
text.append(CRLF); | ||
text.append(body); | ||
|
||
assertEquals(text.toString(), httpResponseStr); | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
...test/java/com/alibaba/csp/sentinel/transport/command/netty/HttpServerInitializerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.alibaba.csp.sentinel.transport.command.netty; | ||
|
||
import io.netty.channel.ChannelHandler; | ||
import io.netty.channel.ChannelPipeline; | ||
import io.netty.channel.socket.SocketChannel; | ||
import io.netty.handler.codec.http.HttpObjectAggregator; | ||
import io.netty.handler.codec.http.HttpRequestDecoder; | ||
import io.netty.handler.codec.http.HttpResponseEncoder; | ||
import org.junit.Test; | ||
import org.mockito.InOrder; | ||
|
||
import static org.mockito.Mockito.*; | ||
|
||
/** | ||
* Test cases for {@link HttpServerInitializer}. | ||
* | ||
* @author cdfive | ||
* @date 2018-12-19 | ||
*/ | ||
public class HttpServerInitializerTest { | ||
|
||
@Test | ||
public void testInitChannel() throws Exception { | ||
// mock Objects | ||
HttpServerInitializer httpServerInitializer = mock(HttpServerInitializer.class); | ||
SocketChannel socketChannel = mock(SocketChannel.class); | ||
ChannelPipeline channelPipeline = mock(ChannelPipeline.class); | ||
|
||
// mock SocketChannel#pipeline() method | ||
when(socketChannel.pipeline()).thenReturn(channelPipeline); | ||
|
||
// HttpServerInitializer#initChannel(SocketChannel) call real method | ||
doCallRealMethod().when(httpServerInitializer).initChannel(socketChannel); | ||
|
||
// start test for HttpServerInitializer#initChannel(SocketChannel) | ||
httpServerInitializer.initChannel(socketChannel); | ||
|
||
// verify 4 times calling ChannelPipeline#addLast() method | ||
verify(channelPipeline, times(4)).addLast(any(ChannelHandler.class)); | ||
|
||
// verify the order of calling ChannelPipeline#addLast() method | ||
InOrder inOrder = inOrder(channelPipeline); | ||
inOrder.verify(channelPipeline).addLast(any(HttpRequestDecoder.class)); | ||
inOrder.verify(channelPipeline).addLast(any(HttpObjectAggregator.class)); | ||
inOrder.verify(channelPipeline).addLast(any(HttpResponseEncoder.class)); | ||
|
||
inOrder.verify(channelPipeline).addLast(any(HttpServerHandler.class)); | ||
} | ||
} |
Oops, something went wrong.