/*
***************************************************************************************
* 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.regression.pattern;
import com.espertech.esper.client.*;
import com.espertech.esper.client.scopetest.EPAssertionUtil;
import com.espertech.esper.client.scopetest.SupportUpdateListener;
import com.espertech.esper.client.soda.EPStatementObjectModel;
import com.espertech.esper.client.time.CurrentTimeEvent;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.supportregression.client.SupportConfigFactory;
import junit.framework.TestCase;
import java.io.Serializable;
public class TestConsumingPattern extends TestCase
{
private EPServiceProvider epService;
private SupportUpdateListener listener;
public void setUp()
{
Configuration configuration = SupportConfigFactory.getConfiguration();
epService = EPServiceProviderManager.getDefaultProvider(configuration);
epService.initialize();
epService.getEPAdministrator().getConfiguration().addEventType("A", AEvent.class);
epService.getEPAdministrator().getConfiguration().addEventType("B", BEvent.class);
epService.getEPAdministrator().getConfiguration().addEventType("C", CEvent.class);
epService.getEPAdministrator().getConfiguration().addEventType("D", DEvent.class);
listener = new SupportUpdateListener();
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());}
}
protected void tearDown() throws Exception {
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();}
listener = null;
}
public void testInvalid() {
tryInvalid("select * from pattern @XX [A]",
"Error in expression: Unrecognized pattern-level annotation 'XX' [select * from pattern @XX [A]]");
String expected = "Discard-partials and suppress-matches is not supported in a joins, context declaration and on-action ";
tryInvalid("select * from pattern " + TargetEnum.DISCARD_AND_SUPPRESS.getText() + "[A]#keepall, A#keepall",
expected + "[select * from pattern @DiscardPartialsOnMatch @SuppressOverlappingMatches [A]#keepall, A#keepall]");
epService.getEPAdministrator().createEPL("create window AWindow#keepall as A");
tryInvalid("on pattern " + TargetEnum.DISCARD_AND_SUPPRESS.getText() + "[A] select * from AWindow",
expected + "[on pattern @DiscardPartialsOnMatch @SuppressOverlappingMatches [A] select * from AWindow]");
}
public void testCombination() {
for (boolean testsoda : new boolean[] {false, true}) {
for (TargetEnum target : TargetEnum.values()) {
runAssertionTargetCurrentMatch(testsoda, target);
runAssertionTargetNextMatch(testsoda, target);
}
}
// test order-by
epService.getEPAdministrator().createEPL("select * from pattern @DiscardPartialsOnMatch [every a=A -> B] order by a.id desc").addListener(listener);
epService.getEPRuntime().sendEvent(new AEvent("A1", null, null));
epService.getEPRuntime().sendEvent(new AEvent("A2", null, null));
epService.getEPRuntime().sendEvent(new BEvent("B1", null));
EventBean[] events = listener.getAndResetLastNewData();
EPAssertionUtil.assertPropsPerRow(events, "a.id".split(","), new Object[][]{{"A2"}, {"A1"}});
}
public void testFollowedByOp() {
runFollowedByOp("every a1=A -> a2=A", false);
runFollowedByOp("every a1=A -> a2=A", true);
runFollowedByOp("every a1=A -[10]> a2=A", false);
runFollowedByOp("every a1=A -[10]> a2=A", true);
}
public void testMatchUntilOp() {
runAssertionMatchUntilBoundOp(true);
runAssertionMatchUntilBoundOp(false);
runAssertionMatchUntilWChildMatcher(true);
runAssertionMatchUntilWChildMatcher(false);
runAssertionMatchUntilRangeOpWTime(); // with time
}
public void testObserverOp() {
String[] fields = "a.id,b.id".split(",");
sendTime(0);
epService.getEPAdministrator().createEPL("select * from pattern " + TargetEnum.DISCARD_ONLY.getText() + " [" +
"every a=A -> b=B -> timer:interval(a.mysec)]").addListener(listener);
sendAEvent("A1", 5); // 5 seconds for this one
sendAEvent("A2", 1); // 1 seconds for this one
sendBEvent("B1");
sendTime(1000);
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1"});
sendTime(5000);
assertFalse(listener.isInvoked());
}
public void testAndOp() {
runAndWAndState(true);
runAndWAndState(false);
runAndWChild(true);
runAndWChild(false);
}
public void testNotOpNotImpacted() {
String[] fields = "a.id".split(",");
sendTime(0);
epService.getEPAdministrator().createEPL("select * from pattern " + TargetEnum.DISCARD_ONLY.getText() + " [" +
"every a=A -> timer:interval(a.mysec) and not (B -> C)]").addListener(listener);
sendAEvent("A1", 5); // 5 sec
sendAEvent("A2", 1); // 1 sec
sendBEvent("B1");
sendTime(1000);
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2"});
sendCEvent("C1", null);
sendTime(5000);
assertFalse(listener.isInvoked());
}
public void testGuardOp() {
runGuardOpBeginState(true);
runGuardOpBeginState(false);
runGuardOpChildState(true);
runGuardOpChildState(false);
}
public void testOrOp() {
String[] fields = "a.id,b.id,c.id".split(",");
sendTime(0);
epService.getEPAdministrator().createEPL("select * from pattern " + TargetEnum.DISCARD_ONLY.getText() + " [" +
"every a=A -> (b=B -> c=C(pc=a.pa)) or timer:interval(1000)]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C1", "x");
assertFalse(listener.isInvoked());
}
public void testEveryOp() {
runAssertionEveryBeginState("");
runAssertionEveryBeginState("-distinct(id)");
runAssertionEveryBeginState("-distinct(id, 10 seconds)");
runAssertionEveryChildState("", true);
runAssertionEveryChildState("", false);
runAssertionEveryChildState("-distinct(id)", true);
runAssertionEveryChildState("-distinct(id)", false);
runAssertionEveryChildState("-distinct(id, 10 seconds)", true);
runAssertionEveryChildState("-distinct(id, 10 seconds)", false);
}
private void runAssertionEveryChildState(String everySuffix, boolean matchDiscard) {
String[] fields = "a.id,b.id,c.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + " [" +
"every a=A -> every" + everySuffix + " (b=B -> c=C(pc=a.pa))]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionEveryBeginState(String distinct) {
String[] fields = "a.id,b.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " + TargetEnum.DISCARD_ONLY.getText() + "[" +
"every a=A -> every" + distinct + " b=B]").addListener(listener);
sendAEvent("A1");
sendBEvent("B1");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1"});
sendBEvent("B2");
assertFalse(listener.isInvoked());
sendAEvent("A2");
sendBEvent("B3");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B3"});
sendBEvent("B4");
assertFalse(listener.isInvoked());
epService.getEPAdministrator().destroyAllStatements();
}
private void sendTime(long msec) {
epService.getEPRuntime().sendEvent(new CurrentTimeEvent(msec));
}
private void sendAEvent(String id) {
sendAEvent(id, null, null);
}
private void sendAEvent(String id, String pa) {
sendAEvent(id, pa, null);
}
private void sendDEvent(String id) {
epService.getEPRuntime().sendEvent(new DEvent(id));
}
private void sendAEvent(String id, int mysec) {
sendAEvent(id, null, mysec);
}
private void sendAEvent(String id, String pa, Integer mysec) {
epService.getEPRuntime().sendEvent(new AEvent(id, pa, mysec));
}
private void sendBEvent(String id) {
sendBEvent(id, null);
}
private void sendBEvent(String id, String pb) {
epService.getEPRuntime().sendEvent(new BEvent(id, pb));
}
private void sendCEvent(String id, String pc) {
epService.getEPRuntime().sendEvent(new CEvent(id, pc));
}
private void runFollowedByOp(String pattern, boolean matchDiscard)
{
String[] fields = "a1.id,a2.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern "
+ (matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + "[" + pattern + "]").addListener(listener);
sendAEvent("E1");
sendAEvent("E2");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"E1", "E2"});
sendAEvent("E3");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"E2", "E3"});
}
sendAEvent("E4");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"E3", "E4"});
sendAEvent("E5");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"E4", "E5"});
}
sendAEvent("E6");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[] {"E5", "E6"});
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionTargetNextMatch(boolean testSoda, TargetEnum target) {
String[] fields = "a.id,b.id,c.id".split(",");
String epl = "select * from pattern " + target.getText() + "[every a=A -> b=B -> c=C(pc=a.pa)]";
if (testSoda) {
EPStatementObjectModel model = epService.getEPAdministrator().compileEPL(epl);
assertEquals(epl, model.toEPL());
epService.getEPAdministrator().create(model).addListener(listener);
}
else {
epService.getEPAdministrator().createEPL(epl).addListener(listener);
}
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (target == TargetEnum.SUPPRESS_ONLY || target == TargetEnum.NONE) {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
else {
assertFalse(listener.isInvoked());
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionMatchUntilBoundOp(boolean matchDiscard) {
String[] fields = "a.id,b[0].id,b[1].id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + "[" +
"every a=A -> [2] b=B(pb in (a.pa, '-'))]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1", "-"); // applies to both matches
sendBEvent("B2", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "B2"});
sendBEvent("B3", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "B3"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionMatchUntilWChildMatcher(boolean matchDiscard) {
String[] fields = "a.id,b[0].id,c[0].id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + " [" +
"every a=A -> [1] (b=B -> c=C(pc=a.pa))]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionMatchUntilRangeOpWTime() {
String[] fields = "a1.id,aarr[0].id".split(",");
sendTime(0);
epService.getEPAdministrator().createEPL("select * from pattern " + TargetEnum.DISCARD_ONLY.getText() + "[" +
"every a1=A -> ([:100] aarr=A until (timer:interval(10 sec) and not b=B))]").addListener(listener);
sendAEvent("A1");
sendTime(1000);
sendAEvent("A2");
sendTime(10000);
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "A2"});
sendTime(11000);
assertFalse(listener.isInvoked());
epService.getEPAdministrator().destroyAllStatements();
}
private void runAssertionTargetCurrentMatch(boolean testSoda, TargetEnum target) {
SupportUpdateListener listener = new SupportUpdateListener();
String[] fields = "a1.id,aarr[0].id,b.id".split(",");
String epl = "select * from pattern " + target.getText() + "[every a1=A -> [:10] aarr=A until b=B]";
if (testSoda) {
EPStatementObjectModel model = epService.getEPAdministrator().compileEPL(epl);
assertEquals(epl, model.toEPL());
epService.getEPAdministrator().create(model).addListener(listener);
}
else {
epService.getEPAdministrator().createEPL(epl).addListener(listener);
}
sendAEvent("A1");
sendAEvent("A2");
sendBEvent("B1");
if (target == TargetEnum.SUPPRESS_ONLY || target == TargetEnum.DISCARD_AND_SUPPRESS) {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "A2", "B1"});
}
else {
EPAssertionUtil.assertPropsPerRowAnyOrder(listener.getAndResetLastNewData(), fields,
new Object[][]{{"A1", "A2", "B1"}, {"A2", null, "B1"}});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAndWAndState(boolean matchDiscard) {
String[] fields = "a.id,b.id,c.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + " [" +
"every a=A -> b=B and c=C(pc=a.pa)]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runAndWChild(boolean matchDiscard) {
String[] fields = "a.id,b.id,c.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + " [" +
"every a=A -> D and (b=B -> c=C(pc=a.pa))]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendDEvent("D1");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runGuardOpBeginState(boolean matchDiscard) {
String[] fields = "a.id,b.id,c.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + "[" +
"every a=A -> b=B -> c=C(pc=a.pa) where timer:within(1)]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void runGuardOpChildState(boolean matchDiscard) {
String[] fields = "a.id,b.id,c.id".split(",");
epService.getEPAdministrator().createEPL("select * from pattern " +
(matchDiscard ? TargetEnum.DISCARD_ONLY.getText() : "") + " [" +
"every a=A -> (b=B -> c=C(pc=a.pa)) where timer:within(1)]").addListener(listener);
sendAEvent("A1", "x");
sendAEvent("A2", "y");
sendBEvent("B1");
sendCEvent("C1", "y");
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A2", "B1", "C1"});
sendCEvent("C2", "x");
if (matchDiscard) {
assertFalse(listener.isInvoked());
}
else {
EPAssertionUtil.assertProps(listener.assertOneGetNewAndReset(), fields, new Object[]{"A1", "B1", "C2"});
}
epService.getEPAdministrator().destroyAllStatements();
}
private void tryInvalid(String epl, String message) {
try {
epService.getEPAdministrator().createEPL(epl);
fail();
}
catch(EPStatementException ex) {
assertEquals(message, ex.getMessage());
}
try {
epService.getEPAdministrator().create(epService.getEPAdministrator().compileEPL(epl));
fail();
}
catch(EPStatementException ex) {
assertEquals(message, ex.getMessage());
}
}
private static class AEvent implements Serializable {
private final String id;
private final String pa;
private final Integer mysec;
private AEvent(String id, String pa, Integer mysec) {
this.id = id;
this.pa = pa;
this.mysec = mysec;
}
public String getId() {
return id;
}
public String getPa() {
return pa;
}
public Integer getMysec() {
return mysec;
}
}
private static class BEvent implements Serializable {
private final String id;
private final String pb;
private BEvent(String id, String pb) {
this.id = id;
this.pb = pb;
}
public String getId() {
return id;
}
public String getPb() {
return pb;
}
}
private static class CEvent implements Serializable {
private final String id;
private final String pc;
private CEvent(String id, String pc) {
this.id = id;
this.pc = pc;
}
public String getId() {
return id;
}
public String getPc() {
return pc;
}
}
private static class DEvent implements Serializable {
private final String id;
private DEvent(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
private enum TargetEnum {
DISCARD_ONLY("@DiscardPartialsOnMatch "),
DISCARD_AND_SUPPRESS("@DiscardPartialsOnMatch @SuppressOverlappingMatches "),
SUPPRESS_ONLY("@SuppressOverlappingMatches "),
NONE("");
private String text;
private TargetEnum(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
}