blob: 189183de0240029f5fb26b873ad092262a29c345 [file] [log] [blame]
/*
* Copyright (c) 2010-2012, 2015 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Bonneau - initial API and implementation
* Andre Dietisheim - maintenance
*/
package org.eclipse.net4j.tests.bugzilla;
import org.eclipse.net4j.Net4jUtil;
import org.eclipse.net4j.connector.IConnector;
import org.eclipse.net4j.jvm.JVMUtil;
import org.eclipse.net4j.signal.IndicationWithResponse;
import org.eclipse.net4j.signal.RequestWithConfirmation;
import org.eclipse.net4j.signal.SignalProtocol;
import org.eclipse.net4j.signal.SignalReactor;
import org.eclipse.net4j.util.IErrorHandler;
import org.eclipse.net4j.util.concurrent.Worker;
import org.eclipse.net4j.util.container.ContainerUtil;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.factory.ProductCreationException;
import org.eclipse.net4j.util.io.ExtendedDataInputStream;
import org.eclipse.net4j.util.io.ExtendedDataOutputStream;
import org.eclipse.net4j.util.tests.AbstractOMTest;
import org.eclipse.spi.net4j.ServerProtocolFactory;
import java.nio.BufferUnderflowException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author David Bonneau
*/
public class Bugzilla_262875_Test extends AbstractOMTest
{
/** the length of the metadata sent in a buffer: channelID, correlationID */
private static final short BUFFER_METADATA_LENTGH = 10;
private IManagedContainer container;
private IConnector connector;
@Override
protected void doSetUp() throws Exception
{
super.doSetUp();
container = ContainerUtil.createContainer();
Net4jUtil.prepareContainer(container);
JVMUtil.prepareContainer(container);
container.registerFactory(new TestProtocol.Factory());
container.activate();
JVMUtil.getAcceptor(container, "default");
connector = JVMUtil.getConnector(container, "default");
}
@Override
protected void doTearDown() throws Exception
{
connector.close();
container.deactivate();
super.doTearDown();
}
/**
* Tests if a buffer underflow exception occurs if the data sent in a request exactly matches the capacity of a
* buffer.
*
* @throws Exception
* the exception
*/
public void testGivenDataMatchesBufferLengthThenBufferUnderflowException() throws Exception
{
final AtomicBoolean failed = new AtomicBoolean(false);
final CountDownLatch latch = new CountDownLatch(1);
IErrorHandler oldErrorHandler = Worker.setGlobalErrorHandler(new IErrorHandler()
{
public void handleError(Throwable t)
{
t.printStackTrace();
if (t instanceof BufferUnderflowException)
{
failed.set(true);
}
latch.countDown();
}
});
try
{
TestProtocol protocol = new TestProtocol();
protocol.open(connector);
short bufferCapacity = protocol.getBufferProvider().getBufferCapacity();
new TestProtocol.Request(protocol, bufferCapacity - BUFFER_METADATA_LENTGH).send();
latch.await(DEFAULT_TIMEOUT_EXPECTED, TimeUnit.MILLISECONDS);
assertEquals(false, failed.get());
}
finally
{
Worker.setGlobalErrorHandler(oldErrorHandler);
}
}
/**
* @author David Bonneau
*/
private static final class TestProtocol extends SignalProtocol<Object>
{
private static final String NAME = "TEST_PROTOCOL";
private static final short SIGNAL_ID = 10;
public TestProtocol()
{
super(NAME);
}
@Override
protected SignalReactor createSignalReactor(short signalID)
{
switch (signalID)
{
case SIGNAL_ID:
return new Indication(this);
}
return super.createSignalReactor(signalID);
}
/**
* @author David Bonneau
*/
private static final class Request extends RequestWithConfirmation<Boolean>
{
private int requestNumOfBytes;
public Request(SignalProtocol<?> protocol, int requestNumOfBytes)
{
super(protocol, SIGNAL_ID);
this.requestNumOfBytes = requestNumOfBytes;
}
@Override
protected void requesting(ExtendedDataOutputStream out) throws Exception
{
for (int i = 0; i < requestNumOfBytes; ++i)
{
out.writeByte(i);
}
// delay completion
Thread.sleep(100);
}
@Override
protected Boolean confirming(ExtendedDataInputStream in) throws Exception
{
return in.readBoolean();
}
}
/**
* @author David Bonneau
*/
private static final class Indication extends IndicationWithResponse
{
public Indication(SignalProtocol<?> protocol)
{
super(protocol, SIGNAL_ID);
}
@Override
protected void indicating(ExtendedDataInputStream in) throws Exception
{
System.out.println("indicating");
}
@Override
protected void responding(ExtendedDataOutputStream out) throws Exception
{
out.writeBoolean(true);
}
}
/**
* @author David Bonneau
*/
private static final class Factory extends ServerProtocolFactory
{
public Factory()
{
super(NAME);
}
public Object create(String description) throws ProductCreationException
{
return new TestProtocol();
}
}
}
}