/*
***************************************************************************************
* 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.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.supportregression.bean.SupportBean;
import com.espertech.esper.supportregression.bean.SupportBeanComplexProps;
import com.espertech.esper.supportregression.bean.SupportBean_N;
import com.espertech.esper.supportregression.client.SupportConfigFactory;
import com.espertech.esper.supportregression.util.SupportMessageAssertUtil;
import junit.framework.TestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestInvalidPattern extends TestCase
{
private EPServiceProvider epService;
private final String EVENT_NUM = SupportBean_N.class.getName();
private final String EVENT_COMPLEX = SupportBeanComplexProps.class.getName();
private final String EVENT_ALLTYPES = SupportBean.class.getName();
public void setUp()
{
epService = EPServiceProviderManager.getDefaultProvider(SupportConfigFactory.getConfiguration());
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.startTest(epService, this.getClass(), getName());}
}
public void tearDown() {
if (InstrumentationHelper.ENABLED) { InstrumentationHelper.endTest();}
}
public void testInvalid()
{
String exceptionText = getSyntaxExceptionPattern(EVENT_NUM + "(doublePrimitive='ss'");
assertEquals("Incorrect syntax near end-of-input expecting a closing parenthesis ')' but found end-of-input at line 1 column 77, please check the filter specification within the pattern expression [" + SupportBean_N.class.getName() + "(doublePrimitive='ss']", exceptionText);
epService.getEPAdministrator().getConfiguration().addEventType("SupportBean", SupportBean.class);
epService.getEPAdministrator().createEPL("select * from pattern[(not a=SupportBean) -> SupportBean(theString=a.theString)]");
// test invalid subselect
epService.getEPAdministrator().createEPL("create window WaitWindow#keepall as (waitTime int)");
epService.getEPAdministrator().createEPL("insert into WaitWindow select intPrimitive as waitTime from SupportBean");
epService.getEPRuntime().sendEvent(new SupportBean("E1", 100));
try {
epService.getEPAdministrator().createPattern("timer:interval((select waitTime from WaitWindow))");
fail();
}
catch (EPStatementException ex) {
assertEquals("Subselects are not allowed within pattern observer parameters, please consider using a variable instead [timer:interval((select waitTime from WaitWindow))]",
ex.getMessage());
}
}
public void testStatementException() throws Exception
{
EPStatementException exception;
exception = getStatementExceptionPattern("timer:at(2,3,4,4,4)");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:at(2,3,4,4,4)': Error computing crontab schedule specification: Invalid combination between days of week and days of month fields for timer:at [");
exception = getStatementExceptionPattern("timer:at(*,*,*,*,*,0,-1)");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:at(*,*,*,*,*,0,-1)': Error computing crontab schedule specification: Invalid timezone parameter '-1' for timer:at, expected a string-type value [");
exception = getStatementExceptionPattern(EVENT_ALLTYPES + " -> timer:within()");
SupportMessageAssertUtil.assertMessage(exception, "Failed to resolve pattern observer 'timer:within()': Pattern guard function 'within' cannot be used as a pattern observer [");
exception = getStatementExceptionPattern(EVENT_ALLTYPES + " where timer:interval(100)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to resolve pattern guard '" + SupportBean.class.getName() + " where timer:interval(100)': Pattern observer function 'interval' cannot be used as a pattern guard [");
exception = getStatementExceptionPattern(EVENT_ALLTYPES + " -> timer:interval()");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:interval()': Timer-interval observer requires a single numeric or time period parameter [");
exception = getStatementExceptionPattern(EVENT_ALLTYPES + " where timer:within()");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern guard '" + SupportBean.class.getName() + " where timer:within()': Timer-within guard requires a single numeric or time period parameter [");
// class not found
exception = getStatementExceptionPattern("dummypkg.dummy()");
SupportMessageAssertUtil.assertMessage(exception, "Failed to resolve event type: Event type or class named 'dummypkg.dummy' was not found [");
// simple property not found
exception = getStatementExceptionPattern(EVENT_NUM + "(dummy=1)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'dummy=1': Property named 'dummy' is not valid in any stream [");
// nested property not found
exception = getStatementExceptionPattern(EVENT_NUM + "(dummy.nested=1)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'dummy.nested=1': Failed to resolve property 'dummy.nested' to a stream or nested property in a stream [");
// property wrong type
exception = getStatementExceptionPattern(EVENT_NUM + "(intPrimitive='s')");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'intPrimitive=\"s\"': Implicit conversion from datatype 'String' to 'Integer' is not allowed [");
// property not a primitive type
exception = getStatementExceptionPattern(EVENT_COMPLEX + "(nested=1)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'nested=1': Implicit conversion from datatype 'Integer' to 'SupportBeanSpecialGetterNested' is not allowed [");
// no tag matches prior use
exception = getStatementExceptionPattern(EVENT_NUM + "(doublePrimitive=x.abc)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'doublePrimitive=x.abc': Failed to resolve property 'x.abc' to a stream or nested property in a stream [");
// range not valid on string
exception = getStatementExceptionPattern(EVENT_ALLTYPES + "(theString in [1:2])");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'theString between 1 and 2': Implicit conversion from datatype 'String' to numeric is not allowed [");
// range does not allow string params
exception = getStatementExceptionPattern(EVENT_ALLTYPES + "(doubleBoxed in ['a':2])");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'doubleBoxed between \"a\" and 2': Implicit conversion from datatype 'String' to numeric is not allowed [");
// invalid observer arg
exception = getStatementExceptionPattern("timer:at(9l)");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:at(9)': Invalid number of parameters for timer:at [timer:at(9l)]");
// invalid guard arg
exception = getStatementExceptionPattern(EVENT_ALLTYPES + " where timer:within('s')");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern guard '" + SupportBean.class.getName() + " where timer:within(\"s\")': Timer-within guard requires a single numeric or time period parameter [");
// use-result property is wrong type
exception = getStatementExceptionPattern("x=" + EVENT_ALLTYPES + " -> " + EVENT_ALLTYPES + "(doublePrimitive=x.boolBoxed)");
SupportMessageAssertUtil.assertMessage(exception, "Failed to validate filter expression 'doublePrimitive=x.boolBoxed': Implicit conversion from datatype 'Boolean' to 'Double' is not allowed [");
// named-parameter for timer:at or timer:interval
exception = getStatementExceptionPattern("timer:interval(interval:10)");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:interval(interval:10)': Timer-interval observer does not allow named parameters [timer:interval(interval:10)]");
exception = getStatementExceptionPattern("timer:at(perhaps:10)");
SupportMessageAssertUtil.assertMessage(exception, "Invalid parameter for pattern observer 'timer:at(perhaps:10)': timer:at does not allow named parameters [timer:at(perhaps:10)]");
}
public void testUseResult()
{
final String EVENT = SupportBean_N.class.getName();
tryValid("na=" + EVENT + " -> nb=" + EVENT + "(doublePrimitive = na.doublePrimitive)");
tryInvalid("xx=" + EVENT + " -> nb=" + EVENT + "(doublePrimitive = na.doublePrimitive)");
tryInvalid("na=" + EVENT + " -> nb=" + EVENT + "(doublePrimitive = xx.doublePrimitive)");
tryInvalid("na=" + EVENT + " -> nb=" + EVENT + "(doublePrimitive = na.xx)");
tryInvalid("xx=" + EVENT + " -> nb=" + EVENT + "(xx = na.doublePrimitive)");
tryInvalid("na=" + EVENT + " -> nb=" + EVENT + "(xx = na.xx)");
tryValid("na=" + EVENT + " -> nb=" + EVENT + "(doublePrimitive = na.doublePrimitive, intBoxed=na.intBoxed)");
tryValid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in (na.doublePrimitive:na.doubleBoxed))");
tryValid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.doublePrimitive:na.doubleBoxed])");
tryValid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.intBoxed:na.intPrimitive])");
tryInvalid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.intBoxed:na.xx])");
tryInvalid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.intBoxed:na.boolBoxed])");
tryInvalid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.xx:na.intPrimitive])");
tryInvalid("na=" + EVENT + "() -> nb=" + EVENT + "(doublePrimitive in [na.boolBoxed:na.intPrimitive])");
}
private void tryInvalid(String eplInvalidPattern)
{
try
{
epService.getEPAdministrator().createPattern(eplInvalidPattern);
fail();
}
catch (EPException ex)
{
// Expected exception
}
}
private String getSyntaxExceptionPattern(String expression)
{
String exceptionText = null;
try
{
epService.getEPAdministrator().createPattern(expression);
fail();
}
catch (EPStatementSyntaxException ex)
{
exceptionText = ex.getMessage();
log.debug(".getSyntaxExceptionPattern pattern=" + expression, ex);
// Expected exception
}
return exceptionText;
}
private EPStatementException getStatementExceptionPattern(String expression) throws Exception
{
return getStatementExceptionPattern(expression, false);
}
private EPStatementException getStatementExceptionPattern(String expression, boolean isLogException) throws Exception
{
try
{
epService.getEPAdministrator().createPattern(expression);
fail();
}
catch (EPStatementSyntaxException es)
{
throw es;
}
catch (EPStatementException ex)
{
// Expected exception
if (isLogException) {
log.debug(".getSyntaxExceptionPattern pattern=" + expression, ex);
}
return ex;
}
throw new IllegalStateException();
}
private void tryValid(String eplInvalidPattern)
{
epService.getEPAdministrator().createPattern(eplInvalidPattern);
}
private final static Logger log = LoggerFactory.getLogger(TestInvalidPattern.class);
}