/* * 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.assertEquals; import org.junit.Before; import net.sourceforge.transfile.operations.AbstractConnectionTestBase.ConnectionRecorder; import net.sourceforge.transfile.operations.Connection.State; import net.sourceforge.jenerics.Tools; /** * TODO doc * * @author codistmonk (creation 2010-06-08) * */ public abstract class AbstractTestWithConnections { private Connection[] connections; private Connection connection1; private Connection connection2; private ConnectionRecorder connectionRecorder1; private ConnectionRecorder connectionRecorder2; @Before public final void before() { this.setConnections(null); } /** * @return * <br>A possibly null value * <br>A shared value */ protected final Connection[] getConnections() { return this.connections; } /** * @param connections * <br>Can be null * <br>Shared parameter */ protected final void setConnections(final Connection[] connections) { this.connections = connections; if (this.getConnections() != null) { this.setConnection1(this.getConnections()[0]); this.setConnection2(this.getConnections()[1]); } else { this.setConnection1(null); this.setConnection2(null); } } /** * @return * <br>A possibly null value * <br>A shared value */ protected final Connection getConnection1() { return this.connection1; } /** * @param connection1 * <br>Can be null * <br>Shared parameter */ protected final void setConnection1(final Connection connection1) { this.connection1 = connection1; this.setConnectionRecorder1(this.getConnection1() != null ? new ConnectionRecorder(this.getConnection1()) : null); } /** * @return * <br>A possibly null value * <br>A shared value */ protected final Connection getConnection2() { return this.connection2; } /** * @param connection2 * <br>Can be null * <br>Shared parameter */ protected final void setConnection2(final Connection connection2) { this.connection2 = connection2; this.setConnectionRecorder2(this.getConnection2() != null ? new ConnectionRecorder(this.getConnection2()) : null); } /** * @return * <br>A possibly null value * <br>A shared value */ protected final ConnectionRecorder getConnectionRecorder1() { return this.connectionRecorder1; } /** * @param connectionRecorder1 * <br>Can be null * <br>Shared parameter */ protected final void setConnectionRecorder1(final ConnectionRecorder connectionRecorder1) { this.connectionRecorder1 = connectionRecorder1; } /** * @return * <br>A possibly null value * <br>A shared value */ protected final ConnectionRecorder getConnectionRecorder2() { return this.connectionRecorder2; } /** * @param connectionRecorder2 * <br>Can be null * <br>Shared parameter */ protected final void setConnectionRecorder2(final ConnectionRecorder connectionRecorder2) { this.connectionRecorder2 = connectionRecorder2; } /** * TODO doc * * @return * <br>A non-null value * <br>A new value */ protected abstract Connection[] createMatchingConnectionPair(); /** * TODO doc * * @param connections * <br>Should not be null */ protected final void waitUntilConnectionsAreReady(final Connection... connections) { try { Thread.sleep(this.getInactivityThreshold()); } catch (final InterruptedException exception) { exception.printStackTrace(); } for (final Connection connection : connections) { if (connection instanceof AbstractConnection) { while (System.currentTimeMillis() < ((AbstractConnection) connection).getLastMessageTime() + this.getInactivityThreshold()) { atomicWait(); } } } } protected void waitUntilMatchingConnectionPairAreReady() { try { Thread.sleep(this.getInactivityThreshold()); } catch (final InterruptedException exception) { Tools.throwUnchecked(exception); } final AbstractConnection connection1 = (AbstractConnection) this.getConnection1(); final AbstractConnection connection2 = (AbstractConnection) this.getConnection2(); long i = 0L; Tools.debugPrint( "\n", i, connection1, connection2, "\n", connection1.getReceivedMessageCount(), connection1.getSentMessageCount(), "\n", connection2.getReceivedMessageCount(), connection2.getSentMessageCount() ); while (connection1.getReceivedMessageCount() != connection2.getSentMessageCount() || connection1.getSentMessageCount() != connection2.getReceivedMessageCount()) { ++i; if (i % INFO_PERIOD == 0L) { Tools.debugPrint( "\n", i, "\n", connection1.getReceivedMessageCount(), connection1.getSentMessageCount(), "\n", connection2.getReceivedMessageCount(), connection2.getSentMessageCount() ); } atomicWait(); } } /** * TODO doc * * @return a time in milliseconds * <br>Range: {@code [0L .. Long.MAX_VALUE]} */ protected long getInactivityThreshold() { return 500L; } /** * TODO doc * */ protected final void createAndConnectMatchingConnectionPair() { this.setConnections(this.createMatchingConnectionPair()); Tools.debugPrint((Object[]) this.getConnections()); assertEquals(Connection.State.DISCONNECTED, this.getConnection1().getState()); assertEquals(Connection.State.DISCONNECTED, this.getConnection2().getState()); this.getConnection1().connect(); this.getConnection2().connect(); waitAndAssertState(Connection.State.CONNECTED, this.getConnections()); } /** * Number affecting the frequency of debugPrint calls to display messages when an expected state is taking too long to occur. */ private static final long INFO_PERIOD = 100L; /** * Time in milliseconds. */ public static final long TEST_TIMEOUT = 30000L; /** * Time in milliseconds. */ public static final long ATOMIC_WAIT_DURATION = 10L; public static final void atomicWait() { Thread.yield(); try { Thread.sleep(ATOMIC_WAIT_DURATION); } catch (final InterruptedException exception) { exception.printStackTrace(); } } /** * TODO doc * * @param state * <br>Can be null * @param connections * <br>Should not be null */ public static final void waitAndAssertState(final State state, final Connection... connections) { boolean wait = true; long j = 0L; while (wait) { atomicWait(); wait = false; if ((j++) % INFO_PERIOD == 0L && connections.length == 2) { Tools.debugPrint(connections[0].getConnectionError(), connections[1].getConnectionError()); } for (final Connection connection : connections) { wait |= connection.getState() != state; } } int i = 0; for (final Connection connection : connections) { assertEquals("connections[" + (i++) + "]", state, connection.getState()); } } }