001: // $Id: AckSenderWindowTest.java,v 1.5 2005/05/30 16:15:05 belaban Exp $
002: package org.jgroups.tests;
003:
004: import junit.framework.Test;
005: import junit.framework.TestCase;
006: import junit.framework.TestSuite;
007: import org.jgroups.Message;
008: import org.jgroups.stack.AckSenderWindow;
009: import org.jgroups.util.Util;
010:
011: import java.util.HashMap;
012:
013: /**
014: * Test cases for AckSenderWindow
015: * @author Bela Ban
016: */
017: public class AckSenderWindowTest extends TestCase {
018: AckSenderWindow win = null;
019: final int NUM_MSGS = 100;
020: long[] xmit_timeouts = { 1000, 2000, 4000, 8000 };
021: double PERCENTAGE_OFF = 1.3; // how much can expected xmit_timeout and real timeout differ to still be okay ?
022: HashMap msgs = new HashMap(); // keys=seqnos (Long), values=Entries
023:
024: class Entry {
025: long start_time = 0; // time message was added
026: long first_xmit = 0; // time between start_time and first_xmit should be ca. 1000ms
027: long second_xmit = 0; // time between first_xmit and second_xmit should be ca. 2000ms
028: long third_xmit = 0; // time between third_xmit and second_xmit should be ca. 4000ms
029: long fourth_xmit = 0; // time between third_xmit and second_xmit should be ca. 8000ms
030:
031: Entry() {
032: start_time = System.currentTimeMillis();
033: }
034:
035: /** Entry is correct if xmit timeouts are not more than 30% off the mark */
036: boolean isCorrect(long seqno) {
037: long t;
038: long expected;
039: long diff, delta;
040: boolean off = false;
041:
042: t = first_xmit - start_time;
043: expected = xmit_timeouts[0];
044: diff = Math.abs(expected - t);
045: delta = (long) (expected * PERCENTAGE_OFF);
046: if (diff >= delta)
047: off = true;
048:
049: t = second_xmit - first_xmit;
050: expected = xmit_timeouts[1];
051: diff = Math.abs(expected - t);
052: delta = (long) (expected * PERCENTAGE_OFF);
053: if (diff >= delta)
054: off = true;
055:
056: t = third_xmit - second_xmit;
057: expected = xmit_timeouts[2];
058: diff = Math.abs(expected - t);
059: delta = (long) (expected * PERCENTAGE_OFF);
060: if (diff >= delta)
061: off = true;
062:
063: t = fourth_xmit - third_xmit;
064: expected = xmit_timeouts[3];
065: diff = Math.abs(expected - t);
066: delta = (long) (expected * PERCENTAGE_OFF);
067: if (diff >= delta)
068: off = true;
069:
070: if (off) {
071: System.err.println("#" + seqno + ": " + this + ": ("
072: + "entry is more than " + PERCENTAGE_OFF
073: + " percentage off ");
074: return false;
075: }
076: return true;
077: }
078:
079: public String toString() {
080: StringBuffer sb = new StringBuffer();
081: sb.append(first_xmit - start_time).append(", ").append(
082: second_xmit - first_xmit).append(", ");
083: sb.append(third_xmit - second_xmit).append(", ").append(
084: fourth_xmit - third_xmit);
085: return sb.toString();
086: }
087: }
088:
089: class MyRetransmitCommand implements
090: AckSenderWindow.RetransmitCommand {
091:
092: public void retransmit(long seqno, Message msg) {
093: Entry entry = (Entry) msgs.get(new Long(seqno));
094:
095: // System.out.println(" -- retransmit(" + seqno + ")");
096:
097: if (entry != null) {
098: if (entry.first_xmit == 0) {
099: entry.first_xmit = System.currentTimeMillis();
100: return;
101: }
102:
103: if (entry.second_xmit == 0) {
104: entry.second_xmit = System.currentTimeMillis();
105: return;
106: }
107:
108: if (entry.third_xmit == 0) {
109: entry.third_xmit = System.currentTimeMillis();
110: return;
111: }
112:
113: if (entry.fourth_xmit == 0) {
114: entry.fourth_xmit = System.currentTimeMillis();
115: return;
116: }
117: }
118: }
119:
120: }
121:
122: public AckSenderWindowTest(String name) {
123: super (name);
124: }
125:
126: /** Tests whether retransmits are called at correct times for 1000 messages */
127: public void testRetransmits() {
128: Entry entry;
129: int num_non_correct_entries = 0;
130:
131: win = new AckSenderWindow(new MyRetransmitCommand(),
132: xmit_timeouts);
133:
134: // 1. Send NUM_MSGS messages:
135: System.out.println("-- sending " + NUM_MSGS + " messages:");
136: for (long i = 0; i < NUM_MSGS; i++) {
137: msgs.put(new Long(i), new Entry());
138: win.add(i, new Message());
139: }
140: System.out.println("-- done");
141:
142: // 2. Wait for at least 4 xmits/msg: total of 1000 + 2000 + 4000 + 8000ms = 15000ms; wait for 20000ms
143: System.out
144: .println("-- waiting for 20 secs for all retransmits");
145: Util.sleep(20000);
146:
147: // 3. Check whether all Entries have correct retransmission times
148: for (long i = 0; i < NUM_MSGS; i++) {
149: entry = (Entry) msgs.get(new Long(i));
150: if (!entry.isCorrect(i)) {
151: num_non_correct_entries++;
152: }
153: }
154:
155: if (num_non_correct_entries > 0)
156: System.err
157: .println("Number of incorrect retransmission timeouts: "
158: + num_non_correct_entries);
159: assertTrue(num_non_correct_entries == 0);
160: win.reset();
161: }
162:
163: public static Test suite() {
164: TestSuite suite;
165: suite = new TestSuite(AckSenderWindowTest.class);
166: return (suite);
167: }
168:
169: public static void main(String[] args) {
170: String[] name = { AckSenderWindowTest.class.getName() };
171: junit.textui.TestRunner.main(name);
172: }
173: }
|