2
* JBoss, Home of Professional Open Source
3
* Copyright 2009, JBoss Inc., and individual contributors as indicated
4
* by the @authors tag. See the copyright.txt in the distribution for a
5
* full listing of individual contributors.
7
* This is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* This software is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this software; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
22
package org.jboss.test.remoting.transport.socket.timeout;
24
import java.io.IOException;
25
import java.io.OutputStream;
26
import java.lang.reflect.Constructor;
27
import java.lang.reflect.InvocationTargetException;
28
import java.net.InetAddress;
29
import java.net.ServerSocket;
30
import java.net.Socket;
31
import java.net.UnknownHostException;
32
import java.util.HashMap;
36
import javax.management.MBeanServer;
37
import javax.net.ServerSocketFactory;
38
import javax.net.SocketFactory;
39
import javax.net.ssl.SSLProtocolException;
41
import junit.framework.TestCase;
43
import org.apache.log4j.ConsoleAppender;
44
import org.apache.log4j.Level;
45
import org.apache.log4j.Logger;
46
import org.apache.log4j.PatternLayout;
47
import org.jboss.logging.XLevel;
48
import org.jboss.remoting.CannotConnectException;
49
import org.jboss.remoting.Client;
50
import org.jboss.remoting.InvocationFailureException;
51
import org.jboss.remoting.InvocationRequest;
52
import org.jboss.remoting.InvokerLocator;
53
import org.jboss.remoting.Remoting;
54
import org.jboss.remoting.ServerInvocationHandler;
55
import org.jboss.remoting.ServerInvoker;
56
import org.jboss.remoting.callback.Callback;
57
import org.jboss.remoting.callback.HandleCallbackException;
58
import org.jboss.remoting.callback.InvokerCallbackHandler;
59
import org.jboss.remoting.transport.Connector;
60
import org.jboss.remoting.transport.PortUtil;
61
import org.jboss.remoting.transport.bisocket.Bisocket;
62
import org.jboss.remoting.transport.socket.SocketServerInvoker;
63
import org.jboss.remoting.transport.socket.SocketWrapper;
67
* Unit tests for JBREM-1120.
69
* @author <a href="ron.sigal@jboss.com">Ron Sigal</a>
72
* Copyright Apr 22, 2009
75
public abstract class WriteTimeoutTestParent extends TestCase
77
private static Logger log = Logger.getLogger(WriteTimeoutTestParent.class);
79
private static boolean firstTime = true;
80
protected static int secondaryServerSocketPort;
81
protected static boolean callbackTest;
83
protected String host;
85
protected String locatorURI;
86
protected InvokerLocator serverLocator;
87
protected Connector connector;
88
protected TestInvocationHandler invocationHandler;
91
public void setUp() throws Exception
96
Logger.getLogger("org.jboss.remoting").setLevel(Level.INFO);
97
Logger.getLogger("org.jboss.test.remoting").setLevel(Level.INFO);
98
String pattern = "[%d{ABSOLUTE}] [%t] %5p (%F:%L) - %m%n";
99
PatternLayout layout = new PatternLayout(pattern);
100
ConsoleAppender consoleAppender = new ConsoleAppender(layout);
101
Logger.getRootLogger().addAppender(consoleAppender);
104
TestOutputStream.counter = 0;
105
callbackTest = false;
109
public void tearDown()
114
public void testClientWriteTimeout() throws Throwable
116
log.info("entering " + getName());
119
setupServer(false, false, "", -1, -1);
122
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
123
HashMap clientConfig = new HashMap();
124
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
125
clientConfig.put(SocketWrapper.WRITE_TIMEOUT, "1000");
126
SocketFactory sf = (SocketFactory) getSocketFactoryConstructor().newInstance(new Object[]{new Integer(5000), new Integer(1)});
127
clientConfig.put(Remoting.CUSTOM_SOCKET_FACTORY, sf);
128
addExtraClientConfig(clientConfig);
129
Client client = new Client(clientLocator, clientConfig);
131
log.info("client is connected");
133
log.info("**************************************");
134
log.info("*** WorkerThread error is expected ***");
135
log.info("**************************************");
137
// Test client side write timeout.
140
client.invoke("abc");
142
catch (InvocationFailureException e)
144
log.info(e.getMessage());
145
assertNotNull(e.getMessage());
146
assertTrue(e.getMessage().startsWith("Unable to perform invocation"));
147
assertTrue(e.getCause() instanceof IOException);
148
IOException ioe = (IOException) e.getCause();
149
assertEquals("closed", ioe.getMessage());
150
log.info("got expected Exception");
154
log.error("got unexpected Exception", t);
155
fail("got unexpected Exception");
160
log.info(getName() + " PASSES");
164
public void testServerWriteTimeout() throws Throwable
166
log.info("entering " + getName());
169
setupServer(true, false, "1000", 5000, 1);
172
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
173
HashMap clientConfig = new HashMap();
174
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
175
clientConfig.put("numberOfCallRetries", "1");
176
clientConfig.put("timeout", "10000");
177
addExtraClientConfig(clientConfig);
178
Client client = new Client(clientLocator, clientConfig);
180
log.info("client is connected");
182
log.info("**************************************");
183
log.info("*** WorkerThread error is expected ***");
184
log.info("**************************************");
186
// Test server side write timeout.
189
client.invoke("abc");
191
catch (InvocationFailureException e)
193
log.info(e.getMessage());
194
// assertNotNull(e.getMessage());
195
// assertTrue(e.getMessage().startsWith("Unable to perform invocation"));
196
// assertTrue(e.getCause() instanceof EOFException);
197
log.info("got expected Exception");
201
log.error("got unexpected Exception", t);
202
fail("got unexpected Exception");
205
// Test server invoker state.
207
SocketServerInvoker serverInvoker = (SocketServerInvoker) connector.getServerInvoker();
208
assertEquals(0, serverInvoker.getCurrentClientPoolSize());
209
assertEquals(1, serverInvoker.getCurrentThreadPoolSize());
210
log.info("used ServerThread has returned to threadPool");
214
log.info(getName() + " PASSES");
218
public void testClientCallbackWriteTimeout() throws Throwable
220
log.info("entering " + getName());
223
if (isBisocket(getTransport()))
227
setupServer(false, false, "", -1, -1);
230
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
231
HashMap clientConfig = new HashMap();
232
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
233
clientConfig.put(SocketWrapper.WRITE_TIMEOUT, "1000");
234
if (isBisocket(getTransport()))
236
SocketFactory sf = (SocketFactory) getSocketFactoryConstructor().newInstance(new Object[]{new Integer(5000), new Integer(1)});
237
clientConfig.put(Remoting.CUSTOM_SOCKET_FACTORY, sf);
241
ServerSocketFactory ssf = (ServerSocketFactory) getServerSocketFactoryConstructor().newInstance(new Object[]{new Integer(5000), new Integer(-1)});
242
clientConfig.put(Remoting.CUSTOM_SERVER_SOCKET_FACTORY, ssf);
244
addExtraClientConfig(clientConfig);
245
Client client = new Client(clientLocator, clientConfig);
247
log.info("client is connected");
250
client.invoke("abc");
251
log.info("connection is good");
253
// Test client callback write timeout.
254
log.info("registering callback handler");
255
log.info("**************************************");
256
log.info("*** WorkerThread error is expected ***");
257
log.info("**************************************");
258
TestCallbackHandler callbackHandler = new TestCallbackHandler();
259
HashMap metadata = new HashMap();
260
if (isBisocket(getTransport()))
262
// metadata.put(SocketWrapper.WRITE_TIMEOUT, "1000");
263
metadata.put(Remoting.SOCKET_FACTORY_NAME, getSocketFactoryClassName());
264
metadata.put("numberOfCallRetries", "1");
265
metadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
266
metadata.put(Bisocket.PING_FREQUENCY, "11111111");
270
// metadata.put(SocketWrapper.WRITE_TIMEOUT, "1000");
271
metadata.put(ServerInvoker.SERVER_SOCKET_FACTORY, getServerSocketFactoryClassName());
272
metadata.put("numberOfCallRetries", "1");
274
client.addListener(callbackHandler, metadata, null, true);
275
log.info("called Client.addListener()");
277
// Test server invoker state.
278
// Wait for local ServerThread to time out. Might take a while in bisocket transports, since
279
// the request to get a socket for the callback client invoker needs its own write on the
282
log.info("back from sleep");
283
Set callbackConnectors = client.getCallbackConnectors(callbackHandler);
284
assertEquals(1, callbackConnectors.size());
285
Connector callbackConnector = (Connector) callbackConnectors.iterator().next();
286
SocketServerInvoker serverInvoker = (SocketServerInvoker) callbackConnector.getServerInvoker();
287
assertEquals(0, serverInvoker.getCurrentClientPoolSize());
288
assertEquals(1, serverInvoker.getCurrentThreadPoolSize());
289
log.info("used ServerThread has returned to threadPool");
293
log.info(getName() + " PASSES");
297
public void testServerCallbackWriteTimeout() throws Throwable
299
log.info("entering " + getName());
302
if (isBisocket(getTransport()))
305
setupServer(true, false, "1000", 5000, 1);
309
setupServer(false, true, "1000", 5000, 1);
313
InvokerLocator clientLocator = new InvokerLocator(locatorURI);
314
HashMap clientConfig = new HashMap();
315
clientConfig.put(InvokerLocator.FORCE_REMOTE, "true");
316
clientConfig.put("numberOfCallRetries", "1");
317
addExtraClientConfig(clientConfig);
318
Client client = new Client(clientLocator, clientConfig);
320
log.info("client is connected");
323
client.invoke("abc");
324
log.info("connection is good");
326
// Test server callback write timeout.
327
log.info("registering callback handler");
328
log.info("**************************************");
329
log.info("*** WorkerThread error is expected ***");
330
log.info("**************************************");
331
HashMap metadata = new HashMap();
332
if (isBisocket(getTransport()))
334
metadata.put(Bisocket.IS_CALLBACK_SERVER, "true");
336
TestCallbackHandler callbackHandler = new TestCallbackHandler();
337
client.addListener(callbackHandler, metadata, null, true);
338
log.info("added listener");
340
// Test server invoker state.
342
log.info("waking up");
343
Throwable t = invocationHandler.t;
344
assertTrue(t instanceof HandleCallbackException);
345
log.info("t.getCause:", t.getCause());
346
if (t.getCause() instanceof InvocationFailureException)
348
InvocationFailureException e = (InvocationFailureException) t.getCause();
349
assertNotNull(e.getMessage());
350
assertTrue(e.getMessage().startsWith("Unable to perform invocation"));
351
assertTrue(e.getCause() instanceof IOException);
352
IOException ioe = (IOException) e.getCause();
353
assertEquals("closed", ioe.getMessage());
357
assertTrue(t.getCause() instanceof CannotConnectException);
358
log.info("t.getCause().getCause(): ", t.getCause().getCause());
359
assertTrue(t.getCause().getCause() instanceof InvocationTargetException);
360
log.info("t.getCause().getCause().getCause(): ", t.getCause().getCause().getCause());
361
// assertTrue(t.getCause().getCause().getCause() instanceof SSLProtocolException);
362
assertTrue(t.getCause().getCause().getCause() instanceof IOException);
363
assertEquals("closed", t.getCause().getCause().getCause().getMessage());
365
log.info("got expected Exception");
369
log.info(getName() + " PASSES");
373
protected abstract String getTransport();
375
protected boolean isBisocket(String transport)
377
return transport.indexOf("bisocket") >= 0;
380
protected String getServerSocketFactoryClassName()
382
return TestServerSocketFactory.class.getName();
385
protected Constructor getServerSocketFactoryConstructor() throws NoSuchMethodException
387
return TestServerSocketFactory.class.getConstructor(new Class[]{int.class, int.class});
390
protected String getSocketFactoryClassName()
392
return TestSocketFactory.class.getName();
395
protected Constructor getSocketFactoryConstructor() throws NoSuchMethodException
397
return TestSocketFactory.class.getConstructor(new Class[]{int.class, int.class});
400
protected void addExtraClientConfig(Map config) {}
401
protected void addExtraServerConfig(Map config) {}
404
protected void setupServer(boolean setWriteTimeout, boolean setCallbackWriteTimeout,
405
String writeTimeout, int blockingTime, int initialWrites) throws Exception
407
host = InetAddress.getLocalHost().getHostAddress();
408
port = PortUtil.findFreePort(host);
409
locatorURI = getTransport() + "://" + host + ":" + port;
410
String metadata = System.getProperty("remoting.metadata");
411
if (metadata != null)
413
locatorURI += "/?" + metadata;
415
serverLocator = new InvokerLocator(locatorURI);
416
log.info("Starting remoting server with locator uri of: " + locatorURI);
417
HashMap config = new HashMap();
418
config.put(InvokerLocator.FORCE_REMOTE, "true");
419
if (isBisocket(getTransport()))
421
secondaryServerSocketPort = PortUtil.findFreePort(host);
422
config.put(Bisocket.SECONDARY_BIND_PORT, Integer.toString(secondaryServerSocketPort));
423
config.put(Bisocket.PING_FREQUENCY, "11111111");
427
config.put(SocketWrapper.WRITE_TIMEOUT, writeTimeout);
428
ServerSocketFactory ssf = (ServerSocketFactory) getServerSocketFactoryConstructor().newInstance(new Object[]{new Integer(blockingTime), new Integer(initialWrites)});
429
config.put(Remoting.CUSTOM_SERVER_SOCKET_FACTORY, ssf);
431
if (setCallbackWriteTimeout)
433
config.put(SocketWrapper.WRITE_TIMEOUT, writeTimeout);
434
SocketFactory sf = (SocketFactory) getSocketFactoryConstructor().newInstance(new Object[]{new Integer(blockingTime), new Integer(initialWrites)});
435
config.put(Remoting.CUSTOM_SOCKET_FACTORY, sf);
439
config.put("numberOfCallRetries", "1");
441
addExtraServerConfig(config);
442
connector = new Connector(serverLocator, config);
444
invocationHandler = new TestInvocationHandler();
445
connector.addInvocationHandler("test", invocationHandler);
450
protected void shutdownServer() throws Exception
452
if (connector != null)
457
static class TestInvocationHandler implements ServerInvocationHandler
461
public void addListener(final InvokerCallbackHandler callbackHandler)
469
log.info("sending callback");
470
callbackHandler.handleCallback(new Callback("callback"));
474
log.info("throwable: ", t);
475
TestInvocationHandler.this.t = t;
480
public Object invoke(final InvocationRequest invocation) throws Throwable
482
return invocation.getParameter();
484
public void removeListener(InvokerCallbackHandler callbackHandler) {}
485
public void setMBeanServer(MBeanServer server) {}
486
public void setInvoker(ServerInvoker invoker) {}
490
static class TestCallbackHandler implements InvokerCallbackHandler
492
public void handleCallback(Callback callback) throws HandleCallbackException
494
log.info("received callback");
499
static public class TestServerSocketFactory extends ServerSocketFactory
504
public TestServerSocketFactory()
507
this.initialWrites = -1;
509
public TestServerSocketFactory(int timeout, int initialWrites)
511
this.timeout = timeout;
512
this.initialWrites = initialWrites;
514
public ServerSocket createServerSocket() throws IOException
516
ServerSocket ss = null;
519
ss = ServerSocketFactory.getDefault().createServerSocket();
523
ss = new TestServerSocket(timeout, initialWrites);
525
log.info("returning: " + ss);
528
public ServerSocket createServerSocket(int port) throws IOException
530
ServerSocket ss = null;
531
if (callbackTest && port != secondaryServerSocketPort)
533
ss = ServerSocketFactory.getDefault().createServerSocket(port);
537
ss = new TestServerSocket(port, timeout, initialWrites);
539
log.info("returning: " + ss);
543
public ServerSocket createServerSocket(int port, int backlog) throws IOException
545
ServerSocket ss = null;
546
if (callbackTest && port != secondaryServerSocketPort)
548
ss = ServerSocketFactory.getDefault().createServerSocket(port, backlog);
552
ss = new TestServerSocket(port, backlog, timeout, initialWrites);
554
log.info("returning: " + ss);
558
public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException
560
ServerSocket ss = null;
561
if (callbackTest && port != secondaryServerSocketPort)
563
ss = ServerSocketFactory.getDefault().createServerSocket(port, backlog, ifAddress);
567
ss = new TestServerSocket(port, backlog, ifAddress, timeout, initialWrites);
569
log.info("returning: " + ss);
575
static class TestServerSocket extends ServerSocket
580
public TestServerSocket(int timeout, int initialWrites) throws IOException
583
this.timeout = timeout;
584
this.initialWrites = initialWrites;
586
public TestServerSocket(int port, int timeout, int initialWrites) throws IOException
589
this.timeout = timeout;
590
this.initialWrites = initialWrites;
592
public TestServerSocket(int port, int backlog, int timeout, int initialWrites) throws IOException
594
super(port, backlog);
595
this.timeout = timeout;
596
this.initialWrites = initialWrites;
598
public TestServerSocket(int port, int backlog, InetAddress bindAddr, int timeout, int initialWrites) throws IOException
600
super(port, backlog, bindAddr);
601
this.timeout = timeout;
602
this.initialWrites = initialWrites;
604
public Socket accept() throws IOException
606
Socket s = new TestSocket(timeout, initialWrites);
610
public String toString()
612
return "TestServerSocket[" + getLocalPort() + "]";
617
public static class TestSocketFactory extends SocketFactory
620
int initialWrites = -1;
622
public TestSocketFactory()
626
public TestSocketFactory(int timeout, int initialWrites)
628
this.timeout = timeout;
629
this.initialWrites = initialWrites;
631
public Socket createSocket()
633
log.info("callbackTest: " + callbackTest);
641
s = new TestSocket(timeout, initialWrites);
643
log.info(this + " returning " + s);
646
public Socket createSocket(String arg0, int arg1) throws IOException, UnknownHostException
648
log.info("callbackTest: " + callbackTest + ", port: " + arg1);
650
if (callbackTest && arg1 != secondaryServerSocketPort)
652
s = new Socket(arg0, arg1);
656
s = new TestSocket(arg0, arg1, timeout, initialWrites);
658
log.info(this + " returning " + s);
662
public Socket createSocket(InetAddress arg0, int arg1) throws IOException
664
log.info("callbackTest: " + callbackTest + ", port: " + arg1);
666
if (callbackTest && arg1 != secondaryServerSocketPort)
668
s = new Socket(arg0, arg1);
672
s = new TestSocket(arg0, arg1, timeout, initialWrites);
674
log.info(this + " returning " + s);
678
public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException, UnknownHostException
680
log.info("callbackTest: " + callbackTest + ", port: " + arg1);
682
if (callbackTest && arg1 != secondaryServerSocketPort)
684
s = new Socket(arg0, arg1);
688
s = new TestSocket(arg0, arg1, arg2, arg3, timeout, initialWrites);
690
log.info(this + " returning " + s);
694
public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException
696
log.info("callbackTest: " + callbackTest + ", port: " + arg1);
698
if (callbackTest && arg1 != secondaryServerSocketPort)
700
s = new Socket(arg0, arg1);
704
s = new TestSocket(arg0, arg1, arg2, arg3, timeout, initialWrites);
706
log.info(this + " returning " + s);
711
static class TestSocket extends Socket
716
public TestSocket(int timeout, int initialWrites)
718
this.timeout = timeout;
719
this.initialWrites = initialWrites;
721
public TestSocket(String host, int port, int timeout, int initialWrites) throws UnknownHostException, IOException
724
this.timeout = timeout;
725
this.initialWrites = initialWrites;
727
public TestSocket(InetAddress address, int port, int timeout, int initialWrites) throws IOException
729
super(address, port);
730
this.timeout = timeout;
731
this.initialWrites = initialWrites;
733
public TestSocket(String host, int port, InetAddress localAddr, int localPort, int timeout, int initialWrites) throws IOException
735
super(host, port, localAddr, localPort);
736
this.timeout = timeout;
737
this.initialWrites = initialWrites;
739
public TestSocket(InetAddress address, int port, InetAddress localAddr, int localPort, int timeout, int initialWrites) throws IOException
741
super(address, port, localAddr, localPort);
742
this.timeout = timeout;
743
this.initialWrites = initialWrites;
745
public OutputStream getOutputStream() throws IOException
747
return new TestOutputStream(super.getOutputStream(), timeout, initialWrites);
749
public String toString()
751
return "TestSocket[" + getLocalPort() + "->" + getPort() + "]";
755
static class TestOutputStream extends OutputStream
761
boolean doWait = true;
762
public static int counter;
764
public TestOutputStream(OutputStream os, int timeout, int initialWrites)
767
this.timeout = timeout;
768
this.initialWrites = initialWrites;
770
public void close()throws IOException
774
log.info(this + " closed");
776
public void write(int b) throws IOException
778
System.out.print("b: " + b);
781
log.info("TestOutputStream closed, cannot write");
782
throw new IOException("closed");
784
if (doWait && ++counter > initialWrites)
788
log.info("TestOutputStream.write() sleeping: " + timeout);
789
Thread.sleep(timeout);
791
catch (InterruptedException e)
798
public void write(byte b[], int off, int len) throws IOException
800
System.out.print("b: ");
801
for (int i = 0; i < len; i++)
803
System.out.print(b[i] + " ");
805
System.out.println("");
808
log.info("TestOutputStream closed, cannot write");
809
throw new IOException("closed");
811
log.info("TestOutputStream: counter = " + counter + ", initialWrites = " + initialWrites);
812
if (++counter > initialWrites)
816
log.info("TestOutputStream.write() sleeping: " + timeout);
817
Thread.sleep(timeout);
819
catch (InterruptedException e)
826
log.info("TestOutputStream closed, cannot write");
827
throw new IOException("closed");
831
log.info(this + " calling write()");
833
os.write(b, off, len);
836
log.info(this + " back from write()");
838
catch (IOException e)
840
log.info("exception: ", e);
b'\\ No newline at end of file'