/*
Copyright (c) 2007 Health Market Science, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
You can contact Health Market Science at info@healthmarketscience.com
or at the following address:
Health Market Science
2700 Horizon Drive
Suite 200
King of Prussia, PA 19406
*/
package com.healthmarketscience.rmiio;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.server.UnicastRemoteObject;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
/**
* @author James Ahlborn
*/
public class RemoteIteratorTest extends BaseRemoteStreamTest {
private static final Logger LOG = LoggerFactory.getLogger(RemoteIteratorTest.class);
public void testTransfer() throws Exception
{
List<List<TestObject>> testObjLists = mainTest(false, false, false,
_clientExceptions,
_monitors);
checkClientExceptions(0);
// should have 3 lists
assertEquals(3, testObjLists.size());
// compare all sent objects to originals
for(List<TestObject> testObjList : testObjLists) {
assertEquals(ObjectClient.SEND_OBJECTS, testObjList);
}
checkMonitors(5, true);
}
public void testEmptyTransfer() throws Exception
{
List<List<TestObject>> testObjLists = mainTest(true, false, false,
_clientExceptions,
_monitors);
checkClientExceptions(0);
// should have 3 lists
assertEquals(3, testObjLists.size());
// should have empty result lists
for(List<TestObject> testObjList : testObjLists) {
assertTrue(testObjList.isEmpty());
}
checkMonitors(5, true);
}
public void testAbortedTransfer() throws Exception
{
List<List<TestObject>> testObjLists = mainTest(false, true, false,
_clientExceptions,
_monitors);
checkClientExceptions(3);
checkMonitors(3, false);
}
public void testNoDelayTransfer() throws Exception
{
List<List<TestObject>> testObjLists = mainTest(false, false, true,
_clientExceptions,
_monitors);
// should have one list with one element
assertEquals(1, testObjLists.size());
assertEquals(1, testObjLists.get(0).size());
assertEquals(ObjectClient.SEND_OBJECTS.get(0),
testObjLists.get(0).get(0));
checkClientExceptions(1);
checkMonitors(1, false);
}
public void testSimple() throws Exception
{
List<TestObject> srcList = new ArrayList<TestObject>();
srcList.addAll(Arrays.asList(
new TestObject("obj1", 1),
new TestObject("obj2", 2),
null,
new TestObject("obj3", 3),
new TestObject("obj4", 4)));
RemoteIterator<TestObject> srcIter =
new SimpleRemoteIterator<TestObject>(srcList);
// serialize/deserialize
RemoteIterator<TestObject> dstIter =
RemoteStreamServerTest.simulateRemote(srcIter);
assertNotSame(srcIter, dstIter);
List<TestObject> dstList = new ArrayList<TestObject>();
while(dstIter.hasNext()) {
dstList.add(dstIter.next());
}
assertEquals(srcList, dstList);
}
public static List<List<TestObject>> mainTest(
final boolean sendEmptyList,
final boolean doAbort,
final boolean noDelayAbort,
final List<Throwable> clientExceptions,
final List<AccumulateRemoteStreamMonitor<?>> monitors)
throws Exception
{
ObjectServer server = new ObjectServer();
final RemoteObjectServer stub = (RemoteObjectServer)
RemoteStreamServerTest.simulateRemote(
UnicastRemoteObject.exportObject(server, 0));
LOG.debug("Server ready");
LOG.debug("Sleeping 3000 ms...");
Thread.sleep(3000);
LOG.debug("Running tests");
Thread clientThread = new Thread(new Runnable()
{
public void run() {
clientExceptions.addAll(
ObjectClient.main(stub, sendEmptyList, doAbort, noDelayAbort,
monitors));
}
});
clientThread.start();
clientThread.join();
LOG.debug("Unexporting server");
UnicastRemoteObject.unexportObject(server, true);
return server._recvdObjectLists;
}
public interface RemoteObjectServer extends Remote {
public void sendObjects(RemoteIterator<TestObject> iterator,
boolean doPartial)
throws IOException;
}
public static class ObjectServer
implements RemoteObjectServer
{
private List<List<TestObject>> _recvdObjectLists =
new LinkedList<List<TestObject>>();
public ObjectServer() {
}
public void sendObjects(RemoteIterator<TestObject> iterator,
boolean doPartial)
throws IOException
{
List<TestObject> recvdObjectList = new LinkedList<TestObject>();
if(!doPartial) {
_recvdObjectLists.add(recvdObjectList);
}
try {
int numRecvd = 0;
while(iterator.hasNext()) {
recvdObjectList.add(iterator.next());
++numRecvd;
if(doPartial && (numRecvd > ObjectClient.PARTIAL_SIZE)) {
// just stop reading
break;
}
}
} finally {
iterator.close();
}
LOG.debug("Server got " + recvdObjectList.size() +
" objects");
}
}
public static class ObjectClient
{
private static final List<TestObject> SEND_OBJECTS =
new LinkedList<TestObject>();
private static final int PARTIAL_SIZE = 100;
static {
SEND_OBJECTS.addAll(Arrays.asList(
new TestObject("obj1", 1),
new TestObject("obj2", 2),
null,
new TestObject("obj3", 3),
new TestObject("obj4", 4)));
// make this list big!
SEND_OBJECTS.addAll(Collections.nCopies(10000,
new TestObject("objMany", 13)));
}
private ObjectClient() {
}
private static void sendObjects(
RemoteObjectServer stub,
boolean useCompression,
boolean doPartial,
boolean sendEmptyList,
boolean doAbort,
boolean noDelay,
boolean noDelayAbort,
List<AccumulateRemoteStreamMonitor<?>> monitors)
throws Exception
{
LOG.debug("Getting iterator");
List<TestObject> sendList = Collections.<TestObject>emptyList();
if(!sendEmptyList) {
sendList = SEND_OBJECTS;
}
AccumulateRemoteIteratorMonitor<RemoteInputStreamServer> monitor =
new AccumulateRemoteIteratorMonitor<RemoteInputStreamServer>();
if(monitors != null) {
monitors.add(monitor);
}
SerialRemoteIteratorServer<TestObject> server = null;
try {
server =
new SerialRemoteIteratorServer<TestObject>(
useCompression, noDelay, monitor,
sendList.iterator());
SerialRemoteIteratorClient<TestObject> client =
RemoteStreamServerTest.simulateRemote(
new SerialRemoteIteratorClient<TestObject>(server));
if(doAbort) {
monitor.setDoAbort(server, doAbort);
}
if(noDelayAbort) {
monitor.setNoDelayAbort(server, noDelayAbort);
}
stub.sendObjects(client, doPartial);
} finally {
if(server != null) {
server.close();
}
}
LOG.debug("Sent objects");
}
public static List<Throwable> main(
RemoteObjectServer stub,
boolean sendEmptyList,
boolean doAbort,
boolean noDelayAbort,
List<AccumulateRemoteStreamMonitor<?>> monitors)
{
List<Throwable> exceptions = new ArrayList<Throwable>();
// try uncompressed, noDelay send
try {
sendObjects(stub, false, false, sendEmptyList, doAbort, true,
noDelayAbort, monitors);
} catch(Throwable t) {
exceptions.add(t);
}
if(!noDelayAbort) {
// try uncompressed send
try {
sendObjects(stub, false, false, sendEmptyList, doAbort, false, false,
monitors);
} catch(Throwable t) {
exceptions.add(t);
}
// try compressed send
try {
sendObjects(stub, true, false, sendEmptyList, doAbort, false, false,
monitors);
} catch(Throwable t) {
exceptions.add(t);
}
if(!doAbort) {
// try partial uncompressed send
try {
sendObjects(stub, false, true, sendEmptyList, false, false, false,
monitors);
} catch(Throwable t) {
exceptions.add(t);
}
// try partial compressed send
try {
sendObjects(stub, true, true, sendEmptyList, false, false, false,
monitors);
} catch(Throwable t) {
exceptions.add(t);
}
}
}
return exceptions;
}
}
private static class AccumulateRemoteIteratorMonitor<S extends RemoteStreamServer>
extends AccumulateRemoteStreamMonitor<S>
{
private RemoteIteratorServer _server;
private boolean _noDelayAbort;
AccumulateRemoteIteratorMonitor() {
super(false);
}
public void setDoAbort(RemoteIteratorServer server,
boolean doAbort) {
_server = server;
_doAbort = doAbort;
}
public void setNoDelayAbort(RemoteIteratorServer server,
boolean noDelayAbort) {
_server = server;
_noDelayAbort = noDelayAbort;
}
@Override
public void localBytesMoved(S stream, int numBytes)
{
if(_noDelayAbort && (_numLocalBytes > 0)) {
try {
_server.abort();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
_numLocalBytes += numBytes;
if(_doAbort && (_numLocalBytes > 0)) {
try {
_server.abort();
} catch(IOException e) {
throw new RuntimeException(e);
}
}
}
}
public static class TestObject implements Serializable
{
private static final long serialVersionUID = 1;
private String _strData;
private int _intData;
public TestObject(String strData, int intData) {
_strData = strData;
_intData = intData;
}
@Override
public boolean equals(Object o) {
return((o instanceof TestObject) &&
(((TestObject)o)._strData.equals(_strData)) &&
(((TestObject)o)._intData == _intData));
}
}
}