/*
* *************************************************************************************
* 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.client.scopetest;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.UpdateListener;
import com.espertech.esper.collection.UniformPair;
import java.util.LinkedList;
import java.util.List;
/**
* Update listener that retains the events it receives for use in assertions.
*/
public class SupportUpdateListener implements UpdateListener
{
private final List<EventBean[]> newDataList;
private final List<EventBean[]> oldDataList;
private EventBean[] lastNewData;
private EventBean[] lastOldData;
private boolean isInvoked;
/**
* Ctor.
*/
public SupportUpdateListener()
{
newDataList = new LinkedList<EventBean[]>();
oldDataList = new LinkedList<EventBean[]>();
}
/**
* Wait for the listener invocation for up to the given number of milliseconds.
* @param msecWait to wait
* @throws RuntimeException when no results were received
*/
public void waitForInvocation(long msecWait) {
long startTime = System.currentTimeMillis();
while(true) {
if ((System.currentTimeMillis() - startTime) > msecWait) {
throw new RuntimeException("No result received");
}
if (isInvoked()) {
return;
}
try {
Thread.sleep(50);
}
catch (InterruptedException e) {
return;
}
}
}
/**
* Wait for the listener invocation for up to the given number of milliseconds.
* @param msecWait to wait
* @param numberOfNewEvents in any number of separate invocations required before returning
* @throws RuntimeException when no results or insufficient number of events were received
*/
public void waitForInvocation(long msecWait, int numberOfNewEvents) {
long startTime = System.currentTimeMillis();
while(true) {
if ((System.currentTimeMillis() - startTime) > msecWait) {
throw new RuntimeException("No events or less then the number of expected events received, expected " + numberOfNewEvents + " received " + getNewDataListFlattened().length);
}
EventBean[] events = getNewDataListFlattened();
if (events.length >= numberOfNewEvents) {
return;
}
try {
Thread.sleep(50);
}
catch (InterruptedException e) {
return;
}
}
}
public synchronized void update(EventBean[] newData, EventBean[] oldData)
{
this.oldDataList.add(oldData);
this.newDataList.add(newData);
this.lastNewData = newData;
this.lastOldData = oldData;
isInvoked = true;
}
/**
* Reset listener, clearing all associated state.
*/
public synchronized void reset()
{
this.oldDataList.clear();
this.newDataList.clear();
this.lastNewData = null;
this.lastOldData = null;
isInvoked = false;
}
/**
* Returns the last array of events (insert stream) that were received.
* @return insert stream events or null if either a null value was received or when no events have been received since the last reset
*/
public EventBean[] getLastNewData()
{
return lastNewData;
}
/**
* Returns the last array of remove-stream events that were received.
* @return remove stream events or null if either a null value was received or when no events have been received since the last reset
*/
public EventBean[] getLastOldData()
{
return lastOldData;
}
/**
* Returns the last array of events (insert stream) that were received and resets the listener.
* @return insert stream events or null if either a null value was received or when no events have been received since the last reset
*/
public synchronized EventBean[] getAndResetLastNewData()
{
EventBean[] lastNew = lastNewData;
reset();
return lastNew;
}
/**
* Returns the last array of events (insert stream) that were received and resets the listener.
* @return insert stream events or null if either a null value was received or when no events have been received since the last reset
*/
public synchronized EventBean[] getAndResetLastOldData()
{
EventBean[] lastOld = lastOldData;
reset();
return lastOld;
}
/**
* Asserts that exactly one insert stream event was received and no remove stream events, resets the listener clearing all state and returns the received event.
* @return single insert-stream event
*/
public synchronized EventBean assertOneGetNewAndReset()
{
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, newDataList.size());
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, oldDataList.size());
if (lastNewData == null) {
ScopeTestHelper.fail("No new-data events received");
}
ScopeTestHelper.assertEquals("Mismatch in the number of new-data events", 1, lastNewData.length);
ScopeTestHelper.assertNull("No old-data events are expected but some were received", lastOldData);
EventBean lastNew = lastNewData[0];
reset();
return lastNew;
}
/**
* Asserts that exactly one remove stream event was received and no insert stream events, resets the listener clearing all state and returns the received event.
* @return single remove-stream event
*/
public synchronized EventBean assertOneGetOldAndReset()
{
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, newDataList.size());
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, oldDataList.size());
if (lastOldData == null) {
ScopeTestHelper.fail("No old-data events received");
}
ScopeTestHelper.assertEquals("Mismatch in the number of old-data events", 1, lastOldData.length);
ScopeTestHelper.assertNull("Expected no new-data events", lastNewData);
EventBean lastNew = lastOldData[0];
reset();
return lastNew;
}
/**
* Asserts that exactly one insert stream event and exactly one remove stream event was received, resets the listener clearing all state and returns the received events as a pair.
* @return pair of insert-stream and remove-stream events
*/
public synchronized UniformPair<EventBean> assertPairGetIRAndReset()
{
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, newDataList.size());
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, oldDataList.size());
if (lastNewData == null) {
ScopeTestHelper.fail("No new-data events received");
}
if (lastOldData == null) {
ScopeTestHelper.fail("No old-data events received");
}
ScopeTestHelper.assertEquals("Mismatch in the number of new-data events", 1, lastNewData.length);
ScopeTestHelper.assertEquals("Mismatch in the number of old-data events", 1, lastOldData.length);
EventBean lastNew = lastNewData[0];
EventBean lastOld = lastOldData[0];
reset();
return new UniformPair<EventBean>(lastNew, lastOld);
}
/**
* Asserts that exactly one insert stream event was received not checking remove stream data, and returns the received event.
* @return single insert-stream event
*/
public synchronized EventBean assertOneGetNew()
{
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, newDataList.size());
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, oldDataList.size());
if (lastNewData == null) {
ScopeTestHelper.fail("No new-data events received");
}
ScopeTestHelper.assertEquals("Mismatch in the number of new-data events", 1, lastNewData.length);
return lastNewData[0];
}
/**
* Asserts that exactly one remove stream event was received not checking insert stream data, and returns the received event.
* @return single remove-stream event
*/
public synchronized EventBean assertOneGetOld()
{
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, newDataList.size());
ScopeTestHelper.assertEquals("Mismatch in the number of invocations", 1, oldDataList.size());
if (lastOldData == null) {
ScopeTestHelper.fail("No old-data events received");
}
ScopeTestHelper.assertEquals("Mismatch in the number of old-data events", 1, lastOldData.length);
return lastOldData[0];
}
/**
* Get a list of all insert-stream event arrays received.
* @return list of event arrays
*/
public List<EventBean[]> getNewDataList()
{
return newDataList;
}
/**
* Get a list of all remove-stream event arrays received.
* @return list of event arrays
*/
public List<EventBean[]> getOldDataList()
{
return oldDataList;
}
/**
* Returns true if the listener was invoked at least once.
* @return invoked flag
*/
public boolean isInvoked()
{
return isInvoked;
}
/**
* Returns true if the listener was invoked at least once and clears the invocation flag.
* @return invoked flag
*/
public synchronized boolean getAndClearIsInvoked()
{
boolean invoked = isInvoked;
isInvoked = false;
return invoked;
}
/**
* Set an array of events as the last insert-stream events received.
* @param lastNewData to store
*/
public void setLastNewData(EventBean[] lastNewData)
{
this.lastNewData = lastNewData;
}
/**
* Set an array of events as the last remove-stream events received.
* @param lastOldData to store
*/
public void setLastOldData(EventBean[] lastOldData)
{
this.lastOldData = lastOldData;
}
/**
* Returns an event array that represents all insert-stream events received so far.
* @return event array
*/
public synchronized EventBean[] getNewDataListFlattened()
{
return flatten(newDataList);
}
/**
* Returns an event array that represents all remove-stream events received so far.
* @return event array
*/
public synchronized EventBean[] getOldDataListFlattened()
{
return flatten(oldDataList);
}
private EventBean[] flatten(List<EventBean[]> list)
{
int count = 0;
for (EventBean[] events : list)
{
if (events != null)
{
count += events.length;
}
}
EventBean[] array = new EventBean[count];
count = 0;
for (EventBean[] events : list)
{
if (events != null)
{
for (int i = 0; i < events.length; i++)
{
array[count++] = events[i];
}
}
}
return array;
}
/**
* Returns a pair of insert and remove stream event arrays considering the last invocation only,
* asserting that only a single invocation occured, and resetting the listener.
* @return pair of event arrays, the first in the pair is the insert stream data, the second in the pair is the remove stream data
*/
public synchronized UniformPair<EventBean[]> assertInvokedAndReset() {
ScopeTestHelper.assertTrue("Listener invocation not received but expected", isInvoked);
ScopeTestHelper.assertEquals("Received more then one invocation", 1, getNewDataList().size());
ScopeTestHelper.assertEquals("Received more then one invocation", 1, getOldDataList().size());
EventBean[] newEvents = getLastNewData();
EventBean[] oldEvents = getLastOldData();
reset();
return new UniformPair<EventBean[]>(newEvents, oldEvents);
}
/**
* Returns a pair of insert and remove stream event arrays considering the all invocations.
* @return pair of event arrays, the first in the pair is the insert stream data, the second in the pair is the remove stream data
*/
public synchronized UniformPair<EventBean[]> getDataListsFlattened()
{
return new UniformPair<EventBean[]>(flatten(newDataList), flatten(oldDataList));
}
/**
* Returns a pair of insert and remove stream event arrays considering the all invocations, and resets the listener.
* @return pair of event arrays, the first in the pair is the insert stream data, the second in the pair is the remove stream data
*/
public synchronized UniformPair<EventBean[]> getAndResetDataListsFlattened()
{
UniformPair pair = getDataListsFlattened();
reset();
return pair;
}
}