package ch.uzh.ifi.ddis.ifp.esper.test;
/*
* #%L
* TestNG4Esper
* %%
* Copyright (C) 2013 University of Zurich
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-2.0.html>.
* #L%
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Optional;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import org.w3c.dom.NodeList;
import ch.uzh.ifi.ddis.ifp.esper.EsperStatementBean;
import ch.uzh.ifi.ddis.ifp.esper.EsperStatementBeanFactory;
import com.espertech.esper.client.Configuration;
import com.espertech.esper.client.EPServiceProvider;
import com.espertech.esper.client.EPServiceProviderManager;
import com.espertech.esper.client.EPStatement;
/**
* <p>
* Generic {@link Test} for the Esper complex event processing engine.
* </p>
* <p>
* The test has the following attributes:
* <ul>
* <li>a final reference to the Esper {@link Configuration},</li>
* <li>a final reference to an {@link EPServiceProvider}</li>
* </ul>
* </p>
* <h2>Configuration</h2>
* <p>
* The test expects the following parameters:
* <table border="1">
* <th>Name</th>
* <th>Value</th>
* <th>Required</th>
* <th>Default</th>
* <tr>
* <td>esper-config</td>
* <td>path to an Esper xml configuration file</td>
* <td>no</td>
* <td>empty configuration</td>
* </tr>
* <tr>
* <td>statement-files-list</td>
* <td>Comma separated list of file names, each file containing a single Esper
* statement.</td>
* <td>yes</td>
* <td> </td>
* </tr>
* </table>
* </p>
*
* @author Thomas Scharrenbach
* @version 0.3.1
* @since 0.0.1
*
*/
public abstract class EsperTest {
protected static final Logger _log = LoggerFactory
.getLogger(EsperTest.class);
//
//
//
private final Configuration _configuration = new Configuration();
private EPServiceProvider _epService;
private final List<EsperStatementBean> _esperStatementBeansList = new ArrayList<EsperStatementBean>();
//
//
//
public static final String DEFAULT_ESPER_STATEMENTS_FILE = "esper-statements.xml";
//
//
//
/**
* Executed as the first call of {@link #configure(String)}.
*/
protected abstract void beforeConfigure();
/**
*
* @param esperConfig
*/
@BeforeMethod
@Parameters({ "esper-config" })
public void configure(@Optional("") String esperConfig) {
beforeConfigure();
if (!esperConfig.trim().isEmpty()) {
try {
_log.info(
"Started loading Esper configuration from file {}...",
esperConfig);
_configuration.configure(esperConfig);
_log.info("Finished loading Esper configuration from file {}.",
esperConfig);
} catch (Exception e) {
_log.info("Error loading Esper configuration from file {}!",
esperConfig, e);
assert false;
}
}
afterConfigure();
assert true;
return;
}
/**
* Executed as the last call of {@link #configure(String)}.
*/
protected abstract void afterConfigure();
/**
* Executed as the first call of {@link #initEngine()}.
*/
protected abstract void beforeInitEngine();
/**
* Initializes the service with the default provider or optional with a
* service provider URI if the parameter is not null.
*/
@BeforeMethod(dependsOnMethods = { "configure" })
@Parameters(value = { "serviceProviderUri" })
public void initEngine(@Optional() String serviceProviderUri) {
beforeInitEngine();
if (serviceProviderUri == null) {
try {
_epService = EPServiceProviderManager
.getDefaultProvider(_configuration);
} catch (Exception e) {
assert false;
throw new RuntimeException(e);
}
} else {
_epService = EPServiceProviderManager.getProvider(
serviceProviderUri, _configuration);
}
afterInitEngine();
}
/**
* Executed as the last call of {@link #initEngine()}.
*/
protected abstract void afterInitEngine();
/**
* <p>
* Adds the statements from the provided statement files.
* </p>
* <h2>Usage in testng.xml</h2>
* <p>
* You may specify the files containing statements as a string parameter to
* testng. The value of the parameter is a comma-separated list of files
* each of which contains a single Esper statement.
* </p>
*
* <pre>
* <parameter name="statement-files-list"
* value="file1,file2,file3" />
* </pre>
*
* @deprecated use {@link #addStatementsFile(String)} instead.
* @param statementFilesList
* String containing a comma-separated list of filenames, each of
* which contains a single Esper statement.
*/
@BeforeMethod(dependsOnMethods = { "initEngine" })
@Parameters({ "statement-files-list" })
public void addStatements(@Optional String statementFilesList) {
if (statementFilesList == null) {
return;
}
BufferedReader reader = null;
// TODO write parser...
for (String statementFile : statementFilesList.split(",")) {
try {
_log.info("Started reading statement file {}...", statementFile);
reader = new BufferedReader(new FileReader(new File(
statementFile)));
StringBuffer buffer = new StringBuffer();
String line = null;
// read all lines into the buffer.
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
// Add the statement to the Esper engine.
final EPStatement statement = _epService.getEPAdministrator()
.createEPL(buffer.toString().trim());
// Add a subscriber to the statement that logs all update
// events to this statement.
statement.setSubscriber(new LogSubscriber(statement));
_log.info("Finished reading statement file {}.", statementFile);
} catch (Exception e) {
_log.error("Error reading statement file {}!", statementFile, e);
assert false;
}
// close the reader if possible.
finally {
if (reader != null) {
try {
_log.info("Started closing statement file {}...",
statementFile);
reader.close();
_log.info("Finished closing statement file {}.",
statementFile);
} catch (IOException e) {
_log.error("Error closing statement file {}!",
statementFile, e);
assert false;
}
}
}
}
}
/**
* <p>
* Adds the statements from the provided statement files.
* </p>
* <h2>Usage in testng.xml</h2>
* <p>
* You may specify the files containing statements as a string parameter to
* testng. The value of the parameter is a comma-separated list of files
* each of which contains a single Esper statement.
* </p>
*
* <pre>
* <parameter name="statement-files-list"
* value="file1,file2,file3" />
* </pre>
*
* @param statementsFile
* String containing the reference to an XML file containing the
* statements for the test.
*/
@BeforeMethod(dependsOnMethods = { "initEngine" })
@Parameters({ "statements-file", "statement-beans-factory" })
public void addStatementsFile(
@Optional String statementsFile,
@Optional("ch.uzh.ifi.ddis.ifp.esper.EsperStatementBeanFactory") String statementBeansFactory) {
try {
if (statementsFile == null) {
_log.warn("No Esper statements file provided!");
return;
}
_log.info("Started adding statements from {} ...", statementsFile);
final EsperStatementBeanFactory esperStatementsBeanFactory = (EsperStatementBeanFactory) Class
.forName(statementBeansFactory).newInstance();
final DocumentBuilder builder = DocumentBuilderFactory
.newInstance().newDocumentBuilder();
// Trying to load statements from file or resource.
InputStream xmlStatementsFileStream = null;
{
final File xmlStatementsFileTest = new File(statementsFile);
if (xmlStatementsFileTest.exists()) {
xmlStatementsFileStream = new FileInputStream(
xmlStatementsFileTest);
_log.info("Loading statements from file {}", statementsFile);
} else {
xmlStatementsFileStream = getClass().getResourceAsStream(
statementsFile);
if (xmlStatementsFileStream == null) {
xmlStatementsFileStream = getClass()
.getResourceAsStream("/" + statementsFile);
_log.info("Loading statements from resource {}", "/"
+ statementsFile);
} else {
_log.info("Loading statements from resource {}",
statementsFile);
}
}
}
_log.info("Started parsing statements from {} ...", statementsFile);
final org.w3c.dom.Document document = builder
.parse(xmlStatementsFileStream);
final NodeList statementNodesList = document
.getElementsByTagName("statement");
final int statementNodesListSize = statementNodesList.getLength();
for (int i = 0; i < statementNodesListSize; ++i) {
final org.w3c.dom.Node statementNode = statementNodesList
.item(i);
final EsperStatementBean esperStatementBean = esperStatementsBeanFactory
.createEsperStatementBean(statementNode);
_esperStatementBeansList.add(esperStatementBean);
}
for (EsperStatementBean esperStatementBean : _esperStatementBeansList) {
// Add the statement to the Esper engine.
_log.info(
"Adding statement with name '{}' to Esper engine with URI '{}'",
esperStatementBean.getName(), getEpService().getURI());
final EPStatement statement = esperStatementBean.getName() == null ? _epService
.getEPAdministrator().createEPL(
esperStatementBean.getEsperStatement())
: _epService.getEPAdministrator().createEPL(
esperStatementBean.getEsperStatement(),
esperStatementBean.getName());
// Add a subscriber to the statement that logs all update
// events to this statement.
statement.setSubscriber(new LogSubscriber(statement));
}
_log.info("Finished parsing statements from {} .", statementsFile);
_log.info("Finished adding statements from {} .", statementsFile);
} catch (Exception e) {
_log.error("Error adding statements from {} !", statementsFile);
assert false;
}
}
//
//
//
public Configuration getConfiguration() {
return _configuration;
}
public EPServiceProvider getEpService() {
return _epService;
}
}