package org.jgroups.protocols;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.util.Util;
import org.testng.annotations.Test;
import java.util.Collections;
import java.util.Set;
/**
* Test battery to the behavior of the MessageWindow structure in ACK_SEQUENCER
*
* @author Pedro Ruivo
* @since 3.1
*/
@Test(groups = Global.FUNCTIONAL, sequential = true)
public class ACK_SEQUENCER_MessageWindowTest {
public void testAddAck() {
ACK_SEQUENCER.MessageWindow messageWindow = new ACK_SEQUENCER.MessageWindow();
addAck(messageWindow, 1);
checkSequence(messageWindow, 1);
addAck(messageWindow, 2);
checkSequence(messageWindow, 1, 2);
addAck(messageWindow, 4);
checkSequence(messageWindow, 1, 2, 4);
checkHighestSequenceNumber(messageWindow, 1);
}
public void testCleanDeliverMessage() {
ACK_SEQUENCER.MessageWindow messageWindow = new ACK_SEQUENCER.MessageWindow();
init(messageWindow, 1, 10);
deliver(messageWindow,1, 10);
checkEmpty(messageWindow);
checkHighestSequenceNumber(messageWindow, 11);
}
public void testAddOldAck() {
ACK_SEQUENCER.MessageWindow messageWindow = new ACK_SEQUENCER.MessageWindow();
init(messageWindow, 1, 10);
deliver(messageWindow, 1, 4);
checkHighestSequenceNumber(messageWindow, 5);
check(messageWindow, 5, 10);
addAck(messageWindow, 3);
checkHighestSequenceNumber(messageWindow, 5);
check(messageWindow, 5, 10);
addAck(messageWindow, 5);
checkHighestSequenceNumber(messageWindow, 5);
check(messageWindow, 5, 10);
}
public void testTryDeliver() {
ACK_SEQUENCER.MessageWindow messageWindow = new ACK_SEQUENCER.MessageWindow();
deliver(messageWindow, 1, 10);
checkEmpty(messageWindow);
checkHighestSequenceNumber(messageWindow, 11);
}
public void testCreateAckCollector() {
ACK_SEQUENCER.MessageWindow messageWindow = new ACK_SEQUENCER.MessageWindow();
init(messageWindow, 1, 10);
deliver(messageWindow, 1, 4);
checkHighestSequenceNumber(messageWindow, 5);
Object obj = messageWindow.getOrCreate(5);
assert obj != null : "Expected ack collector for sequence number 5, but obtained null";
obj = messageWindow.getOrCreate(4);
assert obj == null : "Expected null ack collector but get the ack collector for sequence number 4";
obj = messageWindow.getOrCreate(11);
assert obj != null : "Expected ack collector for sequence number 11, but obtained null";
Object obj2 = messageWindow.getOrCreate(11);
assert obj == obj2 : "Expected the same ack collector for sequence number 11, but obtained a different object";
}
private void init(ACK_SEQUENCER.MessageWindow messageWindow, int begin, int end) {
for (int i = begin; i <= end; ++i) {
addAck(messageWindow, i);
}
checkHighestSequenceNumber(messageWindow, 1);
check(messageWindow, begin, end);
}
private void checkHighestSequenceNumber(ACK_SEQUENCER.MessageWindow messageWindow, long expectedSeqNo) {
assert messageWindow.getNextSeqNoToDeliver() == expectedSeqNo : "Wrong highest sequence number. " +
expectedSeqNo + "!=" + messageWindow.getNextSeqNoToDeliver();
}
private void check(ACK_SEQUENCER.MessageWindow messageWindow, long begin, long end) {
check(messageWindow.getAckWindow().keySet(), begin, end);
}
private void checkEmpty(ACK_SEQUENCER.MessageWindow messageWindow) {
assert messageWindow.getAckWindow().keySet().isEmpty() : "Expected an empty ack window";
}
private void check(Set<Long> seqNos, long begin, long end) {
assert seqNos.size() == end - begin + 1 : "Wrong sequence size";
long value = begin;
for (long seqNo : seqNos) {
assert seqNo == value : "Wrong value in ack window." + seqNo + "!=" + value;
value++;
}
}
private void checkSequence(ACK_SEQUENCER.MessageWindow messageWindow, long... values) {
Set<Long> longs = messageWindow.getAckWindow().keySet();
assert longs.size() == values.length : "Wrong sequence size";
int i = 0;
for (long l : longs) {
assert l == values[i] : "Wrong value in ack window." + l + "!=" + values[i];
i++;
}
}
private void deliver(ACK_SEQUENCER.MessageWindow messageWindow, long seqNo) {
try {
messageWindow.waitUntilDeliverIsPossible(seqNo, 0, Collections.<Address>emptyList(), Util.createRandomAddress());
} catch (InterruptedException e) {
assert false : "Interrupted Exception not expected!";
}
}
private void deliver(ACK_SEQUENCER.MessageWindow messageWindow, long init, long end) {
for (long i = init; i <= end; ++i) {
deliver(messageWindow, i);
}
}
private void addAck(ACK_SEQUENCER.MessageWindow messageWindow, long seqNo) {
messageWindow.addAck(Util.createRandomAddress("A"), seqNo, 0, Collections.<Address>emptyList());
}
}