/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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.citrus.service.requestcontext;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.alibaba.citrus.service.requestcontext.impl.RequestContextChainingServiceImpl;
import com.alibaba.citrus.util.internal.InterfaceImplementorBuilder;
import com.alibaba.citrus.util.internal.Servlet3Util;
import org.easymock.Capture;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RequestContextAsyncTests {
private RequestContextChainingServiceImpl service;
private ServletContext servletContext;
private RequestContext requestContext;
private HttpServletRequest request;
private HttpServletResponse response;
private Map<String, Object> attrs;
private boolean originalServlet3Disabled;
private boolean isAsyncStarted;
private Enum<?> dispatcherType;
private Object /* AsyncContext */ asyncContext;
@Before
public void init() throws Exception {
originalServlet3Disabled = Servlet3Util.setDisableServlet3Features(false);
// mock request
HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
// request
attrs = createHashMap();
request = (HttpServletRequest) new InterfaceImplementorBuilder().addInterface(HttpServletRequest.class).toObject(new Object() {
public Locale getLocale() {
return Locale.CHINA;
}
public HttpSession getSession(boolean create) {
return null;
}
public Object getAttribute(String name) {
return attrs.get(name);
}
public void setAttribute(String name, Object o) {
attrs.put(name, o);
}
public void removeAttribute(String name) {
attrs.remove(name);
}
public boolean isAsyncStarted() {
return isAsyncStarted;
}
public Enum<?> getDispatcherType() {
return dispatcherType;
}
public Object getAsyncContext() {
return asyncContext;
}
}, mockRequest);
// response
response = createMock(HttpServletResponse.class);
// service
RequestContextFactory<RequestContext> factory = new RequestContextFactory<RequestContext>() {
@Override
public RequestContext getRequestContextWrapper(RequestContext wrappedContext) {
return wrappedContext;
}
@Override
public Class<RequestContext> getRequestContextInterface() {
return RequestContext.class;
}
@Override
public Class<? extends RequestContext> getRequestContextProxyInterface() {
return RequestContext.class;
}
@Override
public String[] getFeatures() {
return new String[0];
}
@Override
public FeatureOrder[] featureOrders() {
return new FeatureOrder[0];
}
};
List<RequestContextFactory<?>> factories = createArrayList();
factories.add(factory);
service = new RequestContextChainingServiceImpl();
service.setFactories(factories);
service.afterPropertiesSet();
// servlet context
servletContext = createMock(ServletContext.class);
}
@After
public void dispose() {
Servlet3Util.setDisableServlet3Features(originalServlet3Disabled);
}
@Test
public void getRequestContext() {
requestContext = service.getRequestContext(servletContext, request, response);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
}
@Test
public void getRequestContext_DispatcherAsync() {
if (!Servlet3Util.isServlet3()) {
return;
}
getRequestContext();
dispatcherType = Servlet3Util.DISPATCHER_TYPE_ASYNC;
assertSame(requestContext, service.getRequestContext(servletContext, request, response));
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
}
@Test
public void commitRequestContext_DispatcherRequest() {
dispatcherType = Servlet3Util.DISPATCHER_TYPE_REQUEST;
requestContext = service.getRequestContext(servletContext, request, response);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
service.commitRequestContext(requestContext);
assertSame(null, attrs.get("_outer_webx3_request_context_")); // request和requestContext解除绑定
}
@Test
public void commitRequestContext_DispatcherRequest_AsyncStarted() {
if (!Servlet3Util.isServlet3()) {
return;
}
Object listener1 = getAsyncListener();
Object listener2 = getAsyncListener();
assertNotSame(listener1, listener2);
assertSame(listener1.getClass(), listener2.getClass()); // 不会重复生成class导致permgen溢出
}
private Object getAsyncListener() {
dispatcherType = Servlet3Util.DISPATCHER_TYPE_REQUEST;
requestContext = service.getRequestContext(servletContext, request, response);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
isAsyncStarted = true;
asyncContext = createMock(Servlet3Util.asyncContextClass);
Capture<Object> cap = new Capture<Object>();
Servlet3Util.asyncContext_addAsyncListener(asyncContext, capture(cap));
replay(asyncContext);
service.commitRequestContext(requestContext);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_")); // request和requestContext仍绑定
verify(asyncContext);
Object listener = cap.getValue();
assertTrue(Servlet3Util.asyncListenerClass.isInstance(listener)); // asyncContext.addListener(asyncListener)
return listener;
}
@Test
public void commitRequestContext_DispatcherAsync() {
if (!Servlet3Util.isServlet3()) {
return;
}
dispatcherType = Servlet3Util.DISPATCHER_TYPE_ASYNC;
requestContext = service.getRequestContext(servletContext, request, response);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
service.commitRequestContext(requestContext);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_")); // request和requestContext仍绑定
}
@Test
public void commitRequestContext_DispatcherAsync_AsyncStarted() {
if (!Servlet3Util.isServlet3()) {
return;
}
dispatcherType = Servlet3Util.DISPATCHER_TYPE_ASYNC;
requestContext = service.getRequestContext(servletContext, request, response);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_"));
isAsyncStarted = true;
service.commitRequestContext(requestContext);
assertSame(requestContext, attrs.get("_outer_webx3_request_context_")); // request和requestContext仍绑定
}
}