/* * 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.resolve.typeWithParameters; import static org.jboss.cdi.tck.cdi.Sections.BM_OBSERVER_METHOD_RESOLUTION; import static org.jboss.cdi.tck.cdi.Sections.OBSERVERS_ASSIGNABILITY; import static org.jboss.cdi.tck.cdi.Sections.OBSERVER_METHODS; import static org.jboss.cdi.tck.tests.event.resolve.typeWithParameters.AbstractObserver.buildActionId; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import javax.enterprise.event.Event; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.ObserverMethod; import javax.inject.Inject; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.Set; 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.util.ActionSequence; 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; @SpecVersion(spec = "cdi", version = "2.0-PFD") public class CheckTypeParametersWhenResolvingObserversTest extends AbstractTest { @Deployment public static WebArchive createTestArchive() { return new WebArchiveBuilder().withTestClassPackage(CheckTypeParametersWhenResolvingObserversTest.class).build(); } @Inject Event<Box<Integer, String, Random>> event; @Test @SpecAssertions({ @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "b"), @SpecAssertion(section = BM_OBSERVER_METHOD_RESOLUTION, id = "a") }) public void testResolvingChecksTypeParameters() { verifyObserver(new StringList(), 1, StringListObserver.class); verifyObserver(new IntegerList(), 1, IntegerListObserver.class); verifyObserver(new CharacterList(), 0); } @Test @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "b") public void testParameterizedEventTypeAssignableToRawType() { Box<Integer, String, Random> box = new Box<Integer, String, Random>(); event.fire(box); assertTrue(RawTypeObserver.OBSERVED); verifyObserver(new RawTypeObserver.BoxWithDifferentTypeParameters(), 1, RawTypeObserver.class); verifyObserver(new RawTypeObserver.BoxWithObjectTypeParameters(), 1, RawTypeObserver.class); } @Test @SpecAssertions({ @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "c"), @SpecAssertion(section = OBSERVER_METHODS, id = "ab") }) public void testObservedEventTypeParameterIsActualType() { ActionSequence.reset(); Foo<String> fooString = new Foo.FooString(); verifyObserver(fooString, 1, FooObserver.class); getCurrentManager().fireEvent(fooString); verifyEvent(FooObserver.SEQUENCE, 1, buildActionId(FooObserver.class, fooString)); } @Test @SpecAssertions({ @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "d") }) public void testObservedEventTypeParameterIsActualTypeNested() { ActionSequence.reset(); Foo<List<String>> fooStringList = new Foo.FooStringList(); verifyObserver(fooStringList, 1, FooObserver.class); getCurrentManager().fireEvent(fooStringList); verifyEvent(FooObserver.SEQUENCE_NESTED, 1, buildActionId(FooObserver.class, fooStringList)); } @Test @SpecAssertions({ @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "e") }) public void testObservedEventTypeParameterIsWildcard() { ActionSequence.reset(); Qux<String> quxString = new Qux.QuxString(); Qux<List<String>> quxStringList = new Qux.QuxStringList(); Qux<Number> quxNumber = new Qux.QuxNumber(); verifyObserver(quxString, 1, WildcardObserver.class); verifyObserver(quxNumber, 2, WildcardObserver.class); verifyObserver(quxStringList, 2, WildcardObserver.class); getCurrentManager().fireEvent(quxString); getCurrentManager().fireEvent(quxStringList); getCurrentManager().fireEvent(quxNumber); verifyEvent(WildcardObserver.SEQUENCE, 3, buildActionId(WildcardObserver.class, quxString), buildActionId(WildcardObserver.class, quxStringList), buildActionId(WildcardObserver.class, quxNumber)); verifyEvent(WildcardObserver.SEQUENCE_LOWER, 1, buildActionId(WildcardObserver.class, quxNumber)); verifyEvent(WildcardObserver.SEQUENCE_UPPER, 1, buildActionId(WildcardObserver.class, quxStringList)); } @Test @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "f") public void testObservedEventTypeParameterIsTypeVariable() { ActionSequence.reset(); Duck<String> duckString = new Duck.DuckString(); Duck<Integer> duckInteger = new Duck.DuckInteger(); verifyObserver(duckString, 1, TypeVariableObserver.class); verifyObserver(duckInteger, 2, TypeVariableObserver.class); getCurrentManager().fireEvent(duckString); getCurrentManager().fireEvent(duckInteger); verifyEvent(TypeVariableObserver.SEQUENCE_TYPE_VAR, 2, buildActionId(TypeVariableObserver.class, duckString), buildActionId(TypeVariableObserver.class, duckInteger)); verifyEvent(TypeVariableObserver.SEQUENCE_TYPE_VAR_UPPER, 1, buildActionId(TypeVariableObserver.class, duckInteger)); } @Test @SpecAssertion(section = OBSERVERS_ASSIGNABILITY, id = "a") public void testEventTypeAssignableToATypeVariable() { ActionSequence.reset(); Bar bar = new Bar(); Baz baz = new Baz(); verifyObserver(bar, 1, TypeVariableObserver.class); verifyObserver(baz, 1, TypeVariableObserver.class); getCurrentManager().fireEvent(new Bar()); getCurrentManager().fireEvent(new Baz()); getCurrentManager().fireEvent(new StringList()); verifyEvent(TypeVariableObserver.SEQUENCE_UPPER, 2, buildActionId(TypeVariableObserver.class, bar), buildActionId(TypeVariableObserver.class, baz)); } /** * Quick and dirty test for various event type resolution use cases. */ @Test public void testEventTypeResolution() { int expectedMatches = 5; Dog<?, ?> dogStringNumber = new Dog.DogStringNumber(); verifyObserver(dogStringNumber, expectedMatches, DogObserver.class); getCurrentManager().fireEvent(dogStringNumber); verifyEvent(DogObserver.SEQUENCE, expectedMatches); } public static class CharacterList extends ArrayList<Character> { private static final long serialVersionUID = 1L; } public static class StringList extends ArrayList<String> { private static final long serialVersionUID = 1L; } public static class IntegerList extends ArrayList<Integer> { private static final long serialVersionUID = 1L; } public static class StringListObserver { public boolean wasNotified = false; public void observer(@Observes ArrayList<String> event) { wasNotified = true; } } public static class IntegerListObserver { public boolean wasNotified = false; public void observer(@Observes ArrayList<Integer> event) { wasNotified = true; } } private void verifyObserver(Object event, int expectedNumberOfObservers, Class<?>... expectedObserverTypes) { if (expectedNumberOfObservers < expectedObserverTypes.length) { throw new IllegalArgumentException("Invalid expected arguments"); } Set<ObserverMethod<? super Object>> observers = getCurrentManager().resolveObserverMethods(event); assertEquals(observers.size(), expectedNumberOfObservers); List<Class<?>> observerTypes = Arrays.asList(expectedObserverTypes); for (ObserverMethod<? super Object> observer : observers) { assertTrue(observerTypes.contains(observer.getBeanClass())); } } /** * @param sequenceName * @param expectedSequenceSize * @param actions Sequence data must contain all specified actions */ private void verifyEvent(String sequenceName, int expectedSequenceSize, String... actions) { List<String> sequenceData = ActionSequence.getSequenceData(sequenceName); assertNotNull(sequenceData); assertEquals(sequenceData.size(), expectedSequenceSize); for (String action : actions) { assertTrue(sequenceData.contains(action)); } } }