001: // $Id: TimerTest.java,v 1.5 2005/12/23 18:36:28 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.stack.Interval;
008: import org.jgroups.util.Util;
009:
010: import java.util.HashMap;
011: import java.util.Timer;
012: import java.util.TimerTask;
013:
014: /**
015: * Test cases for Timer. May fail sometimes, for example if there is GC during the run. Therefore, if run
016: * standalone, the likelyhood of GC is smaller than when run with the entire testsuite
017: *
018: * @author Bela Ban
019: */
020: public class TimerTest extends TestCase {
021: Timer win = null;
022: final int NUM_MSGS = 1000;
023: long[] xmit_timeouts = { 1000, 2000, 4000, 8000 };
024: double PERCENTAGE_OFF = 0.3; // how much can expected xmit_timeout and real timeout differ to still be okay ?
025: HashMap msgs = new HashMap(); // keys=seqnos (Long), values=Entries
026:
027: class MyTask extends TimerTask {
028: Entry entry;
029:
030: MyTask(Entry entry) {
031: this .entry = entry;
032: }
033:
034: public void run() {
035: entry.retransmit();
036: }
037:
038: }
039:
040: class Entry {
041: long start_time = 0; // time message was added
042: long first_xmit = 0; // time between start_time and first_xmit should be ca. 1000ms
043: long second_xmit = 0; // time between first_xmit and second_xmit should be ca. 2000ms
044: long third_xmit = 0; // time between third_xmit and second_xmit should be ca. 4000ms
045: long fourth_xmit = 0; // time between third_xmit and second_xmit should be ca. 8000ms
046: Interval interval = new Interval(xmit_timeouts);
047: long seqno = 0;
048:
049: Entry(long seqno) {
050: this .seqno = seqno;
051: start_time = System.currentTimeMillis();
052: }
053:
054: public void retransmit() {
055: if (first_xmit == 0)
056: first_xmit = System.currentTimeMillis();
057: else if (second_xmit == 0)
058: second_xmit = System.currentTimeMillis();
059: else if (third_xmit == 0)
060: third_xmit = System.currentTimeMillis();
061: else if (fourth_xmit == 0)
062: fourth_xmit = System.currentTimeMillis();
063:
064: win.schedule(new MyTask(this ), interval.next());
065: }
066:
067: public long next() {
068: return interval.next();
069: }
070:
071: /**
072: * Entry is correct if xmit timeouts are not more than 30% off the mark
073: */
074: boolean isCorrect() {
075: long t;
076: long expected;
077: long diff, delta;
078: boolean off = false;
079:
080: t = first_xmit - start_time;
081: expected = xmit_timeouts[0];
082: diff = Math.abs(expected - t);
083: delta = (long) (expected * PERCENTAGE_OFF);
084: if (diff >= delta)
085: off = true;
086:
087: t = second_xmit - first_xmit;
088: expected = xmit_timeouts[1];
089: diff = Math.abs(expected - t);
090: delta = (long) (expected * PERCENTAGE_OFF);
091: if (diff >= delta)
092: off = true;
093:
094: t = third_xmit - second_xmit;
095: expected = xmit_timeouts[2];
096: diff = Math.abs(expected - t);
097: delta = (long) (expected * PERCENTAGE_OFF);
098: if (diff >= delta)
099: off = true;
100:
101: t = fourth_xmit - third_xmit;
102: expected = xmit_timeouts[3];
103: diff = Math.abs(expected - t);
104: delta = (long) (expected * PERCENTAGE_OFF);
105: if (diff >= delta)
106: off = true;
107:
108: if (off) {
109: System.err.println("#" + seqno + ": " + this + ": ("
110: + "entry is more than " + PERCENTAGE_OFF
111: + " percentage off ");
112: return false;
113: }
114: return true;
115: }
116:
117: public String toString() {
118: StringBuffer sb = new StringBuffer();
119: sb.append(first_xmit - start_time).append(", ").append(
120: second_xmit - first_xmit).append(", ");
121: sb.append(third_xmit - second_xmit).append(", ").append(
122: fourth_xmit - third_xmit);
123: return sb.toString();
124: }
125: }
126:
127: public TimerTest(String name) {
128: super (name);
129: }
130:
131: /**
132: * Tests whether retransmits are called at correct times for 1000 messages. A retransmit should not be
133: * more than 30% earlier or later than the scheduled retransmission time
134: */
135: public void testRetransmits() {
136: Entry entry;
137: MyTask task;
138: int num_non_correct_entries = 0;
139:
140: win = new Timer();
141:
142: // 1. Add NUM_MSGS messages:
143: System.out.println("-- adding " + NUM_MSGS + " messages:");
144: for (long i = 0; i < NUM_MSGS; i++) {
145: entry = new Entry(i);
146: task = new MyTask(entry);
147: msgs.put(new Long(i), entry);
148: win.schedule(task, entry.next());
149: }
150: System.out.println("-- done");
151:
152: // 2. Wait for at least 4 xmits/msg: total of 1000 + 2000 + 4000 + 8000ms = 15000ms; wait for 20000ms
153: System.out
154: .println("-- waiting for 20 secs for all retransmits");
155: Util.sleep(20000);
156:
157: // 3. Check whether all Entries have correct retransmission times
158: for (long i = 0; i < NUM_MSGS; i++) {
159: entry = (Entry) msgs.get(new Long(i));
160: if (!entry.isCorrect()) {
161: num_non_correct_entries++;
162: }
163: }
164:
165: if (num_non_correct_entries > 0)
166: System.err
167: .println("Number of incorrect retransmission timeouts: "
168: + num_non_correct_entries);
169: else {
170: for (long i = 0; i < NUM_MSGS; i++) {
171: entry = (Entry) msgs.get(new Long(i));
172: if (entry != null)
173: System.out.println(i + ": " + entry);
174: }
175: }
176: assertTrue(num_non_correct_entries == 0);
177: try {
178: win.cancel();
179: } catch (Exception ex) {
180: System.err.println(ex);
181: }
182: }
183:
184: public static Test suite() {
185: TestSuite suite;
186: suite = new TestSuite(TimerTest.class);
187: return (suite);
188: }
189:
190: public static void main(String[] args) {
191: String[] name = { TimerTest.class.getName() };
192: junit.textui.TestRunner.main(name);
193: }
194: }
|