// Copyright (c) 2007-Present Pivotal Software, Inc. All rights reserved.
//
// This software, the RabbitMQ Java client library, is triple-licensed under the
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
// please see LICENSE-APACHE2.
//
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
// either express or implied. See the LICENSE file for specific language governing
// rights and limitations of this software.
//
// If you have any questions regarding licensing, please contact us at
// info@rabbitmq.com.
package com.rabbitmq.client.test.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.util.concurrent.Executors;
import javax.net.SocketFactory;
import com.rabbitmq.client.impl.recovery.AutorecoveringConnection;
import com.rabbitmq.client.test.TestUtils;
import org.junit.Test;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ShutdownListener;
import com.rabbitmq.client.ShutdownSignalException;
import com.rabbitmq.client.impl.AMQConnection;
import com.rabbitmq.client.impl.ChannelN;
import com.rabbitmq.client.impl.ConsumerWorkService;
import com.rabbitmq.client.impl.SocketFrameHandler;
import com.rabbitmq.client.test.BrokerTestCase;
import com.rabbitmq.tools.Host;
public class ChannelLimitNegotiation extends BrokerTestCase {
class SpecialConnection extends AMQConnection {
private final int channelMax;
public SpecialConnection(int channelMax) throws Exception {
this(TestUtils.connectionFactory(), channelMax);
}
private SpecialConnection(ConnectionFactory factory, int channelMax) throws Exception {
super(factory.params(Executors.newFixedThreadPool(1)), new SocketFrameHandler(SocketFactory.getDefault().createSocket("localhost", AMQP.PROTOCOL.PORT)));
this.channelMax = channelMax;
}
/**
* Private API, allows for easier simulation of bogus clients.
*/
@Override
protected int negotiateChannelMax(int requestedChannelMax, int serverMax) {
return this.channelMax;
}
}
@Test public void channelMaxLowerThanServerMinimum() throws Exception {
int n = 64;
ConnectionFactory cf = TestUtils.connectionFactory();
cf.setRequestedChannelMax(n);
Connection conn = cf.newConnection();
assertEquals(n, conn.getChannelMax());
}
@Test public void channelMaxGreaterThanServerValue() throws Exception {
try {
Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 2048).'");
SpecialConnection connection = new SpecialConnection(4096);
try {
connection.start();
fail("expected failure during connection negotiation");
} catch (IOException e) {
// expected
}
} finally {
Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 0).'");
}
}
@Test public void openingTooManyChannels() throws Exception {
int n = 48;
try {
Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, " + n + ").'");
ConnectionFactory cf = TestUtils.connectionFactory();
Connection conn = cf.newConnection();
assertEquals(n, conn.getChannelMax());
for (int i = 1; i <= n; i++) {
assertNotNull(conn.createChannel(i));
}
// ChannelManager guards against channel.open being sent
assertNull(conn.createChannel(n + 1));
// Construct a channel directly
final ChannelN ch = new ChannelN(((AutorecoveringConnection) conn).getDelegate(), n + 1,
new ConsumerWorkService(Executors.newSingleThreadExecutor(),
Executors.defaultThreadFactory(), ConnectionFactory.DEFAULT_SHUTDOWN_TIMEOUT));
conn.addShutdownListener(new ShutdownListener() {
public void shutdownCompleted(ShutdownSignalException cause) {
// make sure channel.open continuation is released
ch.processShutdownSignal(cause, true, true);
}
});
ch.open();
fail("expected channel.open to cause a connection exception");
} catch (IOException e) {
checkShutdownSignal(530, e);
} finally {
Host.rabbitmqctl("eval 'application:set_env(rabbit, channel_max, 0).'");
}
}
}