/*
* *************************************************************************************
* 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.regression.pattern;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import junit.framework.TestCase;
import com.espertech.esper.client.*;
import com.espertech.esper.client.soda.EPStatementObjectModel;
import com.espertech.esper.client.time.CurrentTimeEvent;
import com.espertech.esper.client.time.TimerEvent;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.event.EventBeanUtility;
import com.espertech.esper.regression.support.EventCollection;
import com.espertech.esper.regression.support.EventDescriptor;
import com.espertech.esper.regression.support.EventExpressionCase;
import com.espertech.esper.support.bean.SupportBeanConstants;
import com.espertech.esper.support.bean.SupportBean_A;
import com.espertech.esper.support.client.SupportConfigFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.*;
public class TestCronParameter extends TestCase implements SupportBeanConstants
{
private EPStatement patternStmt;
private String expressionText;
private static long baseTime;
private EventCollection testData;
private EventExpressionCase testCase;
private SupportUpdateListener listener;
private Calendar calendar;
private final Log log = LogFactory.getLog(getClass());
public void setUp()
{
listener = new SupportUpdateListener();
testCase = null;
calendar = Calendar.getInstance();
}
protected void tearDown() throws Exception {
listener = null;
}
public void testOperator() throws Exception
{
// Observer for last Sunday of month, 0 = Sunday
int lastDayOfWeek = getLastDayOfWeekInMonth(0, 2007);
calendar.set(2007, getCurrentMonth(2007), lastDayOfWeek, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, *, *, 0 last, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last day of current month
calendar.set(2007, getCurrentMonth(2007), getLastDayOfMonth(2007), 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, last, *, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last day of Auguts 2007
// For Java: January=0, February=1, March=2, April=3, May=4, June=5,
// July=6, August=7, September=8, November=9, October=10, December=11
// For Esper: January=1, February=2, March=3, April=4, May=5, June=6,
// July=7, August=8, September=9, November=10, October=11, December=12
calendar.set(2007, Calendar.AUGUST, 31, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, last, 8, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last day of February 2007
calendar.set(2007, Calendar.FEBRUARY, 28, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, last, 2, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last day of week (Saturday)
Calendar calendar = Calendar.getInstance();
Date date = new Date();
calendar.setTime(date);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, *, *, last, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last Friday of June
calendar.set(2007, Calendar.JUNE, 29, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, *, 6, 5 last, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last weekday of the current month
calendar.set(2007, getCurrentMonth(2007), getLastWeekDayOfMonth(null, 2007), 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, lastweekday, *, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last weekday of September 2007, it's Friday September 28th
calendar.set(2007, Calendar.SEPTEMBER, 28, 10, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, lastweekday, 9, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last weekday of February, it's Wednesday February 28th
calendar.set(2007, Calendar.FEBRUARY, 28, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, lastweekday, 2, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for nearest weekday for current month on the 10th
calendar.set(2007, getCurrentMonth(2007), getLastWeekDayOfMonth(10, 2007), 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, 10 weekday, *, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for nearest weekday of September 1st (Saturday), it's Monday September 3rd (no "jump" over month)
calendar.set(2007, Calendar.SEPTEMBER, 3, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, 1 weekday, 9, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for nearest weekday of September 30th (Sunday), it's Friday September 28th (no "jump" over month)
calendar.set(2007, Calendar.SEPTEMBER, 28, 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, 30 weekday, 9, *, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
// Observer for last Friday of current month,
// 0=Sunday, 1=Monday, 2=Tuesday, 3=Wednesday, 4= Thursday, 5=Friday, 6=Saturday
calendar.set(2007, getCurrentMonth(2007), getLastDayOfWeekInMonth(5, 2007), 8, 00, 00);
printCurrentTime(calendar);
baseTime = calendar.getTimeInMillis();
testData = getEventSet(baseTime, 1000 * 60 * 10);
expressionText = "timer:at(*, *, *, *, 5 last, *)";
testCase = new EventExpressionCase(expressionText);
testCase.add("A1");
runTestEvent();
}
private void runTestEvent()
{
int totalEventsReceived = 0;
Configuration config = SupportConfigFactory.getConfiguration();
EPServiceProvider serviceProvider = EPServiceProviderManager.getDefaultProvider(config);
serviceProvider.initialize();
EPRuntime runtime = serviceProvider.getEPRuntime();
// Send the start time to the runtime
TimerEvent startTime = new CurrentTimeEvent(baseTime);
runtime.sendEvent(startTime);
log.debug(".runTest Start time is " + startTime);
try
{
patternStmt = serviceProvider.getEPAdministrator().createPattern(expressionText);
}
catch (Exception ex)
{
log.fatal(".runTest Failed to create statement for pattern expression=" + expressionText, ex);
TestCase.fail();
}
patternStmt.addListener(listener);
// Send actual test events
for (Map.Entry<String, Object> entry : testData.entrySet())
{
String eventId = entry.getKey();
// Manipulate the time when this event was send
if (testData.getTime(eventId) != null)
{
TimerEvent currentTimeEvent = new CurrentTimeEvent(testData.getTime(eventId));
runtime.sendEvent(currentTimeEvent);
log.debug(".runTest Sending event " + entry.getKey()
+ " = " + entry.getValue() +
" timed " + currentTimeEvent);
}
// Send event itself
runtime.sendEvent(entry.getValue());
// Check expected results for this event
checkResults(eventId);
// Count and clear the list of events that each listener has received
totalEventsReceived += countListenerEvents();
}
// Count number of expected matches
int totalExpected = 0;
for (LinkedList<EventDescriptor> events : testCase.getExpectedResults().values())
{
totalExpected += events.size();
}
if (totalExpected != totalEventsReceived)
{
log.debug(".test Count expected does not match count received, expected=" + totalExpected +
" received=" + totalEventsReceived);
TestCase.assertTrue(false);
}
// Kill expression
patternStmt.removeAllListeners();
// Send test events again to also test that all were indeed killed
for (Map.Entry<String, Object> entry : testData.entrySet())
{
runtime.sendEvent(entry.getValue());
}
if (listener.getNewDataList().size() > 0)
{
log.debug(".test A match was received after stopping all expressions");
TestCase.assertTrue(false);
}
// test the object model
String epl = "select * from pattern [" + expressionText + "]";
EPStatementObjectModel model = serviceProvider.getEPAdministrator().compileEPL(epl);
assertEquals(epl, model.toEPL());
EPStatement stmt = serviceProvider.getEPAdministrator().create(model);
assertEquals(epl, stmt.getText());
}
private void checkResults(String eventId)
{
log.debug(".checkResults Checking results for event " + eventId);
String expressionText = patternStmt.getText();
LinkedHashMap<String, LinkedList<EventDescriptor>> allExpectedResults = testCase.getExpectedResults();
EventBean[] receivedResults = listener.getLastNewData();
// If nothing at all was expected for this event, make sure nothing was received
if (!(allExpectedResults.containsKey(eventId)))
{
if ((receivedResults != null) && (receivedResults.length > 0))
{
log.debug(".checkResults Incorrect result for expression : " + expressionText);
log.debug(".checkResults Expected no results for event " + eventId + ", but received " + receivedResults.length + " events");
log.debug(".checkResults Received, have " + receivedResults.length + " entries");
printList(receivedResults);
TestCase.assertFalse(true);
}
}
LinkedList<EventDescriptor> expectedResults = allExpectedResults.get(eventId);
// Compare the result lists, not caring about the order of the elements
if (!(compareLists(receivedResults, expectedResults)))
{
log.debug(".checkResults Incorrect result for expression : " + expressionText);
log.debug(".checkResults Expected size=" + expectedResults.size() + " received size=" + (receivedResults == null ? 0 : receivedResults.length));
log.debug(".checkResults Expected, have " + expectedResults.size() + " entries");
printList(expectedResults);
log.debug(".checkResults Received, have " + (receivedResults == null ? 0 : receivedResults.length) + " entries");
printList(receivedResults);
TestCase.assertFalse(true);
}
}
private boolean compareLists(EventBean[] receivedResults,
LinkedList<EventDescriptor> expectedResults)
{
int receivedSize = (receivedResults == null) ? 0 : receivedResults.length;
if (expectedResults.size() != receivedSize)
{
return false;
}
// To make sure all received events have been expected
LinkedList<EventDescriptor> expectedResultsClone = new LinkedList<EventDescriptor>(expectedResults);
// Go through the list of expected results and remove from received result list if found
for (EventDescriptor desc : expectedResults)
{
EventDescriptor foundMatch = null;
for (EventBean received : receivedResults)
{
if (compareEvents(desc, received))
{
foundMatch = desc;
break;
}
}
// No match between expected and received
if (foundMatch == null)
{
return false;
}
expectedResultsClone.remove(foundMatch);
}
// Any left over received results also invalidate the test
if (expectedResultsClone.size() > 0)
{
return false;
}
return true;
}
private static boolean compareEvents(EventDescriptor eventDesc, EventBean eventBean)
{
for (Map.Entry<String, Object> entry : eventDesc.getEventProperties().entrySet())
{
if (!(eventBean.get(entry.getKey()) == (entry.getValue())))
{
return false;
}
}
return true;
}
private void printList(LinkedList<EventDescriptor> events)
{
int index = 0;
for (EventDescriptor desc : events)
{
StringBuffer buffer = new StringBuffer();
int count = 0;
for (Map.Entry<String, Object> entry : desc.getEventProperties().entrySet())
{
buffer.append(" (" + (count++) + ") ");
buffer.append("tag=" + entry.getKey());
String id = findValue(entry.getValue());
buffer.append(" eventId=" + id);
}
log.debug(".printList (" + index + ") : " + buffer.toString());
index++;
}
}
private void printList(EventBean[] events)
{
if (events == null)
{
log.debug(".printList : null-value events array");
return;
}
log.debug(".printList : " + events.length + " elements...");
for (int i = 0; i < events.length; i++)
{
log.debug(" " + EventBeanUtility.printEvent(events[i]));
}
}
private String findValue(Object value)
{
for (Map.Entry<String, Object> entry : testData.entrySet())
{
if (value == entry.getValue())
{
return entry.getKey();
}
}
return null;
}
private int countListenerEvents()
{
int count = 0;
for (EventBean[] events : listener.getNewDataList())
{
count += events.length;
}
listener.reset();
return count;
}
private EventCollection getEventSet(long baseTime, long numMSecBetweenEvents)
{
LinkedHashMap<String, Object> testData = new LinkedHashMap<String, Object>();
testData.put("A1", new SupportBean_A("A1"));
LinkedHashMap<String, Long> times = makeExternalClockTimes(testData, baseTime, numMSecBetweenEvents);
return new EventCollection(testData, times);
}
private LinkedHashMap<String, Long> makeExternalClockTimes(LinkedHashMap<String, Object> testData,
long baseTime,
long numMSecBetweenEvents)
{
LinkedHashMap<String, Long> testDataTimers = new LinkedHashMap<String, Long>();
testDataTimers.put(EventCollection.ON_START_EVENT_ID, baseTime);
for (String id : testData.keySet())
{
baseTime += numMSecBetweenEvents;
testDataTimers.put(id, baseTime);
}
return testDataTimers;
}
private int getCurrentMonth(int year)
{
setTime(year);
return calendar.get(Calendar.MONTH);
}
private int getLastDayOfMonth(int year)
{
setTime(year);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
return calendar.get(Calendar.DAY_OF_MONTH);
}
private int getLastDayOfWeekInMonth(int day, int year)
{
if (day < 0 || day > 7)
{
throw new IllegalArgumentException("Last xx day of the month has to be a day of week (0-7)");
}
int dayOfWeek = getDayOfWeek(day, year);
setTime(year);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
int dayDiff = calendar.get(Calendar.DAY_OF_WEEK) - dayOfWeek;
if (dayDiff > 0)
{
calendar.add(Calendar.DAY_OF_WEEK, -dayDiff);
}
else if (dayDiff < 0)
{
calendar.add(Calendar.DAY_OF_WEEK, -7 - dayDiff);
}
return calendar.get(Calendar.DAY_OF_MONTH);
}
private int getLastWeekDayOfMonth(Integer day, int year)
{
int computeDay = (day == null) ? getLastDayOfMonth(year) : day;
setTime(year);
if (!checkDayValidInMonth(computeDay, calendar.get(Calendar.MONTH), calendar.get(Calendar.YEAR)))
{
throw new IllegalArgumentException("Invalid day for " + calendar.get(Calendar.MONTH));
}
calendar.set(Calendar.DAY_OF_MONTH, computeDay);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
if ((dayOfWeek >= Calendar.MONDAY) && (dayOfWeek <= Calendar.FRIDAY))
{
return computeDay;
}
if (dayOfWeek == Calendar.SATURDAY)
{
if (computeDay == 1)
{
calendar.add(Calendar.DAY_OF_MONTH, +2);
}
else
{
calendar.add(Calendar.DAY_OF_MONTH, -1);
}
}
if (dayOfWeek == Calendar.SUNDAY)
{
if ((computeDay == 28) || (computeDay == 29) || (computeDay == 30) || (computeDay == 31))
{
calendar.add(Calendar.DAY_OF_MONTH, -2);
}
else
{
calendar.add(Calendar.DAY_OF_MONTH, +2);
}
}
return calendar.get(Calendar.DAY_OF_MONTH);
}
private int getDayOfWeek(int day, int year)
{
setTime(year);
calendar.set(Calendar.DAY_OF_WEEK, day + 1);
return calendar.get(Calendar.DAY_OF_WEEK);
}
private void setTime(int year)
{
Date date = new Date();
calendar.setTime(date);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.DAY_OF_MONTH, 1);
}
private boolean checkDayValidInMonth(int day, int month, int year)
{
try
{
Calendar calendar = Calendar.getInstance();
calendar.setLenient(false);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
calendar.getTime();
}
catch (IllegalArgumentException e)
{
return false;
}
return true;
}
private void printCurrentTime(Calendar cal)
{
Date date = cal.getTime();
//System.out.println(new SimpleDateFormat("EEEE").format(date) + " " + new SimpleDateFormat("MMM").format(date) +
// " " + cal.get(Calendar.DAY_OF_MONTH) + " " + cal.get(Calendar.YEAR));
}
}