blob: b43fe35a098c254276e878f08c0313e38aa201bf [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.qpid.test.unit.close;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQSession_0_8;
import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ExchangeDeclareBody;
import org.apache.qpid.framing.ExchangeDeclareOkBody;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
import javax.jms.Session;
/** QPID-1809
*
* Race condition on error handling and close logic.
*
* See most often with SimpleACLTest as this test is the expects the server to
* shut the connection/channels. This sort of testing is not performed by many,
* if any, of the other system tests.
*
* The problem is that we have two threads
*
* MainThread Exception(Mina)Thread
* | |
* Performs |
* ACtion |
* | Receives Server
* | Close
* Blocks for |
* Response |
* | Starts To Notify
* | client
* | |
* | <----- Notify Main Thread
* Notification |
* wakes client |
* | |
* Client then |
* processes Error. |
* | |
* Potentially Attempting Close Channel/Connection
* Connection Close
*
* The two threads both attempt to close the connection but the main thread does
* so assuming that the connection is open and valid.
*
* The Exception thread must modify the connection so that no furter syncWait
* commands are performed.
*
* This test sends an ExchangeDeclare that is Asynchronous and will fail and
* so cause a ChannelClose error but we perform a syncWait so that we can be
* sure to test that the BlockingWaiter is correctly awoken.
*
*/
public class JavaServerCloseRaceConditionTest extends QpidBrokerTestCase
{
private static final String EXCHANGE_NAME = "NewExchangeNametoFailLookup";
public void test() throws Exception
{
AMQConnection connection = (AMQConnection) getConnection();
AMQSession_0_8 session = (AMQSession_0_8) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Set no wait true so that we block the connection
// Also set a different exchange class string so the attempt to declare
// the exchange causes an exchange.
ExchangeDeclareBody body = session.getMethodRegistry().createExchangeDeclareBody(session.getTicket(), new AMQShortString(EXCHANGE_NAME), null,
true, false, false, false, true, null);
AMQFrame exchangeDeclare = body.generateFrame(session.getChannelId());
try
{
// block our thread so that can times out
connection.getProtocolHandler().syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class);
}
catch (Exception e)
{
assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME));
}
try
{
// Depending on if the notification thread has closed the connection
// or not we may get an exception here when we attempt to close the
// connection. If we do get one then it should be the same as above
// an AMQAuthenticationException.
connection.close();
}
catch (Exception e)
{
assertTrue("Exception should say the exchange is not known.", e.getMessage().contains("Unknown exchange: " + EXCHANGE_NAME));
}
}
}