/*
* Copyright © 2010 Martin Riedel
*
* This file is part of TransFile.
*
* TransFile is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* TransFile 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with TransFile. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.transfile.operations;
import static org.junit.Assert.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sourceforge.transfile.operations.messages.DataOfferMessage;
import net.sourceforge.transfile.operations.messages.DisconnectMessage;
import net.sourceforge.transfile.operations.messages.Message;
import org.junit.Test;
/**
* TODO doc
*
* @author codistmonk (creation 2010-06-05)
*
*/
public abstract class AbstractConnectionTestBase extends AbstractTestWithConnections {
@Test(timeout = TEST_TIMEOUT)
public final void testUpdatePeers() {
final Connection connection = this.createUnmatchedConnection();
final ConnectionRecorder connectionRecorder = new ConnectionRecorder(connection);
final String localPeer = "protocol://localHost:1";
final String remotePeer = "protocol://remoteHost:2";
connection.setLocalPeer(localPeer);
connection.setRemotePeer(remotePeer);
connection.setLocalPeer(localPeer);
connection.setRemotePeer(remotePeer);
connection.setLocalPeer(remotePeer);
connection.setRemotePeer(localPeer);
assertEquals(Arrays.asList(
localPeer,
remotePeer,
remotePeer,
localPeer
), connectionRecorder.getEvents());
}
@Test(timeout = TEST_TIMEOUT)
public final void testAbortConnectUnmatchedConnection() {
final Connection connection = this.createUnmatchedConnection();
final ConnectionRecorder connectionRecorder = new ConnectionRecorder(connection);
assertEquals(Connection.State.DISCONNECTED, connection.getState());
connection.connect();
this.waitUntilConnectionsAreReady(connection);
connection.disconnect();
waitAndAssertState(Connection.State.DISCONNECTED, connection);
assertEquals(Arrays.asList(
Connection.State.CONNECTING,
Connection.State.DISCONNECTED
), connectionRecorder.getEvents());
}
@Test(timeout = TEST_TIMEOUT)
public final void testConnectTimeout() throws InterruptedException {
final Connection connection = this.createUnmatchedConnection();
final ConnectionRecorder connectionRecorder = new ConnectionRecorder(connection);
assertEquals(Connection.State.DISCONNECTED, connection.getState());
connection.connect();
Thread.sleep(this.getConnectTimeout());
waitAndAssertState(Connection.State.DISCONNECTED, connection);
assertEquals(Arrays.asList(
Connection.State.CONNECTING,
Connection.State.DISCONNECTED
), connectionRecorder.getEvents());
}
@Test(timeout = TEST_TIMEOUT)
public final void testConnectionAndDataTransfer() {
this.createAndConnectMatchingConnectionPair();
final Message dataMessage1 = new DataOfferMessage(new File("dummy"), 0L, "Hello world!".getBytes());
final Message dataMessage2 = new DataOfferMessage(new File("dummy"), 0L, "42".getBytes());
this.getConnection1().sendMessage(dataMessage1);
this.waitUntilMatchingConnectionPairAreReady();
this.getConnection2().sendMessage(dataMessage2);
this.waitUntilMatchingConnectionPairAreReady();
this.getConnection1().disconnect();
waitAndAssertState(Connection.State.DISCONNECTED, this.getConnections());
assertEquals(Arrays.asList(
Connection.State.CONNECTING,
Connection.State.CONNECTED,
dataMessage2,
Connection.State.DISCONNECTED
), this.getConnectionRecorder1().getEvents());
assertEquals(Arrays.asList(
Connection.State.CONNECTING,
Connection.State.CONNECTED,
dataMessage1,
// The state is changed as soon as the disconnect message is received
// That's why the logger detects the state change before the disconnect message
// TODO should this behavior be changed?
Connection.State.DISCONNECTED,
new DisconnectMessage()
), this.getConnectionRecorder2().getEvents());
}
/**
* TODO doc
*
* @return a time in milliseconds
* <br>Range: {@code [0L .. Long.MAX_VALUE]}
*/
protected long getConnectTimeout() {
return 500L;
}
/**
* TODO doc
*
* @return
* <br>A non-null value
* <br>A new value
*/
protected abstract Connection createUnmatchedConnection();
/**
* TODO doc
*
* @author codistmonk (creation 2010-06-05)
*
*/
public static class ConnectionRecorder implements Connection.Listener {
private final Connection connection;
private final List<Object> events;
/**
*
* @param connection
* <br>Should not be null
* <br>Shared parameter
*/
public ConnectionRecorder(final Connection connection) {
this.connection = connection;
this.events = new ArrayList<Object>();
this.getConnection().addConnectionListener(this);
}
/**
*
* @return
* <br>A non-null value
* <br>A shared value
*/
public final Connection getConnection() {
return this.connection;
}
/**
*
* @return
* <br>A non-null value
* <br>A shared value
*/
public final List<Object> getEvents() {
return this.events;
}
@Override
public final void localPeerChanged() {
this.getEvents().add(this.getConnection().getLocalPeer());
}
@Override
public final void remotePeerChanged() {
this.getEvents().add(this.getConnection().getRemotePeer());
}
@Override
public final void messageReceived(final Message message) {
this.getEvents().add(message);
}
@Override
public final void stateChanged() {
this.getEvents().add(this.getConnection().getState());
}
}
}