/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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.filter;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.supportunit.bean.SupportBean;
import com.espertech.esper.supportunit.bean.SupportBeanSimple;
import com.espertech.esper.supportunit.event.SupportEventBeanFactory;
import com.espertech.esper.supportunit.event.SupportEventTypeFactory;
import com.espertech.esper.supportunit.filter.SupportFilterHandle;
import com.espertech.esper.supportunit.filter.SupportFilterSpecBuilder;
import junit.framework.TestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicReference;
public class TestFilterServiceImpl extends TestCase {
private EventType eventTypeOne;
private EventType eventTypeTwo;
private FilterServiceLockCoarse filterService;
private Vector<FilterValueSet> filterSpecs;
private Vector<SupportFilterHandle> filterCallbacks;
private Vector<EventBean> events;
private Vector<int[]> matchesExpected;
public void setUp() {
filterService = new FilterServiceLockCoarse(false);
eventTypeOne = SupportEventTypeFactory.createBeanType(SupportBean.class);
eventTypeTwo = SupportEventTypeFactory.createBeanType(SupportBeanSimple.class);
filterSpecs = new Vector<FilterValueSet>();
filterSpecs.add(SupportFilterSpecBuilder.build(eventTypeOne, new Object[0]).getValueSet(null, null, null));
filterSpecs.add(SupportFilterSpecBuilder.build(eventTypeOne, new Object[]{
"intPrimitive", FilterOperator.RANGE_CLOSED, 10, 20,
"theString", FilterOperator.EQUAL, "HELLO",
"boolPrimitive", FilterOperator.EQUAL, false,
"doubleBoxed", FilterOperator.GREATER, 100d}).getValueSet(null, null, null));
filterSpecs.add(SupportFilterSpecBuilder.build(eventTypeTwo, new Object[0]).getValueSet(null, null, null));
filterSpecs.add(SupportFilterSpecBuilder.build(eventTypeTwo, new Object[]{
"myInt", FilterOperator.RANGE_HALF_CLOSED, 1, 10,
"myString", FilterOperator.EQUAL, "Hello"}).getValueSet(null, null, null));
// Create callbacks and add
filterCallbacks = new Vector<SupportFilterHandle>();
for (int i = 0; i < filterSpecs.size(); i++) {
filterCallbacks.add(new SupportFilterHandle());
filterService.add(filterSpecs.get(i), filterCallbacks.get(i));
}
// Create events
matchesExpected = new Vector<int[]>();
events = new Vector<EventBean>();
events.add(makeTypeOneEvent(15, "HELLO", false, 101));
matchesExpected.add(new int[]{1, 1, 0, 0});
events.add(makeTypeTwoEvent("Hello", 100));
matchesExpected.add(new int[]{0, 0, 1, 0});
events.add(makeTypeTwoEvent("Hello", 1)); // eventNumber = 2
matchesExpected.add(new int[]{0, 0, 1, 0});
events.add(makeTypeTwoEvent("Hello", 2));
matchesExpected.add(new int[]{0, 0, 1, 1});
events.add(makeTypeOneEvent(15, "HELLO", true, 100));
matchesExpected.add(new int[]{1, 0, 0, 0});
events.add(makeTypeOneEvent(15, "HELLO", false, 99));
matchesExpected.add(new int[]{1, 0, 0, 0});
events.add(makeTypeOneEvent(9, "HELLO", false, 100));
matchesExpected.add(new int[]{1, 0, 0, 0});
events.add(makeTypeOneEvent(10, "no", false, 100));
matchesExpected.add(new int[]{1, 0, 0, 0});
events.add(makeTypeOneEvent(15, "HELLO", false, 999999)); // number 8
matchesExpected.add(new int[]{1, 1, 0, 0});
events.add(makeTypeTwoEvent("Hello", 10));
matchesExpected.add(new int[]{0, 0, 1, 1});
events.add(makeTypeTwoEvent("Hello", 11));
matchesExpected.add(new int[]{0, 0, 1, 0});
}
public void testEvalEvents() {
for (int i = 0; i < events.size(); i++) {
List<FilterHandle> matchList = new LinkedList<FilterHandle>();
filterService.evaluate(events.get(i), matchList);
for (FilterHandle match : matchList) {
SupportFilterHandle handle = (SupportFilterHandle) match;
handle.matchFound(events.get(i), null);
}
int[] matches = matchesExpected.get(i);
for (int j = 0; j < matches.length; j++) {
SupportFilterHandle callback = filterCallbacks.get(j);
if (matches[j] != callback.getAndResetCountInvoked()) {
log.debug(".testEvalEvents Match failed, event=" + events.get(i).getUnderlying());
log.debug(".testEvalEvents Match failed, eventNumber=" + i + " index=" + j);
assertTrue(false);
}
}
}
}
/**
* Test for removing a callback that is waiting to occur,
* ie. a callback is removed which was a result of an evaluation and it
* thus needs to be removed from the tree AND the current dispatch list.
*/
public void testActiveCallbackRemove() {
FilterValueSet spec = SupportFilterSpecBuilder.build(eventTypeOne, new Object[0]).getValueSet(null, null, null);
final SupportFilterHandle callbackTwo = new SupportFilterHandle();
// callback that removes another matching filter spec callback
final AtomicReference<FilterServiceEntry> filterServiceEntryOne = new AtomicReference<FilterServiceEntry>();
FilterHandleCallback callbackOne = new FilterHandleCallback() {
public int getStatementId() {
return 1;
}
public void matchFound(EventBean theEvent, Collection<FilterHandleCallback> allStmtMatches) {
log.debug(".matchFound Removing callbackTwo");
filterService.remove(callbackTwo, filterServiceEntryOne.get());
}
public boolean isSubSelect() {
return false;
}
};
FilterServiceEntry filterServiceEntry = filterService.add(spec, callbackOne);
filterServiceEntryOne.set(filterServiceEntry);
filterService.add(spec, callbackTwo);
// send event
EventBean theEvent = makeTypeOneEvent(1, "HELLO", false, 1);
List<FilterHandle> matches = new LinkedList<FilterHandle>();
filterService.evaluate(theEvent, matches);
for (FilterHandle match : matches) {
FilterHandleCallback handle = (FilterHandleCallback) match;
handle.matchFound(theEvent, null);
}
// Callback two MUST be invoked, was removed by callback one, but since the
// callback invocation order should not matter, the second one MUST also execute
assertEquals(1, callbackTwo.getAndResetCountInvoked());
}
private EventBean makeTypeOneEvent(int intPrimitive, String theString, boolean boolPrimitive, double doubleBoxed) {
SupportBean bean = new SupportBean();
bean.setIntPrimitive(intPrimitive);
bean.setTheString(theString);
bean.setBoolPrimitive(boolPrimitive);
bean.setDoubleBoxed(doubleBoxed);
return SupportEventBeanFactory.createObject(bean);
}
private EventBean makeTypeTwoEvent(String myString, int myInt) {
SupportBeanSimple bean = new SupportBeanSimple(myString, myInt);
return SupportEventBeanFactory.createObject(bean);
}
private static final Logger log = LoggerFactory.getLogger(TestFilterServiceImpl.class);
}