package io.craft.atom.util.schedule; import io.craft.atom.test.CaseCounter; import io.craft.atom.util.schedule.ExpirationListener; import io.craft.atom.util.schedule.TimingWheel; import java.util.Date; import java.util.Set; import java.util.concurrent.TimeUnit; import junit.framework.Assert; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author mindwind * @version 1.0, Sep 21, 2012 */ public class TestTimingWheel { private static final Logger LOG = LoggerFactory.getLogger(TestTimingWheel.class); private TimingWheel<String> wheel ; private volatile long startTime; private volatile long endTime ; @Before public void before() { wheel = new TimingWheel<String>(1, 500, TimeUnit.MILLISECONDS); wheel.addExpirationListener(new TestExpirationListener()); wheel.start(); } @After public void after() { wheel.stop(); } @Test public void testAdd() throws InterruptedException { startTime = System.currentTimeMillis(); long ttl = wheel.add("test-0"); LOG.debug("[CRAFT-ATOM-UTIL] Add object test-0 to timing wheel, will timeout after {} ms, start time={}", ttl, new Date(startTime)); for (int i = 1; i <= 30; i++) { Thread.sleep(10); wheel.add("test-" + i); } Assert.assertEquals(31, wheel.size()); System.out.println(String.format("[CRAFT-ATOM-UTIL] (^_^) <%s> Case -> test timing wheel add. ", CaseCounter.incr(1))); } @Test public void testRemove() throws InterruptedException { for (int i = 1; i <= 10; i++) { Thread.sleep(10); wheel.add("test-" + i); } Assert.assertEquals(10, wheel.size()); wheel.remove("test-3"); wheel.remove("test-4"); wheel.remove("test-5"); Assert.assertEquals(7, wheel.size()); Set<String> set = wheel.elements(); Assert.assertEquals(7, set.size()); System.out.println(String.format("[CRAFT-ATOM-UTIL] (^_^) <%s> Case -> test timing wheel remove. ", CaseCounter.incr(3))); } @Test public void testAddTwice() throws InterruptedException { startTime = System.currentTimeMillis(); long ttl = wheel.add("test-1"); LOG.debug("[CRAFT-ATOM-UTIL] Add object test-1 to timing wheel, will timeout after {} ms, start time={}", ttl, new Date(startTime)); Thread.sleep(20); ttl = wheel.add("test-1"); LOG.debug("[CRAFT-ATOM-UTIL] Add object test-1 second to timing wheel, will timeout after {} ms, start time={}", ttl, new Date(startTime)); Assert.assertEquals(1, wheel.size()); System.out.println(String.format("[CRAFT-ATOM-UTIL] (^_^) <%s> Case -> test timing wheel add twice. ", CaseCounter.incr(1))); } @Test public void testExpire() throws InterruptedException { startTime = System.currentTimeMillis(); long ttl = wheel.add("test-1"); while(endTime == 0); long deviation = (endTime - startTime) - ttl; LOG.debug("[CRAFT-ATOM-UTIL] Timing wheel deviation={}", deviation); Assert.assertTrue(deviation <= 2); Assert.assertTrue(deviation >= -2); System.out.println(String.format("[CRAFT-ATOM-UTIL] (^_^) <%s> Case -> test timing wheel expire. ", CaseCounter.incr(2))); } private class TestExpirationListener implements ExpirationListener<String> { @Override public void expired(String expiredObject) { endTime = System.currentTimeMillis(); LOG.debug("[CRAFT-ATOM-UTIL] Expired object={} end time={}", expiredObject, new Date(endTime)); } } }