/*
* *************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
* *************************************************************************************
*/
package com.espertech.esper.schedule;
import com.espertech.esper.support.schedule.SupportScheduleCallback;
import com.espertech.esper.timer.TimeSourceServiceImpl;
import com.espertech.esper.type.ScheduleUnit;
import junit.framework.TestCase;
import java.util.Calendar;
import java.util.Collection;
import java.util.LinkedList;
public class TestSchedulingServiceImpl extends TestCase
{
private SchedulingServiceImpl service;
private SchedulingMgmtServiceImpl mgmtService;
private ScheduleSlot slots[][];
private SupportScheduleCallback callbacks[];
public void setUp()
{
service = new SchedulingServiceImpl(new TimeSourceServiceImpl());
mgmtService = new SchedulingMgmtServiceImpl();
// 2-by-2 table of buckets and slots
ScheduleBucket[] buckets = new ScheduleBucket[3];
slots = new ScheduleSlot[buckets.length][2];
for (int i = 0; i < buckets.length; i++)
{
buckets[i] = mgmtService.allocateBucket();
slots[i] = new ScheduleSlot[2];
for (int j = 0; j < slots[i].length; j++)
{
slots[i][j] = buckets[i].allocateSlot();
}
}
callbacks = new SupportScheduleCallback[5];
for (int i= 0; i < callbacks.length; i++)
{
callbacks[i] = new SupportScheduleCallback();
}
}
public void testAddTwice()
{
service.add(100, callbacks[0], slots[0][0]);
assertTrue(service.isScheduled(callbacks[0]));
service.add(100, callbacks[0], slots[0][0]);
service.add(ScheduleComputeHelper.computeNextOccurance(new ScheduleSpec(), service.getTime()), callbacks[1], slots[0][0]);
service.add(ScheduleComputeHelper.computeNextOccurance(new ScheduleSpec(), service.getTime()), callbacks[1], slots[0][0]);
}
public void testTrigger()
{
long startTime = 0;
service.setTime(0);
// Add callbacks
service.add(20, callbacks[3], slots[1][1]);
service.add(20, callbacks[2], slots[1][0]);
service.add(20, callbacks[1], slots[0][1]);
service.add(21, callbacks[0], slots[0][0]);
assertTrue(service.isScheduled(callbacks[3]));
assertTrue(service.isScheduled(callbacks[0]));
// Evaluate before the within time, expect not results
startTime += 19;
service.setTime(startTime);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
assertTrue(service.isScheduled(callbacks[3]));
// Evaluate exactly on the within time, expect a result
startTime += 1;
service.setTime(startTime);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 1, 2, 3, 0});
assertFalse(service.isScheduled(callbacks[3]));
// Evaluate after already evaluated once, no result
startTime += 1;
service.setTime(startTime);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {4, 0, 0, 0, 0});
assertFalse(service.isScheduled(callbacks[3]));
startTime += 1;
service.setTime(startTime);
evaluateSchedule();
assertEquals(0, callbacks[3].clearAndGetOrderTriggered());
// Adding the same callback more than once should cause an exception
service.add(20, callbacks[0], slots[0][0]);
service.add(28, callbacks[0], slots[0][0]);
service.remove(callbacks[0], slots[0][0]);
service.add(20, callbacks[2], slots[1][0]);
service.add(25, callbacks[1], slots[0][1]);
service.remove(callbacks[1], slots[0][1]);
service.add(21, callbacks[0], slots[0][0]);
service.add(21, callbacks[3], slots[1][1]);
service.add(20, callbacks[1], slots[0][1]);
SupportScheduleCallback.setCallbackOrderNum(0);
startTime += 20;
service.setTime(startTime);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 1, 2, 0, 0});
startTime += 1;
service.setTime(startTime);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {3, 0, 0, 4, 0});
service.setTime(startTime + Integer.MAX_VALUE);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
}
public void testWaitAndSpecTogether()
{
Calendar calendar = Calendar.getInstance();
calendar.set(2004, 11, 9, 15, 27, 10);
calendar.set(Calendar.MILLISECOND, 500);
long startTime = calendar.getTimeInMillis();
service.setTime(startTime);
// Add a specification
ScheduleSpec spec = new ScheduleSpec();
spec.addValue(ScheduleUnit.MONTHS, 12);
spec.addValue(ScheduleUnit.DAYS_OF_MONTH, 9);
spec.addValue(ScheduleUnit.HOURS, 15);
spec.addValue(ScheduleUnit.MINUTES, 27);
spec.addValue(ScheduleUnit.SECONDS, 20);
service.add(ScheduleComputeHelper.computeDeltaNextOccurance(spec, service.getTime()), callbacks[3], slots[1][1]);
spec.addValue(ScheduleUnit.SECONDS, 15);
service.add(ScheduleComputeHelper.computeDeltaNextOccurance(spec, service.getTime()), callbacks[4], slots[2][0]);
// Add some more callbacks
service.add(5000, callbacks[0], slots[0][0]);
service.add(10000, callbacks[1], slots[0][1]);
service.add(15000, callbacks[2], slots[1][0]);
// Now send a times reflecting various seconds later and check who got a callback
service.setTime(startTime + 1000);
SupportScheduleCallback.setCallbackOrderNum(0);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
service.setTime(startTime + 2000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
service.setTime(startTime + 4000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
service.setTime(startTime + 5000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {1, 0, 0, 0, 2});
service.setTime(startTime + 9000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
service.setTime(startTime + 10000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 3, 0, 4, 0});
service.setTime(startTime + 11000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
service.setTime(startTime + 15000);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 5, 0, 0});
service.setTime(startTime + Integer.MAX_VALUE);
evaluateSchedule();
checkCallbacks(callbacks, new Integer[] {0, 0, 0, 0, 0});
}
public void testIncorrectRemove()
{
SchedulingServiceImpl evaluator = new SchedulingServiceImpl(new TimeSourceServiceImpl());
SupportScheduleCallback callback = new SupportScheduleCallback();
evaluator.remove(callback, null);
}
private void checkCallbacks(SupportScheduleCallback callbacks[], Integer[] results)
{
assertTrue(callbacks.length == results.length);
for (int i = 0; i < callbacks.length; i++)
{
assertEquals((int) results[i], (int) callbacks[i].clearAndGetOrderTriggered());
}
}
private void evaluateSchedule()
{
Collection<ScheduleHandle> handles = new LinkedList<ScheduleHandle>();
service.evaluate(handles);
for (ScheduleHandle handle : handles)
{
ScheduleHandleCallback cb = (ScheduleHandleCallback) handle;
cb.scheduledTrigger(null);
}
}
}