/*
* 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.extensions.alternative.metadata;
import static org.jboss.cdi.tck.cdi.Sections.ALTERNATIVE_METADATA_SOURCES;
import static org.jboss.cdi.tck.cdi.Sections.ALTERNATIVE_METADATA_SOURCES_EE;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.util.AnnotationLiteral;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.cdi.tck.AbstractTest;
import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.descriptor.api.Descriptors;
import org.jboss.shrinkwrap.descriptor.api.beans11.BeansDescriptor;
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;
/**
* This test class contains tests for adding meta data using extensions.
*
* @author Jozef Hartinger
* @author Martin Kouba
* @author Tomas Remes
*/
@SpecVersion(spec = "cdi", version = "2.0-PFD")
public class AlternativeMetadataTest extends AbstractTest {
@Deployment
public static WebArchive createTestArchive() {
return new WebArchiveBuilder()
.withTestClassPackage(AlternativeMetadataTest.class)
.withBeansXml(
Descriptors.create(BeansDescriptor.class).getOrCreateInterceptors()
.clazz(GroceryInterceptor.class.getName()).up()
)
.withExtension(ProcessAnnotatedTypeObserver.class).build();
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ha")
public void testGetBaseTypeUsedToDetermineTypeOfInjectionPoint() {
// The base type of the fruit injection point is overridden to
// TropicalFruit
assertTrue(GroceryWrapper.isGetBaseTypeOfFruitFieldUsed());
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getFruit().getMetadata().getType(),
TropicalFruit.class);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "hb")
public void testGetBaseTypeUsedToDetermineTypeOfInitializerInjectionPoint() {
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getInitializerFruit().getMetadata().getType(),
TropicalFruit.class);
assertTrue(GroceryWrapper.isGetBaseTypeOfInitializerTropicalFruitParameterUsed());
}
@Test
@SpecAssertions({ @SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "hc"),
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "s") })
public void testGetBaseTypeUsedToDetermineTypeOfConstructorInjectionPoint() {
assertEquals(getContextualReference(Market.class).getConstructorFruit().getMetadata().getType(),
TropicalFruit.class);
assertTrue(MarketWrapper.isGetBaseTypeOfMarketConstructorParameterUsed());
// s assertion
assertTrue(getContextualReference(Market.class).getConstructorFruit().getMetadata().getQualifiers().contains(Any.Literal.INSTANCE));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "hd")
public void testGetBaseTypeUsedToDetermineTypeOfProducerInjectionPoint() {
assertEquals(getContextualReference(Bill.class, new ExpensiveLiteral()).getFruit().getMetadata().getType(), TropicalFruit.class);
assertTrue(MarketWrapper.isGetBaseTypeOfBillProducerParameterUsed());
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "he")
public void testGetBaseTypeUsedToDetermineTypeOfObserverInjectionPoint() {
getCurrentManager().fireEvent(new Milk(false));
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getObserverFruit().getMetadata().getType(),
TropicalFruit.class);
assertTrue(GroceryWrapper.isGetBaseTypeOfObserverInjectionPointUsed());
}
@Test
@SpecAssertions({ @SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "hf"),
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ad") })
public void testGetBaseTypeUsedToDetermineTypeOfDisposerInjectionPoint() {
Bean<Bill> bill = getBeans(Bill.class, new CheapLiteral()).iterator().next();
CreationalContext<Bill> context = getCurrentManager().createCreationalContext(bill);
Bill instance = getCurrentManager().getContext(bill.getScope()).get(bill);
bill.destroy(instance, context);
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getDisposerFruit().getMetadata().getType(),
TropicalFruit.class);
assertTrue(GroceryWrapper.isGetBaseTypeOfBillDisposerParameterUsed());
// ad assertion
assertTrue(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getDisposerFruit().getMetadata().getQualifiers().contains(Any.Literal.INSTANCE));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "i")
public void testGetBaseTypeUsedToDetermineTypeOfEventParameter() {
getCurrentManager().fireEvent(new Carrot());
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getWrappedEventParameter().getClass(),
Carrot.class);
assertTrue(GroceryWrapper.isGetBaseTypeOfObserverParameterUsed());
}
@Test
@SpecAssertions({ @SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "j"),
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ac") })
public void testGetBaseTypeUsedToDetermineTypeOfDisposalParameter() throws NoSuchMethodException {
Bean<Carrot> carrot = getBeans(Carrot.class, new CheapLiteral()).iterator().next();
CreationalContext<Carrot> context = getCurrentManager().createCreationalContext(carrot);
Carrot instance = getCurrentManager().getContext(carrot.getScope()).get(carrot, context);
carrot.destroy(instance, context);
// ac assertion - disposal method called after adding extra qualifier to disposer parameter
assertNotNull(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getWrappedDisposalParameter());
assertEquals(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getWrappedDisposalParameter().getClass(),
Carrot.class);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ka")
public void testGetTypeClosureUsed() {
assertTrue(GroceryWrapper.isGetTypeClosureUsed());
// should be [Object, Grocery] instead of [Object, Shop, Grocery]
assertEquals(getBeans(Grocery.class, Any.Literal.INSTANCE).iterator().next().getTypes().size(), 2);
assertEquals(getBeans(Shop.class, Any.Literal.INSTANCE).size(), 0);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES_EE, id = "kb")
public void testGetTypeClosureUsedToDetermineTypeOfSessionBean() {
Bean<Pasta> pasta = getBeans(Pasta.class).iterator().next();
assertEquals(pasta.getTypes().size(), 2);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "kc")
public void testGetTypeClosureUsedToDetermineTypeOfProducerField() {
//produced by Market.carrot
Bean<Carrot> carrot = getBeans(Carrot.class, new ExpensiveLiteral()).iterator().next();
// should be [Carrot] instead of [Carrot, Vegetables]
assertEquals(carrot.getTypes().size(), 1);
assertEquals(carrot.getTypes().iterator().next(), Carrot.class);
assertTrue(MarketWrapper.isGetTypeCLosureOfProducerFieldUsed());
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "kd")
public void testGetTypeClosureUsedToDetermineTypeOfProducerMethod() {
// produced by Grocery.createVegetable()
Bean<Carrot> carrot = getBeans(Carrot.class, new CheapLiteral()).iterator().next();
// should be [Object, Carrot] instead of [Object, Carrot, Vegetables]
assertEquals(carrot.getTypes().size(), 2);
assertFalse(carrot.getTypes().contains(Vegetables.class));
assertTrue(GroceryWrapper.isGetTypeClosureOfProducerMethodUsed());
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "l")
public void testGetAnnotationUsedForGettingScopeInformation() {
// @ApplicationScoped is overridden by @RequestScoped
assertEquals(getBeans(Grocery.class, Any.Literal.INSTANCE).iterator().next().getScope(), RequestScoped.class);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "m")
public void testGetAnnotationUsedForGettingQualifierInformation() {
// @Expensive is overridden by @Cheap
assertEquals(getBeans(Grocery.class, new CheapLiteral()).size(), 1);
assertEquals(getBeans(Grocery.class, new ExpensiveLiteral()).size(), 0);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "n")
public void testGetAnnotationUsedForGettingStereotypeInformation() {
// The extension adds a stereotype with @Named qualifier
assertNotNull(getContextualReference("grocery", Grocery.class));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "p")
public void testGetAnnotationUsedForGettingInterceptorInformation() {
// The extension adds the GroceryInterceptorBinding
Grocery grocery = getContextualReference(Grocery.class, Any.Literal.INSTANCE);
assertEquals(grocery.foo(), "foo");
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "r")
public void testPreviouslyNonInjectAnnotatedConstructorIsUsed() {
assertTrue(getContextualReference(Grocery.class, Any.Literal.INSTANCE).isConstructorWithParameterUsed());
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "t")
public void testPreviouslyNonInjectAnnotatedFieldIsInjected() {
assertTrue(getContextualReference(Grocery.class, Any.Literal.INSTANCE).isVegetablesInjected());
}
@SuppressWarnings("unchecked")
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "u")
public void testExtraQualifierIsAppliedToInjectedField() {
assertNotNull(getContextualReference(Grocery.class, Any.Literal.INSTANCE).getFruit());
Set<Annotation> qualifiers = getContextualReference(Grocery.class, Any.Literal.INSTANCE).getFruit().getMetadata()
.getQualifiers();
assertEquals(qualifiers.size(), 1);
assertTrue(annotationSetMatches(qualifiers, Cheap.class));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "v")
public void testProducesCreatesProducerField() {
// The extension adds @Producer to the bread field
assertEquals(getBeans(Bread.class, Any.Literal.INSTANCE).size(), 1);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "w")
public void testInjectCreatesInitializerMethod() {
// The extension adds @Inject to the nonInjectAnnotatedInitializer()
// method
assertTrue(getContextualReference(Grocery.class, Any.Literal.INSTANCE).isWaterInjected());
}
@SuppressWarnings("unchecked")
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "x")
public void testQualifierAddedToInitializerParameter() {
// The @Cheap qualifier is added to the method parameter
Set<Annotation> qualifiers = getContextualReference(Grocery.class, Any.Literal.INSTANCE).getInitializerFruit().getMetadata()
.getQualifiers();
assertTrue(annotationSetMatches(qualifiers, Cheap.class));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "y")
public void testProducesCreatesProducerMethod() {
// The extension adds @Producer to the getMilk() method
assertEquals(getBeans(Milk.class, Any.Literal.INSTANCE).size(), 1);
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "z")
public void testQualifierIsAppliedToProducerMethod() {
// The extension adds @Expensive to the getMilk() method
assertEquals(getBeans(Yogurt.class, new ExpensiveLiteral()).size(), 1);
assertEquals(getBeans(Yogurt.class, new CheapLiteral()).size(), 0);
}
@SuppressWarnings("unchecked")
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "aa")
public void testQualifierIsAppliedToProducerMethodParameter() {
// The @Cheap qualifier is added to the method parameter
Set<Annotation> qualifiers = getContextualReference(Yogurt.class, Any.Literal.INSTANCE).getFruit().getMetadata()
.getQualifiers();
assertEquals(qualifiers.size(), 1);
assertTrue(annotationSetMatches(qualifiers, Cheap.class));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ab")
public void testDisposesIsAppliedToMethodParameter() {
Bean<Yogurt> yogurt = getBeans(Yogurt.class, new ExpensiveLiteral()).iterator().next();
CreationalContext<Yogurt> context = getCurrentManager().createCreationalContext(yogurt);
Yogurt instance = getCurrentManager().getContext(yogurt.getScope()).get(yogurt, context);
yogurt.destroy(instance, context);
assertTrue(Grocery.isDisposerMethodCalled());
}
@SuppressWarnings("unchecked")
@Test
@SpecAssertions({ @SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ae"), @SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "ag") })
public void testObserverMethod() {
getCurrentManager().fireEvent(new Milk(true));
Milk event = getContextualReference(Grocery.class, Any.Literal.INSTANCE).getObserverEvent();
TropicalFruit parameter = getContextualReference(Grocery.class, Any.Literal.INSTANCE).getObserverParameter();
assertNotNull(event);
assertNotNull(parameter);
assertEquals(parameter.getMetadata().getQualifiers().size(), 1);
assertTrue(annotationSetMatches(parameter.getMetadata().getQualifiers(), Cheap.class));
}
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "af")
public void testExtraQualifierAppliedToObservesMethodParameter() {
getCurrentManager().fireEvent(new Bread(true));
// normally, the event would be observer, however the extension adds the
// @Expensive qualifier to the method parameter
assertFalse(getContextualReference(Grocery.class, Any.Literal.INSTANCE).isObserver2Used());
}
@SuppressWarnings("serial")
@Test
@SpecAssertion(section = ALTERNATIVE_METADATA_SOURCES, id = "h")
public void testContainerUsesOperationsOfAnnotatedNotReflectionApi() {
assertEquals(getBeans(Sausage.class, Any.Literal.INSTANCE).size(), 1);
// Overriding annotated type has no methods and fields and thus there are no cheap and expensive sausages
assertTrue(getBeans(Sausage.class, new AnnotationLiteral<Expensive>() {
}).isEmpty());
assertTrue(getBeans(Sausage.class, new AnnotationLiteral<Cheap>() {
}).isEmpty());
}
}