package org.jacorb.test.bugs.bugjac330;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.jacorb.orb.Delegate;
import org.jacorb.orb.giop.ClientConnection;
import org.jacorb.orb.giop.ClientConnectionManager;
import org.jacorb.test.BasicServer;
import org.jacorb.test.BasicServerHelper;
import org.jacorb.test.harness.CommonSetup;
import org.jacorb.test.harness.ORBTestCase;
import org.jacorb.test.harness.ServerSetup;
import org.jacorb.test.harness.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.omg.CORBA.NO_RESOURCES;
import org.omg.ETF.Profile;
/**
* @author Alphonse Bendt
*/
public class MultipleServerTest extends ORBTestCase
{
private ServerSetup setup1;
private String server1IOR;
private ServerSetup setup2;
private String server2IOR;
@Before
public void setUp() throws Exception
{
Properties orbProps = new Properties();
if (TestUtils.isSSLEnabled)
{
// In this case we have been configured to run all the tests
// in SSL mode. For simplicity, we will use the demo/ssl keystore
// and properties (partly to ensure that they always work)
Properties cp = CommonSetup.loadSSLProps("jsse_client_props", "jsse_client_ks");
orbProps.putAll(cp);
}
setup1 = new ServerSetup(null, CustomBasicServerImpl.class.getName(), orbProps );
setup1.setUp();
server1IOR = setup1.getServerIOR();
setup2 = new ServerSetup(null, CustomBasicServerImpl.class.getName(), orbProps );
setup2.setUp();
server2IOR = setup2.getServerIOR();
}
@After
public void tearDown() throws Exception
{
setup2.tearDown();
setup1.tearDown();
}
@Override
protected void patchORBProperties(Properties props) throws Exception
{
props.put("jacorb.connection.client.max_receptor_threads", "1");
if (name.getMethodName().equals("testNoIdleThreads"))
{
props.put("jacorb.connection.client.max_idle_receptor_threads", "0");
}
else if (name.getMethodName().equals("testDisconnectAfterSystemException"))
{
props.put("jacorb.connection.client.max_receptor_threads", "1");
props.put("jacorb.connection.client.max_idle_receptor_threads", "0");
props.put("jacorb.connection.client.disconnect_after_systemexception", "true");
}
else if (name.getMethodName().equals("testDisconnectAfterSystemExceptionNoTimeout"))
{
props.put("jacorb.connection.client.max_receptor_threads", "1");
props.put("jacorb.connection.client.max_idle_receptor_threads", "1");
props.put("jacorb.connection.client.disconnect_after_systemexception", "true");
}
}
@Test
public void testAccessTwoServersAtOnceShouldFail() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
assertEquals(10, server1.bounce_long(10));
BasicServer server2 = BasicServerHelper.narrow(orb.string_to_object(server2IOR));
try
{
server2.bounce_long(10);
fail();
}
catch (NO_RESOURCES e)
{
// expected
}
}
@Test
public void testAccessTwoServersOneByOne() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
assertEquals(10, server1.bounce_long(10));
server1._release();
// give the ConsumerReceptorThread some time to finish its work
Thread.sleep(1000);
BasicServer server2 = BasicServerHelper.narrow(orb.string_to_object(server2IOR));
assertEquals(10, server2.bounce_long(10));
server2._release();
}
@Test
public void testAccessTwoServersAtOnceReleaseTryAgain() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
assertEquals(10, server1.bounce_long(10));
BasicServer server2 = BasicServerHelper.narrow(orb.string_to_object(server2IOR));
try
{
server2.bounce_long(10);
fail("should fail as there may not be more than 1 ClientReceptorThreads");
}
catch (NO_RESOURCES e)
{
// expected
}
server1._release();
// give the ConsumerReceptorThread some time to finish its work
Thread.sleep(1000);
// retry bind
assertEquals(10, server2.bounce_long(10));
}
@Test
public void testNoIdleThreads() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
assertEquals(10, server1.bounce_long(10));
final String threadName = "ClientMessageReceptor";
assertTrue(isThereAThreadNamed(threadName));
server1._release();
int retry = 0;
final int maxRetry = 30;
while( (retry++ < maxRetry) && isThereAThreadNamed(threadName))
{
// wait some time to allow the ClientMessageReceptor Thread to exit
Thread.sleep(1000);
System.gc();
}
dumpThread(threadName);
assertFalse("there should be no idle thread", isThereAThreadNamed(threadName));
}
@Test
public void testDisconnectAfterSystemException() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
server1.ping();
Thread.sleep(10000);
final String threadName = "ClientMessageReceptor";
dumpThread(threadName);
assertFalse(isThereAThreadNamed(threadName));
server1._release();
}
public void testDisconnectAfterSystemExceptionNoTimeout() throws Exception
{
BasicServer server1 = BasicServerHelper.narrow(orb.string_to_object(server1IOR));
try
{
server1.pass_in_long(0);
}
catch (Throwable e)
{
Field fconnmgr = Delegate.class.getDeclaredField("conn_mg");
fconnmgr.setAccessible(true);
Delegate d = (Delegate) ((org.omg.CORBA.portable.ObjectImpl)server1)._get_delegate();
ClientConnectionManager ccm = (ClientConnectionManager) fconnmgr.get(d);
Field connections = ClientConnectionManager.class.getDeclaredField("connections");
connections.setAccessible(true);
@SuppressWarnings("unchecked")
HashMap<Profile, ClientConnection> c = (HashMap<Profile, ClientConnection>) connections.get(ccm);
assertTrue (c.size() == 0);
}
}
private void dumpThread(final String threadName) throws Exception
{
Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces ();
Iterator<Thread> i = map.keySet().iterator();
while(i.hasNext())
{
Thread key = i.next();
if (!key.getName().startsWith(threadName))
{
continue;
}
StackTraceElement[] stack = map.get(key);
TestUtils.getLogger().debug(key.getName());
for (int j = 0; j < stack.length; j++)
{
TestUtils.getLogger().debug("\t" + stack[j]);
}
TestUtils.getLogger().debug("");
}
}
private boolean isThereAThreadNamed(String name)
{
// begin hack.
// fetch the names of all active threads and see if
// the name matches.
int threadCount = Thread.activeCount();
Thread[] threads = new Thread[threadCount];
Thread.enumerate(threads);
for (int i = 0; i < threads.length; i++)
{
if (threads[i] == null)
{
continue;
}
if (threads[i].getName().indexOf(name) >= 0)
{
return true;
}
}
return false;
}
}