/* * Copyright (C) 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.errai.cdi.event.client.test; import java.lang.annotation.Annotation; import java.util.Arrays; import org.jboss.errai.bus.client.ErraiBus; import org.jboss.errai.bus.client.api.BusLifecycleAdapter; import org.jboss.errai.bus.client.api.BusLifecycleEvent; import org.jboss.errai.bus.client.api.ClientMessageBus; import org.jboss.errai.bus.client.api.base.MessageBuilder; import org.jboss.errai.cdi.event.client.DependentEventObserverTestModule; import org.jboss.errai.cdi.event.client.EventObserverTestModule; import org.jboss.errai.cdi.event.client.EventProducerTestModule; import org.jboss.errai.cdi.event.client.NotifierModule; import org.jboss.errai.cdi.event.client.OnDemandEventObserver; import org.jboss.errai.cdi.event.client.PrimitiveEventTestModule; import org.jboss.errai.cdi.event.client.shared.Create; import org.jboss.errai.cdi.event.client.shared.Delete; import org.jboss.errai.cdi.event.client.shared.NotifierStartEvent; import org.jboss.errai.cdi.event.client.shared.Update; import org.jboss.errai.enterprise.client.cdi.api.CDI; import org.jboss.errai.ioc.client.IOCUtil; import org.jboss.errai.ioc.client.container.IOC; import com.google.gwt.user.client.Timer; /** * Tests CDI event observers. * * @author Christian Sadilek <csadilek@redhat.com> */ public class EventObserverIntegrationTest extends AbstractEventIntegrationTest { @Override public String getModuleName() { return "org.jboss.errai.cdi.event.EventObserverTestModule"; } @Override protected void gwtSetUp() throws Exception { EventProducerTestModule.clearReceivedEventsOnServer(); super.gwtSetUp(); } public void testBusReadyEventObserver() { delayTestFinish(60000); CDI.addPostInitTask(new Runnable() { @Override public void run() { final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); assertEquals("Wrong number of BusReadyEvents received:", 1, module.getBusReadyEventsReceived()); finishTest(); } }); } public void testEventObservers() { final Runnable verifier = new Runnable() { @Override public void run() { final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); // assert that client received all events EventObserverIntegrationTest.this.verifyQualifiedEvents(module.getReceivedQualifiedEvents(), true); EventObserverIntegrationTest.this.verifySuperTypeEvents(module.getReceivedSuperTypeEvents()); finishTest(); } }; CDI.addPostInitTask(new Runnable() { @Override public void run() { final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); assertNotNull(module.getStartEvent()); module.setResultVerifier(verifier); module.start(); } }); // only used for the case the {@see FinishEvent} was not received verifyInBackupTimer(verifier, 120000); delayTestFinish(240000); } public void testOnDemandEventObservers() { assertEquals("An instance of the observer already exists! This test is now pointless!", 0, OnDemandEventObserver.instanceCount); final Runnable secondVerifier = new Runnable() { @Override public void run() { final OnDemandEventObserver observer = IOC.getBeanManager().lookupBean(OnDemandEventObserver.class).getInstance(); assertEquals(1, observer.getEventLog().size()); finishTest(); } }; final Runnable firstVerifier = new Runnable() { @Override public void run() { // now creating this observer for the first time ever final OnDemandEventObserver observer = IOC.getBeanManager().lookupBean(OnDemandEventObserver.class).getInstance(); assertEquals(0, observer.getEventLog().size()); final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); module.setResultVerifier(secondVerifier); EventProducerTestModule.clearReceivedEventsOnServer(); module.start(); } }; CDI.addPostInitTask(new Runnable() { @Override public void run() { final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); assertNotNull(module.getStartEvent()); module.setResultVerifier(firstVerifier); module.start(); } }); verifyInBackupTimer(firstVerifier, 120000); delayTestFinish(240000); } // regression test for ERRAI-592 public void testObserversStillWorkAfterSessionRenegotiation() { /* Unfortunately, this test is quite intricate. Here's the outline: * - set up event observers (the server will associate our QueueSession with those observers) * - kill the QueueSession * - ask the bus to reconnect (gives us a new QueueSession with a different ID) * - test that the pre-existing CDI observers still receive events from the server */ final Runnable verifier = new Runnable() { @Override public void run() { System.out.println("Verifier starting"); final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); // assert that client received all events EventObserverIntegrationTest.this.verifyQualifiedEvents(module.getReceivedQualifiedEvents(), true); EventObserverIntegrationTest.this.verifySuperTypeEvents(module.getReceivedSuperTypeEvents()); finishTest(); } }; CDI.addPostInitTask(new Runnable() { @Override public void run() { final EventObserverTestModule module = IOC.getBeanManager().lookupBean(EventObserverTestModule.class).getInstance(); assertNotNull(module.getStartEvent()); module.setResultVerifier(verifier); // unlike the other test cases, not starting the test yet! final ClientMessageBus bus = (ClientMessageBus) ErraiBus.get(); MessageBuilder.createMessage("queueSessionInvalidationService").done().sendNowWith(bus); new Timer() { @Override public void run() { System.out.println("Stopping bus..."); bus.stop(false); bus.addLifecycleListener(new BusLifecycleAdapter() { @Override public void busOnline(final BusLifecycleEvent e) { System.out.println("Bus is back online. Starting event test module."); module.start(); } }); } }.schedule(1000); new Timer() { @Override public void run() { System.out.println("Restarting bus..."); bus.init(); } }.schedule(4000); } }); verifyInBackupTimer(verifier, 120000); delayTestFinish(240000); } public void testDestroyBeanWithEventObservers() { final DependentEventObserverTestModule module = IOC.getBeanManager().lookupBean(DependentEventObserverTestModule.class).getInstance(); IOC.getBeanManager().destroyBean(module); assertTrue("Bean wasn't destroyed", module.isDestroyed()); } // Regression test for ERRAI-646 public void testDestroyBeanWithEventObserversDoesNotUnsubscribeOtherObservers() { CDI.addPostInitTask(new Runnable() { @Override public void run() { final DependentEventObserverTestModule module = IOC.getBeanManager().lookupBean(DependentEventObserverTestModule.class).getInstance(); IOC.getBeanManager().destroyBean(module); } }); new Timer() { @Override public void run() { testEventObservers(); } }.schedule(30000); delayTestFinish(240000); } public void testObserverOfPrimitiveEvent() throws Exception { final PrimitiveEventTestModule module = IOCUtil.getInstance(PrimitiveEventTestModule.class); module.boolEvent.fire(false); module.doubleEvent.fire(1.0); module.floatEvent.fire(2.0f); module.intEvent.fire(3); module.longEvent.fire(4L); module.shortEvent.fire((short) 5); module.byteEvent.fire((byte) 6); module.charEvent.fire((char) 7); assertEquals(Arrays .asList( false, 1.0, 2.0f, 3, 4L, (short) 5, (byte) 6, (char) 7 ), module.observed); } public void testEventWithEmptyCollectionOfSubTypeRetainsQualifiers() throws Exception { final long start = System.currentTimeMillis(); final int timeLimit = 20000; delayTestFinish(timeLimit); CDI.addPostInitTask(() -> { final Create create = new Create() { @Override public Class<? extends Annotation> annotationType() { return Create.class; } }; final Update update = new Update() { @Override public Class<? extends Annotation> annotationType() { return Update.class; } }; final Delete delete = new Delete() { @Override public Class<? extends Annotation> annotationType() { return Delete.class; } }; final NotifierModule module = IOCUtil.getInstance(NotifierModule.class); module.event.select(create).fire(new NotifierStartEvent()); module.event.select(update).fire(new NotifierStartEvent()); module.event.select(delete).fire(new NotifierStartEvent()); final Runnable test = () -> { assertTrue(module.observed.containsKey(Create.class)); assertEquals(1, module.observed.get(Create.class).size()); assertTrue(module.observed.get(Create.class).get(0).getEmpty().isEmpty()); assertTrue(module.observed.containsKey(Update.class)); assertEquals(1, module.observed.get(Update.class).size()); assertTrue(module.observed.get(Update.class).get(0).getEmpty().isEmpty()); assertTrue(module.observed.containsKey(Delete.class)); assertEquals(1, module.observed.get(Delete.class).size()); assertTrue(module.observed.get(Delete.class).get(0).getEmpty().isEmpty()); finishTest(); }; final Timer timer = new Timer() { @Override public void run() { try { test.run(); } catch (final AssertionError ae) { if (timeLimit - (System.currentTimeMillis() - start) > 1000) { schedule(500); } else { throw ae; } } } }; timer.schedule(500); }); } }