package com.espertech.esper.regression.multithread;/* *************************************************************************************** * 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. * *************************************************************************************** */ import com.espertech.esper.client.*; import com.espertech.esper.supportregression.client.SupportConfigFactory; import com.espertech.esper.supportregression.util.SupportMTUpdateListener; import junit.framework.TestCase; import java.util.List; import java.util.concurrent.atomic.AtomicLong; public class TestMTStmtNamedWindowUniqueTwoWJoinConsumer extends TestCase { public void testUniqueNamedWindowDispatch() throws Exception { runAssertion(true, null, null); runAssertion(false, true, ConfigurationEngineDefaults.Threading.Locking.SPIN); runAssertion(false, true, ConfigurationEngineDefaults.Threading.Locking.SUSPEND); runAssertion(false, false, null); } private void runAssertion(boolean useDefault, Boolean preserve, ConfigurationEngineDefaults.Threading.Locking locking) throws Exception { Configuration config = SupportConfigFactory.getConfiguration(); if (!useDefault) { config.getEngineDefaults().getThreading().setNamedWindowConsumerDispatchPreserveOrder(preserve); config.getEngineDefaults().getThreading().setNamedWindowConsumerDispatchLocking(locking); } final EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider(config); epService.initialize(); epService.getEPAdministrator().getConfiguration().addEventType(EventOne.class); epService.getEPAdministrator().getConfiguration().addEventType(EventTwo.class); String epl = "create window EventOneWindow#unique(key) as EventOne;\n" + "insert into EventOneWindow select * from EventOne;\n" + "create window EventTwoWindow#unique(key) as EventTwo;\n" + "insert into EventTwoWindow select * from EventTwo;\n" + "@name('out') select * from EventOneWindow as e1, EventTwoWindow as e2 where e1.key = e2.key"; epService.getEPAdministrator().getDeploymentAdmin().parseDeploy(epl); SupportMTUpdateListener listener = new SupportMTUpdateListener(); epService.getEPAdministrator().getStatement("out").addListener(listener); Runnable runnableOne = new Runnable() { public void run() { for (int i = 0; i < 33; i++) { EventOne eventOne = new EventOne("TEST"); epService.getEPRuntime().sendEvent(eventOne); EventTwo eventTwo = new EventTwo("TEST"); epService.getEPRuntime().sendEvent(eventTwo); } } }; Runnable runnableTwo = new Runnable() { public void run() { for (int i = 0; i < 33; i++) { EventTwo eventTwo = new EventTwo("TEST"); epService.getEPRuntime().sendEvent(eventTwo); EventOne eventOne = new EventOne("TEST"); epService.getEPRuntime().sendEvent(eventOne); } } }; Runnable runnableThree = new Runnable() { public void run() { for (int i = 0; i < 34; i++) { EventTwo eventTwo = new EventTwo("TEST"); epService.getEPRuntime().sendEvent(eventTwo); EventOne eventOne = new EventOne("TEST"); epService.getEPRuntime().sendEvent(eventOne); } } }; Thread t1 = new Thread(runnableOne); Thread t2 = new Thread(runnableTwo); Thread t3 = new Thread(runnableThree); t1.start(); t2.start(); t3.start(); t1.join(); t2.join(); t3.join(); List<EventBean[]> delivered = listener.getNewDataList(); // count deliveries of multiple rows int countMultiDeliveries = 0; for (EventBean[] events : delivered) { countMultiDeliveries += (events.length > 1 ? 1 : 0); } // count deliveries where instance doesn't monotonically increase from previous row for one column int countNotMonotone = 0; Long previousIdE1 = null; Long previousIdE2 = null; for (EventBean[] events : delivered) { long idE1 = (Long) events[0].get("e1.instance"); long idE2 = (Long) events[0].get("e2.instance"); // comment-in when needed: System.out.println("Received " + idE1 + " " + idE2); if (previousIdE1 != null) { boolean incorrect = idE1 != previousIdE1 && idE2 != previousIdE2; if (!incorrect) { incorrect = (idE1 == previousIdE1 && idE2 != (previousIdE2 + 1) || (idE2 == previousIdE2 && idE1 != (previousIdE1 + 1))); } if (incorrect) { // comment-in when needed: System.out.println("Non-Monotone increase (this is still correct but noteworthy)"); countNotMonotone++; } } previousIdE1 = idE1; previousIdE2 = idE2; } if (useDefault || preserve) { assertEquals("multiple row deliveries: " + countMultiDeliveries, 0, countMultiDeliveries); // the number of non-monotone delivers should be small but not zero // this is because when the event get generated and when the event actually gets processed may not be in the same order assertTrue("count not monotone: " + countNotMonotone, countNotMonotone < 50); assertTrue(delivered.size() >= 197); // its possible to not have 199 since there may not be events on one side of the join } else { assertTrue("multiple row deliveries: " + countMultiDeliveries, countMultiDeliveries > 0); assertTrue("count not monotone: " + countNotMonotone, countNotMonotone > 5); } } public static class EventOne { private static final AtomicLong ATOMIC_LONG = new AtomicLong(1); private final long instance; private final String key; private EventOne(String key) { instance = ATOMIC_LONG.getAndIncrement(); this.key = key; } public String getKey() { return key; } public long getInstance() { return instance; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof EventOne)) return false; EventOne eventOne = (EventOne) o; return key.equals(eventOne.key); } public int hashCode() { return key.hashCode(); } } public static class EventTwo { private static final AtomicLong ATOMIC_LONG = new AtomicLong(1); private final long instance; private final String key; public EventTwo(String key) { instance = ATOMIC_LONG.getAndIncrement(); this.key = key; } public long getInstance() { return instance; } public String getKey() { return key; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof EventTwo)) return false; EventTwo eventTwo = (EventTwo) o; return key.equals(eventTwo.key); } public int hashCode() { return key.hashCode(); } } }