/* * JBoss, Home of Professional Open Source * Copyright 2010, Red Hat, Inc., and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.cdi.tck.tests.event.fires; import static org.jboss.cdi.tck.TestGroups.REWRITE; import static org.jboss.cdi.tck.cdi.Sections.BM_FIRE_EVENT; import static org.jboss.cdi.tck.cdi.Sections.EVENT; import static org.jboss.cdi.tck.cdi.Sections.FIRING_EVENTS; import static org.jboss.cdi.tck.cdi.Sections.FIRING_EVENTS_SYNCHRONOUSLY; import static org.jboss.cdi.tck.cdi.Sections.OBSERVER_RESOLUTION; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Event; import javax.enterprise.inject.Any; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.InjectionPoint; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.cdi.tck.AbstractTest; import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; import org.jboss.cdi.tck.tests.extensions.beanManager.broken.event.ContainerLifecycleEvents; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.test.audit.annotations.SpecAssertion; import org.jboss.test.audit.annotations.SpecAssertions; import org.jboss.test.audit.annotations.SpecVersion; import org.testng.annotations.Test; /** * Tests that verify the event firing behavior of the Event interface. * * @author Dan Allen * @author Martin Kouba */ @Test @SpecVersion(spec = "cdi", version = "2.0-PFD") public class FireEventTest extends AbstractTest { @Deployment public static WebArchive createTestArchive() { return new WebArchiveBuilder().withTestClassPackage(FireEventTest.class).withClass(ContainerLifecycleEvents.class).build(); } @SuppressWarnings("serial") @Test @SpecAssertions({ @SpecAssertion(section = BM_FIRE_EVENT, id = "a"), @SpecAssertion(section = BM_FIRE_EVENT, id = "b") }) public void testBeanManagerFireEvent() { Billing billing = getContextualReference(Billing.class); billing.reset(); MiniBar miniBar = new MiniBar(); miniBar.stockNoNotify(); getCurrentManager().fireEvent(miniBar); assertTrue(billing.isActive()); Item chocolate = miniBar.getItemByName("Chocolate"); getCurrentManager().fireEvent(chocolate, new Lifted.LiftedLiteral() { }); assertEquals(billing.getCharge(), 5); } @Test(expectedExceptions = { IllegalArgumentException.class }) @SpecAssertion(section = BM_FIRE_EVENT, id = "c") public void testTypeVariableEventTypeFails() throws Exception { getContextualReference(Bar.class).<Integer> fireWithTypeVariable(); } @SuppressWarnings("serial") @Test(expectedExceptions = { IllegalArgumentException.class }) @SpecAssertion(section = BM_FIRE_EVENT, id = "d") public void testDuplicateBindingsToFireEventFails() throws Exception { getCurrentManager().fireEvent(new Object(), new Lifted.LiftedLiteral("a") { }, new Lifted.LiftedLiteral("b") { }); } /** * This test verifies that the {@link Event} object capable of firing {@link Item} objects can be injected with the {@link * @Any} binding type and that the injected object can be used to fire an event. The functionality is verified by checking * that the corresponding observer gets invoked. */ // Simplify assertions @Test(groups = REWRITE) @SpecAssertion(section = FIRING_EVENTS, id = "a") public void testInjectedAnyEventCanFireEvent() { Billing billing = getContextualReference(Billing.class); billing.reset(); Bean<MiniBar> miniBarBean = getUniqueBean(MiniBar.class); InjectionPoint eventInjection = null; for (InjectionPoint candidate : miniBarBean.getInjectionPoints()) { if (candidate.getMember().getName().equals("miniBarEvent")) { eventInjection = candidate; break; } } assertNotNull(eventInjection); assertEquals(eventInjection.getQualifiers().size(), 1); assertTrue(eventInjection.getQualifiers().contains(Any.Literal.INSTANCE)); CreationalContext<MiniBar> miniBarCc = getCurrentManager().createCreationalContext(miniBarBean); MiniBar miniBar = miniBarBean.create(miniBarCc); miniBar.stock(); assertTrue(billing.isActive()); assertEquals(billing.getMiniBarValue(), 16); } /** * This test verifies that the fire() method of the injected {@link Event} object accepts an event object and that the event * object's type is the same as the the parameterized type on the event field. **/ // Simplify assertions @Test(groups = REWRITE) @SpecAssertions({ @SpecAssertion(section = FIRING_EVENTS_SYNCHRONOUSLY, id = "b"), @SpecAssertion(section = EVENT, id = "cb") }) public void testInjectedEventAcceptsEventObject() throws SecurityException, NoSuchFieldException, NoSuchMethodException { Billing billing = getContextualReference(Billing.class); billing.reset(); Bean<MiniBar> miniBarBean = getUniqueBean(MiniBar.class); CreationalContext<MiniBar> miniBarCc = getCurrentManager().createCreationalContext(miniBarBean); MiniBar miniBar = miniBarBean.create(miniBarCc); Field eventField = miniBar.getClass().getDeclaredField("miniBarEvent"); ParameterizedType eventFieldType = (ParameterizedType) eventField.getGenericType(); assertEquals(eventFieldType.getActualTypeArguments().length, 1); assertEquals(MiniBar.class, eventFieldType.getActualTypeArguments()[0]); assertEquals(Event.class, eventFieldType.getRawType()); Method fireMethod = null; @SuppressWarnings("unchecked") Class<Event<Item>> eventFieldClass = (Class<Event<Item>>) eventFieldType.getRawType(); for (Method method : eventFieldClass.getMethods()) { if (method.getName().equals("fire") && !method.isSynthetic()) { if (fireMethod != null) { fail("Expecting exactly one method on Event named 'fire'"); } fireMethod = method; } } if (fireMethod == null) { fail("Expecting exactly one method on Event named 'fire'"); } assertEquals(fireMethod.getParameterTypes().length, 1); assertEquals(fireMethod.getGenericParameterTypes().length, 1); // make sure the same type used to parameterize the Event class is referenced in the fire() method Type fireMethodArgumentType = fireMethod.getGenericParameterTypes()[0]; @SuppressWarnings("rawtypes") Type eventClassParameterizedType = ((TypeVariable) fireMethod.getGenericParameterTypes()[0]).getGenericDeclaration() .getTypeParameters()[0]; assertEquals(fireMethodArgumentType, eventClassParameterizedType); miniBar.stock(); assertTrue(billing.isActive()); assertEquals(billing.getMiniBarValue(), 16); } /** * This test verifies that the {@link Event} object representing an {@link Item} with the {@link @Lifted} binding type is * properly injected and that this object can be used to fire an event. The functionality is verified by checking that the * cooresponding observer gets invoked. */ @SuppressWarnings("serial") // Simplify assertions @Test(groups = REWRITE) @SpecAssertions({ @SpecAssertion(section = FIRING_EVENTS, id = "c"), @SpecAssertion(section = EVENT, id = "cb") }) public void testInjectedEventCanHaveBindings() { Billing billing = getContextualReference(Billing.class); billing.reset(); Bean<MiniBar> miniBarBean = getUniqueBean(MiniBar.class); InjectionPoint eventInjection = null; for (InjectionPoint candidate : miniBarBean.getInjectionPoints()) { if (candidate.getMember().getName().equals("itemLiftedEvent")) { eventInjection = candidate; break; } } assertNotNull(eventInjection); assertEquals(eventInjection.getQualifiers().size(), 1); assertTrue(eventInjection.getQualifiers().contains(new Lifted.LiftedLiteral() { })); CreationalContext<MiniBar> miniBarCc = getCurrentManager().createCreationalContext(miniBarBean); MiniBar miniBar = miniBarBean.create(miniBarCc); miniBar.stock(); Item chocolate = miniBar.getItemByName("Chocolate"); assertNotNull(chocolate); miniBar.liftItem(chocolate); assertEquals(billing.getCharge(), chocolate.getPrice()); } /** * This test verifies that binding types can be specified dynamically when firing an event using {@link Event#fire()} by * first using the {@link Event#select()} method to retrieve an Event object with associated binding types. */ // Simplify assertions @Test(groups = REWRITE) @SpecAssertion(section = FIRING_EVENTS, id = "d") public void testInjectedEventCanSpecifyBindingsDynamically() { Billing billing = getContextualReference(Billing.class); billing.reset(); Housekeeping housekeeping = getContextualReference(Housekeeping.class); Bean<MiniBar> miniBarBean = getUniqueBean(MiniBar.class); InjectionPoint eventInjection = null; for (InjectionPoint candidate : miniBarBean.getInjectionPoints()) { if (candidate.getMember().getName().equals("itemEvent")) { eventInjection = candidate; break; } } assertNotNull(eventInjection); assertEquals(eventInjection.getQualifiers().size(), 1); assertTrue(eventInjection.getQualifiers().contains(Any.Literal.INSTANCE)); CreationalContext<MiniBar> miniBarCc = getCurrentManager().createCreationalContext(miniBarBean); MiniBar miniBar = miniBarBean.create(miniBarCc); miniBar.stock(); Item water = miniBar.liftItemByName("16 oz Water"); miniBar.restoreItem(water); assertEquals(billing.getCharge(), 1); assertEquals(housekeeping.getItemsTainted().size(), 1); assertTrue(housekeeping.getItemsTainted().contains(water)); } @Test @SpecAssertion(section = EVENT, id = "ca") public void testEventProvidesMethodForFiringEventsWithCombinationOfTypeAndBindings() { DoggiePoints points = getContextualReference(DoggiePoints.class); points.reset(); DogWhisperer master = getContextualReference(DogWhisperer.class); master.issueTamingCommand(); assertEquals(points.getNumTamed(), 1); assertEquals(points.getNumPraiseReceived(), 0); master.givePraise(); assertEquals(points.getNumTamed(), 1); assertEquals(points.getNumPraiseReceived(), 1); } // Simplify assertions @SuppressWarnings("serial") @Test(groups = REWRITE) @SpecAssertion(section = EVENT, id = "eda") public void testEventSelectedFiresAndObserversNotified() { Housekeeping houseKeeping = getContextualReference(Housekeeping.class); houseKeeping.reset(); MiniBar miniBar = getContextualReference(MiniBar.class); Item chocolate = new Item("Chocolate", 5); Item crackers = new Item("Crackers", 2); miniBar.getItemEvent().fire(chocolate); assertEquals(houseKeeping.getItemActivity().size(), 1); assertEquals(houseKeeping.getItemActivity().get(0), chocolate); miniBar.getItemEvent().select(new Lifted.LiftedLiteral() { }).fire(crackers); assertEquals(houseKeeping.getItemActivity().size(), 2); assertEquals(houseKeeping.getItemActivity().get(1), crackers); assertEquals(houseKeeping.getItemsMissing().size(), 1); assertEquals(houseKeeping.getItemsMissing().iterator().next(), crackers); } @Test(expectedExceptions = IllegalArgumentException.class) @SpecAssertions({ @SpecAssertion(section = EVENT, id = "f"), @SpecAssertion(section = OBSERVER_RESOLUTION, id = "j") }) public <T> void testEventFireThrowsExceptionIfEventObjectTypeContainsUnresovableTypeVariable() { MiniBar miniBar = getContextualReference(MiniBar.class); miniBar.itemEvent.fire(new Item_Illegal<T>("12 oz Beer", 6)); } @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) @SpecAssertion(section = EVENT, id = "g") public void testFireContainerLifecycleEvent(ContainerLifecycleEventDispatcher containerLifecycleEvents) { containerLifecycleEvents.fireContainerLifecycleEvents(); } }