netty5/transport/src/test/java/io/netty/channel/AbstractChannelTest.java
Scott Mitchell a68264dc02 DefaultChannelConfig maxMessagesPerRead default not always set
Motivation:
ChannelMetadata has a field minMaxMessagesPerRead which can be confusing. There are also some cases where static instances are used and the default value for channel type is not being applied.

Modifications:
- use a default value which is set unconditionally to simplify
- make sure static instances of MaxMessagesRecvByteBufAllocator are not used if the intention is that the default maxMessagesPerRead should be derived from the channel type.

Result:
Less confusing interfaces in ChannelMetadata and ChannelConfig. Default maxMessagesPerRead is correctly applied.
2015-11-25 15:14:24 -08:00

169 lines
5.7 KiB
Java

/*
* Copyright 2014 The Netty Project
* The Netty Project licenses this file to you 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 io.netty.channel;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.net.SocketAddress;
import org.easymock.Capture;
import org.junit.Test;
public class AbstractChannelTest {
@Test
public void ensureInitialRegistrationFiresActive() throws Throwable {
EventLoop eventLoop = createNiceMock(EventLoop.class);
// This allows us to have a single-threaded test
expect(eventLoop.inEventLoop()).andReturn(true).anyTimes();
TestChannel channel = new TestChannel();
ChannelHandler handler = createMock(ChannelHandler.class);
handler.handlerAdded(anyObject(ChannelHandlerContext.class)); expectLastCall();
Capture<Throwable> throwable = catchHandlerExceptions(handler);
handler.channelRegistered(anyObject(ChannelHandlerContext.class));
expectLastCall().once();
handler.channelActive(anyObject(ChannelHandlerContext.class));
expectLastCall().once();
replay(handler, eventLoop);
channel.pipeline().addLast(handler);
registerChannel(eventLoop, channel);
checkForHandlerException(throwable);
verify(handler);
}
@Test
public void ensureSubsequentRegistrationDoesNotFireActive() throws Throwable {
EventLoop eventLoop = createNiceMock(EventLoop.class);
// This allows us to have a single-threaded test
expect(eventLoop.inEventLoop()).andReturn(true).anyTimes();
TestChannel channel = new TestChannel();
ChannelHandler handler = createMock(ChannelHandler.class);
handler.handlerAdded(anyObject(ChannelHandlerContext.class)); expectLastCall();
Capture<Throwable> throwable = catchHandlerExceptions(handler);
handler.channelRegistered(anyObject(ChannelHandlerContext.class));
expectLastCall().times(2); // Should register twice
handler.channelActive(anyObject(ChannelHandlerContext.class));
expectLastCall().once(); // Should only fire active once
replay(handler, eventLoop);
channel.pipeline().addLast(handler);
registerChannel(eventLoop, channel);
channel.unsafe().deregister(new DefaultChannelPromise(channel));
registerChannel(eventLoop, channel);
checkForHandlerException(throwable);
verify(handler);
}
private void registerChannel(EventLoop eventLoop, Channel channel) throws Exception {
DefaultChannelPromise future = new DefaultChannelPromise(channel);
channel.unsafe().register(eventLoop, future);
future.sync(); // Cause any exceptions to be thrown
}
private Capture<Throwable> catchHandlerExceptions(ChannelHandler handler) throws Exception {
Capture<Throwable> throwable = new Capture<Throwable>();
handler.exceptionCaught(anyObject(ChannelHandlerContext.class), capture(throwable));
expectLastCall().anyTimes();
return throwable;
}
private void checkForHandlerException(Capture<Throwable> throwable) throws Throwable {
if (throwable.hasCaptured()) {
throw throwable.getValue();
}
}
private static class TestChannel extends AbstractChannel {
private static final ChannelMetadata TEST_METADATA = new ChannelMetadata(false);
private class TestUnsafe extends AbstractUnsafe {
@Override
public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { }
}
public TestChannel() {
super(null);
}
@Override
public ChannelConfig config() {
return new DefaultChannelConfig(this);
}
@Override
public boolean isOpen() {
return true;
}
@Override
public boolean isActive() {
return true;
}
@Override
public ChannelMetadata metadata() {
return TEST_METADATA;
}
@Override
protected AbstractUnsafe newUnsafe() {
return new TestUnsafe();
}
@Override
protected boolean isCompatible(EventLoop loop) {
return true;
}
@Override
protected SocketAddress localAddress0() {
return null;
}
@Override
protected SocketAddress remoteAddress0() {
return null;
}
@Override
protected void doBind(SocketAddress localAddress) throws Exception { }
@Override
protected void doDisconnect() throws Exception { }
@Override
protected void doClose() throws Exception { }
@Override
protected void doBeginRead() throws Exception { }
@Override
protected void doWrite(ChannelOutboundBuffer in) throws Exception { }
}
}