From fb5d6efcb5cdb6718199f94258897eb9263f4a4c Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Tue, 14 Nov 2023 12:56:13 +0100 Subject: [PATCH 1/3] initial TCK tests for method invokers --- .../full/invokers/SimpleInvokerTest.java | 80 ++++ .../invalid/DecoratorInvokerTest.java | 82 ++++ .../cdi/tck/tests/invokers/InvokerHolder.java | 36 ++ .../tests/invokers/InvokerHolderCreator.java | 37 ++ .../invokers/InvokerHolderExtensionBase.java | 49 +++ .../tck/tests/invokers/SimpleInvokerTest.java | 80 ++++ .../basic/BadInstanceInvokerTest.java | 92 ++++ .../basic/ExcessArgumentsInvokerTest.java | 89 ++++ .../basic/GoodInstanceInvokerTest.java | 99 +++++ .../basic/InstanceMethodInvokerTest.java | 122 ++++++ .../basic/InterceptedMethodInvokerTest.java | 110 +++++ .../basic/InvokerAssignabilityTest.java | 405 ++++++++++++++++++ .../invokers/basic/InvokerVisibilityTest.java | 178 ++++++++ .../basic/MissingArgumentsInvokerTest.java | 103 +++++ .../basic/PrimitiveParametersInvokerTest.java | 106 +++++ .../PrimitiveReturnValueInvokerTest.java | 87 ++++ .../basic/StaticMethodInvokerTest.java | 120 ++++++ .../invokers/basic/ThrowingInvokerTest.java | 99 +++++ .../basic/VarargsMethodInvokerTest.java | 96 +++++ .../invokers/basic/VoidMethodInvokerTest.java | 85 ++++ .../basic/ZeroParametersInvokerTest.java | 88 ++++ .../invalid/ConstructorInvokerTest.java | 66 +++ .../invalid/InterceptorInvokerTest.java | 90 ++++ .../MethodFromDifferentClassInvokerTest.java | 78 ++++ ...ObjectMethodButNotToStringInvokerTest.java | 66 +++ .../invalid/PrivateMethodInvokerTest.java | 68 +++ .../invalid/ProducerFieldBeanInvokerTest.java | 77 ++++ .../ProducerMethodBeanInvokerTest.java | 79 ++++ impl/src/main/resources/tck-audit-cdi.xml | 162 +++++++ 29 files changed, 2929 insertions(+) create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/SimpleInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/invalid/DecoratorInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolder.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderCreator.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/SimpleInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/BadInstanceInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ExcessArgumentsInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/GoodInstanceInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InstanceMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InterceptedMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerAssignabilityTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerVisibilityTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/MissingArgumentsInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveParametersInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveReturnValueInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/StaticMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ThrowingInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VarargsMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VoidMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ZeroParametersInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ConstructorInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/InterceptorInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/MethodFromDifferentClassInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ObjectMethodButNotToStringInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/PrivateMethodInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerFieldBeanInvokerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerMethodBeanInvokerTest.java diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/SimpleInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/SimpleInvokerTest.java new file mode 100644 index 000000000..8435f84c8 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/SimpleInvokerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2024, 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.full.invokers; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessManagedBean; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.jboss.cdi.tck.TestGroups.CDI_FULL; +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +@Test(groups = CDI_FULL) +public class SimpleInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(SimpleInvokerTest.class) + .withClasses(MyService.class) + .withExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements Extension { + private Map> invokers = new HashMap<>(); + + public void myServiceRegistration(@Observes ProcessManagedBean pmb) { + pmb.getAnnotatedBeanClass() + .getMethods() + .stream() + .filter(it -> "hello".equals(it.getJavaMember().getName())) + .forEach(it -> invokers.put(it.getJavaMember().getName(), pmb.createInvoker(it).build())); + } + + public Invoker getInvoker(String name) { + return (Invoker) invokers.get(name); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.METHOD_INVOKERS_FULL, id = "a") + public void test(MyService service) throws Exception { + Invoker hello = getCurrentManager().getExtension(TestExtension.class).getInvoker("hello"); + assertEquals(hello.invoke(service, new Object[]{1, List.of()}), "foobar1[]"); + } + + @ApplicationScoped + public static class MyService { + public String hello(int param1, List param2) { + return "foobar" + param1 + param2; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/invalid/DecoratorInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/invalid/DecoratorInvokerTest.java new file mode 100644 index 000000000..fb3175e6e --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/full/invokers/invalid/DecoratorInvokerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2024, 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.full.invokers.invalid; + +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessManagedBean; +import jakarta.inject.Inject; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.jboss.cdi.tck.TestGroups.CDI_FULL; + +@SpecVersion(spec = "cdi", version = "4.1") +@Test(groups = CDI_FULL) +public class DecoratorInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(DecoratorInvokerTest.class) + .withClasses(MyService.class, MyDecorator.class) + .withExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements Extension { + public void myDecoratorRegistration(@Observes ProcessManagedBean pmb) { + pmb.getAnnotatedBeanClass() + .getMethods() + .stream() + .filter(it -> "hello".equals(it.getJavaMember().getName())) + .forEach(it -> pmb.createInvoker(it).build()); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER_FULL, id = "a") + public void trigger() { + } + + public interface MyService { + String hello(); + } + + @Decorator + @Priority(1) + public static class MyDecorator implements MyService { + @Inject + @Delegate + MyService delegate; + + @Override + public String hello() { + return "decorated: " + delegate.hello(); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolder.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolder.java new file mode 100644 index 000000000..8d9c0cd27 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolder.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024, 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.invokers; + +import jakarta.enterprise.invoke.Invoker; + +import java.util.Map; + +import static org.testng.Assert.assertNotNull; + +public class InvokerHolder { + private final Map> invokers; + + public InvokerHolder(Map> invokers) { + this.invokers = invokers; + } + + public Invoker get(String id) { + Invoker result = (Invoker) invokers.get(id); + assertNotNull(result); + return result; + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderCreator.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderCreator.java new file mode 100644 index 000000000..59cad83e7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderCreator.java @@ -0,0 +1,37 @@ +/* + * Copyright 2024, 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.invokers; + +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.Parameters; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator; +import jakarta.enterprise.invoke.Invoker; + +import java.util.HashMap; +import java.util.Map; + +public class InvokerHolderCreator implements SyntheticBeanCreator { + @Override + public InvokerHolder create(Instance lookup, Parameters params) { + String[] names = params.get("names", String[].class); + Invoker[] invokers = params.get("invokers", Invoker[].class); + Map> map = new HashMap<>(); + for (int i = 0; i < names.length; i++) { + map.put(names[i], invokers[i]); + } + return new InvokerHolder(map); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java new file mode 100644 index 000000000..e627811b3 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024, 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.invokers; + +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public abstract class InvokerHolderExtensionBase { + private final Map invokers = new LinkedHashMap<>(); + + protected final void registerInvokers(BeanInfo bean, InvokerFactory invokers, Set methods) { + bean.declaringClass() + .methods() + .stream() + .filter(it -> methods.contains(it.name())) + .forEach(it -> registerInvoker(it.name(), invokers.createInvoker(bean, it).build())); + } + + protected final void registerInvoker(String id, InvokerInfo invoker) { + invokers.put(id, invoker); + } + + protected final void synthesizeInvokerHolder(SyntheticComponents syn) { + syn.addBean(InvokerHolder.class) + .type(InvokerHolder.class) + .withParam("names", invokers.keySet().toArray(String[]::new)) + .withParam("invokers", invokers.values().toArray(InvokerInfo[]::new)) + .createWith(InvokerHolderCreator.class); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/SimpleInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/SimpleInvokerTest.java new file mode 100644 index 000000000..b2b28d34d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/SimpleInvokerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2024, 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.invokers; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class SimpleInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(SimpleInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.METHOD_INVOKERS, id = "a") + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "a") + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "e") + @SpecAssertion(section = Sections.USING_INVOKER_BUILDER, id = "a") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{1, List.of()}), "foobar1[]"); + } + + @ApplicationScoped + public static class MyService { + public String hello(int param1, List param2) { + return "foobar" + param1 + param2; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/BadInstanceInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/BadInstanceInvokerTest.java new file mode 100644 index 000000000..93f3fc0a7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/BadInstanceInvokerTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class BadInstanceInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(BadInstanceInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "b") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "c") + public void test(InvokerHolder invokers) { + Invoker hello = invokers.get("hello"); + assertThrows(RuntimeException.class, () -> { + hello.invoke(null, new Object[]{""}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(new Object(), new Object[]{""}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke("", new Object[]{""}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(List.of(""), new Object[]{""}); + }); + } + + @ApplicationScoped + public static class MyService { + public String hello(String param) { + return "foobar_" + param; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ExcessArgumentsInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ExcessArgumentsInvokerTest.java new file mode 100644 index 000000000..600d06507 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ExcessArgumentsInvokerTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ExcessArgumentsInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ExcessArgumentsInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "k") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{"a", "ignored"}), "foobar_a"); + assertEquals(hello.invoke(new MyService(), new Object[]{"b", 1, 2, 3}), "foobar_b"); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals(helloStatic.invoke(null, new Object[]{"c", new Object()}), "quux_c"); + assertEquals(helloStatic.invoke(null, new Object[]{"d", List.of(), Set.of()}), "quux_d"); + } + + @ApplicationScoped + public static class MyService { + public String hello(String param) { + return "foobar_" + param; + } + + public static String helloStatic(String param) { + return "quux_" + param; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/GoodInstanceInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/GoodInstanceInvokerTest.java new file mode 100644 index 000000000..7e9b4c287 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/GoodInstanceInvokerTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class GoodInstanceInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(GoodInstanceInvokerTest.class) + .withClasses(MyService.class, MyServiceInterface.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + bean.declaringClass() + .methods() + .stream() + .filter(it -> "hello".equals(it.name()) || it.declaringClass().isInterface()) + .forEach(it -> { + registerInvoker(it.name(), invokers.createInvoker(bean, it).build()); + }); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "da") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "db") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "dc") + public void test(InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(getContextualReference(MyService.class), new Object[]{"1"}), "foobar_1"); + assertEquals(hello.invoke(new MyService(), new Object[]{"2"}), "foobar_2"); + + Invoker helloInterface = invokers.get("helloInterface"); + assertEquals(helloInterface.invoke(getContextualReference(MyServiceInterface.class), new Object[]{"3"}), "quux_3"); + assertEquals(helloInterface.invoke(new MyService(), new Object[]{"4"}), "quux_4"); + } + + public interface MyServiceInterface { + String helloInterface(String param); + } + + @ApplicationScoped + public static class MyService implements MyServiceInterface { + public String hello(String param) { + return "foobar_" + param; + } + + @Override + public String helloInterface(String param) { + return "quux_" + param; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InstanceMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InstanceMethodInvokerTest.java new file mode 100644 index 000000000..96403ffd4 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InstanceMethodInvokerTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.expectThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InstanceMethodInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InstanceMethodInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "doSomething", "fail")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.USING_INVOKER, id = "a") + @SpecAssertion(section = Sections.USING_INVOKER, id = "b") + @SpecAssertion(section = Sections.USING_INVOKER, id = "c") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{0, List.of()}), "foobar0[]"); + assertEquals(hello.invoke(new MyService(), new Object[]{1, List.of()}), "foobar1[]"); + assertThrows(RuntimeException.class, () -> { + hello.invoke(null, new Object[]{2, List.of()}); + }); + + Invoker helloDetyped = (Invoker) hello; + assertEquals("foobar3[]", helloDetyped.invoke(service, new Object[]{3, List.of()})); + assertEquals("foobar4[]", helloDetyped.invoke(new MyService(), new Object[]{4, List.of()})); + assertThrows(RuntimeException.class, () -> { + helloDetyped.invoke(null, new Object[]{5, List.of()}); + }); + + Invoker doSomething = invokers.get("doSomething"); + assertEquals(0, MyService.counter); + assertNull(doSomething.invoke(service, null)); + assertEquals(1, MyService.counter); + assertNull(doSomething.invoke(new MyService(), new Object[]{})); + assertEquals(2, MyService.counter); + + Invoker fail = invokers.get("fail"); + assertNull(fail.invoke(service, new Object[]{false})); + IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> { + fail.invoke(service, new Object[]{true}); + }); + assertEquals("expected", ex.getMessage()); + } + + @ApplicationScoped + public static class MyService { + public static int counter = 0; + + public String hello(int param1, List param2) { + return "foobar" + param1 + param2; + } + + public void doSomething() { + counter++; + } + + public void fail(boolean doFail) { + if (doFail) { + throw new IllegalArgumentException("expected"); + } + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InterceptedMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InterceptedMethodInvokerTest.java new file mode 100644 index 000000000..f38454f0e --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InterceptedMethodInvokerTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.annotation.Priority; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InterceptorBinding; +import jakarta.interceptor.InvocationContext; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InterceptedMethodInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InterceptedMethodInvokerTest.class) + .withClasses(MyInterceptorBinding.class, MyInterceptor.class, MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.USING_INVOKER, id = "d") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{0, List.of("a")}), "intercepted: foobar0[a]"); + // not a contextual reference, not intercepted + assertEquals(hello.invoke(new MyService(), new Object[]{1, List.of("b")}), "foobar1[b]"); + } + + @Target({ElementType.TYPE, ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @InterceptorBinding + public @interface MyInterceptorBinding { + } + + @MyInterceptorBinding + @Interceptor + @Priority(1) + public static class MyInterceptor { + @AroundInvoke + Object aroundInvoke(InvocationContext ctx) throws Exception { + return "intercepted: " + ctx.proceed(); + } + } + + @ApplicationScoped + public static class MyService { + public static int counter = 0; + + @MyInterceptorBinding + public String hello(int param1, List param2) { + return "foobar" + param1 + param2; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerAssignabilityTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerAssignabilityTest.java new file mode 100644 index 000000000..549aecd67 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerAssignabilityTest.java @@ -0,0 +1,405 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.fail; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InvokerAssignabilityTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InvokerAssignabilityTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + for (MethodInfo method : bean.declaringClass().methods()) { + registerInvoker(method.name(), invokers.createInvoker(bean, method).build()); + } + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "g") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "l") + public void testNonNull(MyService service, InvokerHolder invokers) { + assertOK(invokers, service, "helloBoolean", array(true)); + assertOK(invokers, service, "helloByte", array((byte) 1)); + assertOK(invokers, service, "helloShort", array((short) 1)); + assertOK(invokers, service, "helloInt", array(1)); + assertOK(invokers, service, "helloLong", array(1L)); + assertOK(invokers, service, "helloFloat", array(1.0F)); + assertOK(invokers, service, "helloDouble", array(1.0)); + assertOK(invokers, service, "helloChar", array('a')); + + assertOK(invokers, service, "helloShort", array((byte) 1)); + assertOK(invokers, service, "helloInt", array((byte) 1)); + assertOK(invokers, service, "helloInt", array((short) 1)); + assertOK(invokers, service, "helloLong", array((byte) 1)); + assertOK(invokers, service, "helloLong", array((short) 1)); + assertOK(invokers, service, "helloLong", array(1)); + assertOK(invokers, service, "helloFloat", array(1)); + assertOK(invokers, service, "helloFloat", array(1L)); + assertOK(invokers, service, "helloDouble", array(1)); + assertOK(invokers, service, "helloDouble", array(1L)); + assertOK(invokers, service, "helloDouble", array(1.0F)); + + assertOK(invokers, service, "helloBooleanWrapper", array(true)); + assertOK(invokers, service, "helloByteWrapper", array((byte) 1)); + assertOK(invokers, service, "helloShortWrapper", array((short) 1)); + assertOK(invokers, service, "helloIntWrapper", array(1)); + assertOK(invokers, service, "helloLongWrapper", array(1L)); + assertOK(invokers, service, "helloFloatWrapper", array(1.0F)); + assertOK(invokers, service, "helloDoubleWrapper", array(1.0)); + assertOK(invokers, service, "helloCharWrapper", array('a')); + assertOK(invokers, service, "helloString", array("")); + assertOK(invokers, service, "helloCollection", array(List.of())); + assertOK(invokers, service, "helloCollection", array(Set.of())); + assertOK(invokers, service, "helloSerializable", array(1)); // Number is Serializable + assertOK(invokers, service, "helloSerializable", array(new Object[]{})); + assertOK(invokers, service, "helloSerializable", array(new String[]{})); + assertOK(invokers, service, "helloObject", array("")); + assertOK(invokers, service, "helloObject", array(List.of())); + assertOK(invokers, service, "helloObject", array(new Object())); + assertOK(invokers, service, "helloObject", array(new int[]{})); + assertOK(invokers, service, "helloObject", array(new String[]{})); + assertOK(invokers, service, "helloObject", array(new List[]{})); + assertOK(invokers, service, "helloObject", array(new Object[]{})); + + assertOK(invokers, service, "helloBooleanArray", array(new boolean[]{true})); + assertOK(invokers, service, "helloByteArray", array(new byte[]{(byte) 1})); + assertOK(invokers, service, "helloShortArray", array(new short[]{(short) 1})); + assertOK(invokers, service, "helloIntArray", array(new int[]{1})); + assertOK(invokers, service, "helloLongArray", array(new long[]{1L})); + assertOK(invokers, service, "helloFloatArray", array(new float[]{1.0F})); + assertOK(invokers, service, "helloDoubleArray", array(new double[]{1.0})); + assertOK(invokers, service, "helloCharArray", array(new char[]{'a'})); + assertOK(invokers, service, "helloStringArray", array(new String[]{})); + assertOK(invokers, service, "helloObjectArray", array(new String[]{})); + assertOK(invokers, service, "helloObjectArray", array(new Object[]{})); + + assertOK(invokers, service, "helloCollectionArrayArray", array(new List[][]{})); + assertOK(invokers, service, "helloCollectionArrayArray", array(new Set[][]{})); + assertOK(invokers, service, "helloObjectArrayArray", array(new List[][]{})); + assertOK(invokers, service, "helloObjectArrayArray", array(new Set[][]{})); + assertOK(invokers, service, "helloObjectArrayArray", array(new String[][]{})); + assertOK(invokers, service, "helloObjectArrayArray", array(new Object[][]{})); + assertOK(invokers, service, "helloObjectArrayArray", array(new Object[][][]{})); + + assertFail(invokers, service, "helloBoolean", array(1)); + assertFail(invokers, service, "helloByte", array(1)); + assertFail(invokers, service, "helloShort", array(1)); + assertFail(invokers, service, "helloInt", array(1L)); + assertFail(invokers, service, "helloInt", array(1.0)); + assertFail(invokers, service, "helloLong", array(1.0F)); + assertFail(invokers, service, "helloLong", array(1.0)); + assertFail(invokers, service, "helloFloat", array(1.0)); + assertFail(invokers, service, "helloChar", array(false)); + assertFail(invokers, service, "helloChar", array((byte) 1)); + assertFail(invokers, service, "helloChar", array((short) 1)); + assertFail(invokers, service, "helloChar", array(1)); + assertFail(invokers, service, "helloChar", array(1L)); + assertFail(invokers, service, "helloChar", array(1.0F)); + assertFail(invokers, service, "helloChar", array(1.0)); + assertFail(invokers, service, "helloLong", array(new BigInteger("1"))); + assertFail(invokers, service, "helloDouble", array(new BigInteger("1"))); + assertFail(invokers, service, "helloDouble", array(new BigDecimal("1.0"))); + + assertFail(invokers, service, "helloBooleanWrapper", array(1)); + assertFail(invokers, service, "helloByteWrapper", array(1)); + assertFail(invokers, service, "helloShortWrapper", array((byte) 1)); + assertFail(invokers, service, "helloShortWrapper", array(1)); + assertFail(invokers, service, "helloIntWrapper", array((short) 1)); + assertFail(invokers, service, "helloIntWrapper", array(1L)); + assertFail(invokers, service, "helloLongWrapper", array(1)); + assertFail(invokers, service, "helloLongWrapper", array(1.0)); + assertFail(invokers, service, "helloFloatWrapper", array(1)); + assertFail(invokers, service, "helloFloatWrapper", array(1L)); + assertFail(invokers, service, "helloFloatWrapper", array(1.0)); + assertFail(invokers, service, "helloDoubleWrapper", array(1)); + assertFail(invokers, service, "helloDoubleWrapper", array(1L)); + assertFail(invokers, service, "helloDoubleWrapper", array(1.0F)); + assertFail(invokers, service, "helloCharWrapper", array((byte) 1)); + assertFail(invokers, service, "helloCharWrapper", array(1)); + assertFail(invokers, service, "helloCharWrapper", array(1L)); + assertFail(invokers, service, "helloCharWrapper", array(1.0F)); + assertFail(invokers, service, "helloCharWrapper", array(1.0)); + assertFail(invokers, service, "helloLongWrapper", array(new BigInteger("1"))); + assertFail(invokers, service, "helloDoubleWrapper", array(new BigInteger("1"))); + assertFail(invokers, service, "helloDoubleWrapper", array(new BigDecimal("1.0"))); + assertFail(invokers, service, "helloString", array(new Object())); + assertFail(invokers, service, "helloCollection", array(1)); + assertFail(invokers, service, "helloCollection", array(new Object())); + assertFail(invokers, service, "helloSerializable", array(new Object())); + + assertFail(invokers, service, "helloBooleanArray", array(new int[]{1})); + assertFail(invokers, service, "helloByteArray", array(new int[]{1})); + assertFail(invokers, service, "helloShortArray", array(new int[]{1})); + assertFail(invokers, service, "helloIntArray", array(new long[]{1L})); + assertFail(invokers, service, "helloLongArray", array(new int[]{1})); + assertFail(invokers, service, "helloFloatArray", array(new double[]{1.0})); + assertFail(invokers, service, "helloDoubleArray", array(new float[]{1.0F})); + assertFail(invokers, service, "helloCharArray", array(new int[]{1})); + assertFail(invokers, service, "helloStringArray", array("")); + assertFail(invokers, service, "helloStringArray", array(new Object())); + assertFail(invokers, service, "helloStringArray", array(new String[][]{})); + assertFail(invokers, service, "helloStringArray", array(new Object[]{})); + assertFail(invokers, service, "helloObjectArray", array("")); + assertFail(invokers, service, "helloObjectArray", array(new Object())); + + assertFail(invokers, service, "helloCollectionArrayArray", array(new List[]{})); + assertFail(invokers, service, "helloCollectionArrayArray", array(new Set[]{})); + assertFail(invokers, service, "helloCollectionArrayArray", array(new List[][][]{})); + assertFail(invokers, service, "helloCollectionArrayArray", array(new Set[][][]{})); + assertFail(invokers, service, "helloCollectionArrayArray", array(new Object[][]{})); + assertFail(invokers, service, "helloObjectArrayArray", array(new Object[]{})); + assertFail(invokers, service, "helloObjectArrayArray", array(new Object())); + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "g") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "l") + public void testNull(MyService service, InvokerHolder invokers) { + assertOK(invokers, service, "helloBooleanWrapper", array(null)); + assertOK(invokers, service, "helloByteWrapper", array(null)); + assertOK(invokers, service, "helloShortWrapper", array(null)); + assertOK(invokers, service, "helloIntWrapper", array(null)); + assertOK(invokers, service, "helloLongWrapper", array(null)); + assertOK(invokers, service, "helloFloatWrapper", array(null)); + assertOK(invokers, service, "helloDoubleWrapper", array(null)); + assertOK(invokers, service, "helloCharWrapper", array(null)); + assertOK(invokers, service, "helloString", array(null)); + assertOK(invokers, service, "helloCollection", array(null)); + assertOK(invokers, service, "helloSerializable", array(null)); + assertOK(invokers, service, "helloObject", array(null)); + + assertOK(invokers, service, "helloBooleanArray", array(null)); + assertOK(invokers, service, "helloByteArray", array(null)); + assertOK(invokers, service, "helloShortArray", array(null)); + assertOK(invokers, service, "helloIntArray", array(null)); + assertOK(invokers, service, "helloLongArray", array(null)); + assertOK(invokers, service, "helloFloatArray", array(null)); + assertOK(invokers, service, "helloDoubleArray", array(null)); + assertOK(invokers, service, "helloCharArray", array(null)); + assertOK(invokers, service, "helloStringArray", array(null)); + assertOK(invokers, service, "helloObjectArray", array(null)); + + assertOK(invokers, service, "helloCollectionArrayArray", array(null)); + assertOK(invokers, service, "helloObjectArrayArray", array(null)); + + assertFail(invokers, service, "helloBoolean", array(null)); + assertFail(invokers, service, "helloByte", array(null)); + assertFail(invokers, service, "helloShort", array(null)); + assertFail(invokers, service, "helloInt", array(null)); + assertFail(invokers, service, "helloLong", array(null)); + assertFail(invokers, service, "helloFloat", array(null)); + assertFail(invokers, service, "helloDouble", array(null)); + assertFail(invokers, service, "helloChar", array(null)); + } + + // produces a single-element array whose only element is `obj` + private static Object[] array(Object obj) { + return new Object[]{obj}; + } + + private static void assertOK(InvokerHolder invokers, MyService instance, String methodName, Object[] arguments) { + Invoker invoker = invokers.get(methodName); + String result = null; + try { + result = invoker.invoke(instance, arguments); + } catch (Exception e) { + fail("unexpected exception", e); + } + assertEquals("OK", result); + } + + private static void assertFail(InvokerHolder invokers, MyService instance, String methodName, Object[] arguments) { + Invoker invoker = invokers.get(methodName); + assertThrows(RuntimeException.class, () -> invoker.invoke(instance, arguments)); + } + + @ApplicationScoped + public static class MyService { + public String helloBoolean(boolean b) { + return "OK"; + } + + public String helloByte(byte b) { + return "OK"; + } + + public String helloShort(short s) { + return "OK"; + } + + public String helloInt(int i) { + return "OK"; + } + + public String helloLong(long l) { + return "OK"; + } + + public String helloFloat(float f) { + return "OK"; + } + + public String helloDouble(double d) { + return "OK"; + } + + public String helloChar(char ch) { + return "OK"; + } + + public String helloBooleanWrapper(Boolean b) { + return "OK"; + } + + public String helloByteWrapper(Byte b) { + return "OK"; + } + + public String helloShortWrapper(Short s) { + return "OK"; + } + + public String helloIntWrapper(Integer i) { + return "OK"; + } + + public String helloLongWrapper(Long l) { + return "OK"; + } + + public String helloFloatWrapper(Float f) { + return "OK"; + } + + public String helloDoubleWrapper(Double d) { + return "OK"; + } + + public String helloCharWrapper(Character ch) { + return "OK"; + } + + public String helloString(String s) { + return "OK"; + } + + public String helloCollection(Collection c) { + return "OK"; + } + + public String helloSerializable(Serializable s) { + return "OK"; + } + + public String helloObject(Object o) { + return "OK"; + } + + public String helloBooleanArray(boolean[] b) { + return "OK"; + } + + public String helloByteArray(byte[] b) { + return "OK"; + } + + public String helloShortArray(short[] s) { + return "OK"; + } + + public String helloIntArray(int[] i) { + return "OK"; + } + + public String helloLongArray(long[] l) { + return "OK"; + } + + public String helloFloatArray(float[] f) { + return "OK"; + } + + public String helloDoubleArray(double[] d) { + return "OK"; + } + + public String helloCharArray(char[] ch) { + return "OK"; + } + + public String helloStringArray(String[] s) { + return "OK"; + } + + public String helloObjectArray(Object[] o) { + return "OK"; + } + + public String helloCollectionArrayArray(Collection[][] c) { + return "OK"; + } + + public String helloObjectArrayArray(Object[][] o) { + return "OK"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerVisibilityTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerVisibilityTest.java new file mode 100644 index 000000000..1e44a35f3 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/InvokerVisibilityTest.java @@ -0,0 +1,178 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InvokerVisibilityTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InvokerVisibilityTest.class) + .withClasses(MyPublicService.class, MyProtectedService.class, MyPackagePrivateService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyPublicService.class) + public void myPublicServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + invokersForAllMethods(bean, invokers); + } + + @Registration(types = MyProtectedService.class) + public void myProtectedServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + invokersForAllMethods(bean, invokers); + } + + @Registration(types = MyPackagePrivateService.class) + public void myPackagePrivateServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + invokersForAllMethods(bean, invokers); + } + + private void invokersForAllMethods(BeanInfo bean, InvokerFactory invokers) { + for (MethodInfo method : bean.declaringClass().methods()) { + registerInvoker(bean.declaringClass().simpleName() + "_" + method.name(), + invokers.createInvoker(bean, method).build()); + } + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "be") + public void test(Instance lookup, InvokerHolder invokers) throws Exception { + for (Class clazz : List.of(MyPublicService.class, MyProtectedService.class, MyPackagePrivateService.class)) { + Object service = lookup.select(clazz).get(); + + for (String method : List.of("hello", "helloProtected", "helloPackagePrivate", + "helloStatic", "helloProtectedStatic", "helloPackagePrivateStatic")) { + String id = clazz.getSimpleName() + "_" + method; + assertEquals(invokers.get(id).invoke(service, null), id); + } + } + } + + @ApplicationScoped + public static class MyPublicService { + public String hello() { + return "MyPublicService_hello"; + } + + protected String helloProtected() { + return "MyPublicService_helloProtected"; + } + + String helloPackagePrivate() { + return "MyPublicService_helloPackagePrivate"; + } + + public static String helloStatic() { + return "MyPublicService_helloStatic"; + } + + protected static String helloProtectedStatic() { + return "MyPublicService_helloProtectedStatic"; + } + + static String helloPackagePrivateStatic() { + return "MyPublicService_helloPackagePrivateStatic"; + } + } + + @ApplicationScoped + protected static class MyProtectedService { + public String hello() { + return "MyProtectedService_hello"; + } + + protected String helloProtected() { + return "MyProtectedService_helloProtected"; + } + + String helloPackagePrivate() { + return "MyProtectedService_helloPackagePrivate"; + } + + public static String helloStatic() { + return "MyProtectedService_helloStatic"; + } + + protected static String helloProtectedStatic() { + return "MyProtectedService_helloProtectedStatic"; + } + + static String helloPackagePrivateStatic() { + return "MyProtectedService_helloPackagePrivateStatic"; + } + } + + @ApplicationScoped + static class MyPackagePrivateService { + public String hello() { + return "MyPackagePrivateService_hello"; + } + + protected String helloProtected() { + return "MyPackagePrivateService_helloProtected"; + } + + String helloPackagePrivate() { + return "MyPackagePrivateService_helloPackagePrivate"; + } + + public static String helloStatic() { + return "MyPackagePrivateService_helloStatic"; + } + + protected static String helloProtectedStatic() { + return "MyPackagePrivateService_helloProtectedStatic"; + } + + static String helloPackagePrivateStatic() { + return "MyPackagePrivateService_helloPackagePrivateStatic"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/MissingArgumentsInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/MissingArgumentsInvokerTest.java new file mode 100644 index 000000000..e7a57d37c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/MissingArgumentsInvokerTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class MissingArgumentsInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(MissingArgumentsInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "i") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "j") + public void test(MyService service, InvokerHolder invokers) { + Invoker hello = invokers.get("hello"); + assertThrows(RuntimeException.class, () -> { + hello.invoke(service, null); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(service, new Object[]{}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(new MyService(), new Object[]{1}); + }); + + Invoker helloStatic = invokers.get("helloStatic"); + assertThrows(RuntimeException.class, () -> { + helloStatic.invoke(null, null); + }); + assertThrows(RuntimeException.class, () -> { + helloStatic.invoke(null, new Object[]{""}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(null, new Object[]{}); + }); + } + + @ApplicationScoped + public static class MyService { + public String hello(int param1, String param2) { + return "foobar_" + param1 + param2; + } + + public static String helloStatic(String param1, int param2) { + return "quux_" + param1 + param2; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveParametersInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveParametersInvokerTest.java new file mode 100644 index 000000000..fa8f8b122 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveParametersInvokerTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class PrimitiveParametersInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(PrimitiveParametersInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "g") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "l") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{true, 'a', 1}), "foobar_true_a_1"); + assertEquals(hello.invoke(new MyService(), new Object[]{false, 'b', (short) 2}), "foobar_false_b_2"); + assertThrows(RuntimeException.class, () -> { + hello.invoke(new MyService(), new Object[]{null, null, null}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(service, new Object[]{true, 'a', 1L}); + }); + assertThrows(RuntimeException.class, () -> { + hello.invoke(service, new Object[]{true, 'a', 1.0}); + }); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals(helloStatic.invoke(null, new Object[]{1L, 1.0}), "quux_1_1.0"); + assertEquals(helloStatic.invoke(null, new Object[]{1, 1.0}), "quux_1_1.0"); + assertEquals(helloStatic.invoke(null, new Object[]{1L, 1.0F}), "quux_1_1.0"); + assertThrows(RuntimeException.class, () -> { + helloStatic.invoke(null, new Object[]{null, null}); + }); + assertThrows(RuntimeException.class, () -> { + helloStatic.invoke(null, new Object[]{1.0, 1.0}); + }); + } + + @ApplicationScoped + public static class MyService { + public String hello(boolean b, char c, int i) { + return "foobar_" + b + "_" + c + "_" + i; + } + + public static String helloStatic(long l, double d) { + return "quux_" + l + "_" + d; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveReturnValueInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveReturnValueInvokerTest.java new file mode 100644 index 000000000..10d433511 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/PrimitiveReturnValueInvokerTest.java @@ -0,0 +1,87 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class PrimitiveReturnValueInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(PrimitiveReturnValueInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "m") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, null), Integer.valueOf(42)); + assertEquals(hello.invoke(new MyService(), null), Integer.valueOf(42)); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals(helloStatic.invoke(null, null), Float.valueOf(42.0F)); + } + + @ApplicationScoped + public static class MyService { + public int hello() { + return 42; + } + + public static float helloStatic() { + return 42.0F; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/StaticMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/StaticMethodInvokerTest.java new file mode 100644 index 000000000..9050d769c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/StaticMethodInvokerTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.expectThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class StaticMethodInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(StaticMethodInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "doSomething", "fail")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.USING_INVOKER, id = "a") + @SpecAssertion(section = Sections.USING_INVOKER, id = "b") + @SpecAssertion(section = Sections.USING_INVOKER, id = "c") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "a") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{0, List.of()}), "foobar0[]"); + assertEquals(hello.invoke(new MyService(), new Object[]{1, List.of()}), "foobar1[]"); + assertEquals(hello.invoke(null, new Object[]{2, List.of()}), "foobar2[]"); + + Invoker helloDetyped = (Invoker) hello; + assertEquals("foobar3[]", helloDetyped.invoke(service, new Object[]{3, List.of()})); + assertEquals("foobar4[]", helloDetyped.invoke(new MyService(), new Object[]{4, List.of()})); + assertEquals("foobar5[]", helloDetyped.invoke(null, new Object[]{5, List.of()})); + + Invoker doSomething = invokers.get("doSomething"); + assertEquals(0, MyService.counter); + assertNull(doSomething.invoke(service, null)); + assertEquals(1, MyService.counter); + assertNull(doSomething.invoke(new MyService(), new Object[]{})); + assertEquals(2, MyService.counter); + assertNull(doSomething.invoke(null, new Object[]{})); + assertEquals(3, MyService.counter); + + Invoker fail = invokers.get("fail"); + assertNull(fail.invoke(null, new Object[]{false})); + IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> { + fail.invoke(null, new Object[]{true}); + }); + assertEquals("expected", ex.getMessage()); + } + + @ApplicationScoped + public static class MyService { + public static int counter = 0; + + public static String hello(int param1, List param2) { + return "foobar" + param1 + param2; + } + + public static void doSomething() { + counter++; + } + + public static void fail(boolean doFail) { + if (doFail) { + throw new IllegalArgumentException("expected"); + } + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ThrowingInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ThrowingInvokerTest.java new file mode 100644 index 000000000..7bdfadfbf --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ThrowingInvokerTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ThrowingInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ThrowingInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.USING_INVOKER, id = "a") + @SpecAssertion(section = Sections.USING_INVOKER, id = "b") + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "n") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{false}), "foobar"); + assertThrows(IllegalArgumentException.class, () -> hello.invoke(service, new Object[]{true})); + assertEquals(hello.invoke(new MyService(), new Object[]{false}), "foobar"); + assertThrows(IllegalArgumentException.class, () -> hello.invoke(new MyService(), new Object[]{true})); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals("quux", helloStatic.invoke(null, new Object[]{false})); + assertThrows(IllegalStateException.class, () -> helloStatic.invoke(null, new Object[]{true})); + } + + @ApplicationScoped + public static class MyService { + public String hello(boolean fail) { + if (fail) { + throw new IllegalArgumentException(); + } + return "foobar"; + } + + public static String helloStatic(boolean fail) { + if (fail) { + throw new IllegalStateException(); + } + return "quux"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VarargsMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VarargsMethodInvokerTest.java new file mode 100644 index 000000000..d599fb44d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VarargsMethodInvokerTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class VarargsMethodInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(VarargsMethodInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "f") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, new Object[]{0, new String[]{}}), "foobar0[]"); + assertEquals(hello.invoke(new MyService(), new Object[]{1, new String[]{"a"}}), "foobar1[a]"); + assertThrows(RuntimeException.class, () -> { + hello.invoke(null, new Object[]{1, "a"}); + }); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals(helloStatic.invoke(null, new Object[]{0, new String[]{"b"}}), "quux0[b]"); + assertEquals(helloStatic.invoke(null, new Object[]{1, new String[]{"c"}}), "quux1[c]"); + assertThrows(RuntimeException.class, () -> { + helloStatic.invoke(null, new Object[]{1, "a"}); + }); + } + + @ApplicationScoped + public static class MyService { + public String hello(int param1, String... param2) { + return "foobar" + param1 + Arrays.toString(param2); + } + + public static String helloStatic(int param1, String... param2) { + return "quux" + param1 + Arrays.toString(param2); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VoidMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VoidMethodInvokerTest.java new file mode 100644 index 000000000..a6839363e --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/VoidMethodInvokerTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertNull; + +@SpecVersion(spec = "cdi", version = "4.1") +public class VoidMethodInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(VoidMethodInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "m") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertNull(hello.invoke(service, new Object[]{1})); + assertNull(hello.invoke(new MyService(), new Object[]{2})); + + Invoker helloStatic = invokers.get("helloStatic"); + assertNull(helloStatic.invoke(null, new Object[]{3})); + } + + @ApplicationScoped + public static class MyService { + public void hello(int param) { + } + + public static void helloStatic(int param) { + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ZeroParametersInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ZeroParametersInvokerTest.java new file mode 100644 index 000000000..9705589bc --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/basic/ZeroParametersInvokerTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2024, 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.invokers.basic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ZeroParametersInvokerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ZeroParametersInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello", "helloStatic")); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.BEHAVIOR_OF_INVOKE, id = "h") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals(hello.invoke(service, null), "foobar"); + assertEquals(hello.invoke(new MyService(), new Object[]{}), "foobar"); + + Invoker helloStatic = invokers.get("helloStatic"); + assertEquals(helloStatic.invoke(null, null), "quux"); + assertEquals(helloStatic.invoke(null, new Object[]{}), "quux"); + } + + @ApplicationScoped + public static class MyService { + public String hello() { + return "foobar"; + } + + public static String helloStatic() { + return "quux"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ConstructorInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ConstructorInvokerTest.java new file mode 100644 index 000000000..d647c693d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ConstructorInvokerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ConstructorInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ConstructorInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + for (MethodInfo ctor : bean.declaringClass().constructors()) { + invokers.createInvoker(bean, ctor).build(); + } + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "bb") + public void trigger() { + } + + @ApplicationScoped + public static class MyService { + public MyService() { + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/InterceptorInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/InterceptorInvokerTest.java new file mode 100644 index 000000000..6a9d6cf01 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/InterceptorInvokerTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InterceptorInfo; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InterceptorBinding; +import jakarta.interceptor.InvocationContext; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InterceptorInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InterceptorInvokerTest.class) + .withClasses(MyInterceptorBinding.class, MyInterceptor.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyInterceptor.class) + public void myInterceptorRegistration(InterceptorInfo bean, InvokerFactory invokers) { + bean.declaringClass() + .methods() + .stream() + .filter(it -> "hello".equals(it.name())) + .forEach(it -> invokers.createInvoker(bean, it).build()); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "d") + public void trigger() { + } + + @Target({ElementType.TYPE, ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @InterceptorBinding + public @interface MyInterceptorBinding { + } + + @MyInterceptorBinding + @Interceptor + @Priority(1) + public static class MyInterceptor { + String hello() { + return "foobar"; + } + + @AroundInvoke + Object intercept(InvocationContext ctx) throws Exception { + return ctx.proceed(); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/MethodFromDifferentClassInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/MethodFromDifferentClassInvokerTest.java new file mode 100644 index 000000000..0b2fafe09 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/MethodFromDifferentClassInvokerTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Enhancement; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class MethodFromDifferentClassInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(MethodFromDifferentClassInvokerTest.class) + .withClasses(MyService.class, MyOtherService.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + private MethodInfo doSomething; + + @Enhancement(types = MyOtherService.class) + public void myOtherServiceEnhancement(MethodInfo method) { + if ("doSomething".equals(method.name())) { + doSomething = method; + } + } + + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + invokers.createInvoker(bean, doSomething).build(); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "bd") + public void trigger() { + } + + @ApplicationScoped + public static class MyService { + } + + @ApplicationScoped + public static class MyOtherService { + public void doSomething() { + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ObjectMethodButNotToStringInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ObjectMethodButNotToStringInvokerTest.java new file mode 100644 index 000000000..13ca2026d --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ObjectMethodButNotToStringInvokerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.enterprise.lang.model.declarations.MethodInfo; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ObjectMethodButNotToStringInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ObjectMethodButNotToStringInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + for (MethodInfo method : bean.declaringClass().superClassDeclaration().methods()) { + if ("hashCode".equals(method.name())) { + invokers.createInvoker(bean, method).build(); + } + } + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "bc") + public void trigger() { + } + + @ApplicationScoped + public static class MyService { + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/PrivateMethodInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/PrivateMethodInvokerTest.java new file mode 100644 index 000000000..8b4816a98 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/PrivateMethodInvokerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class PrivateMethodInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(PrivateMethodInvokerTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + bean.declaringClass() + .methods() + .stream() + .filter(it -> "hello".equals(it.name())) + .forEach(it -> invokers.createInvoker(bean, it).build()); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "ba") + public void trigger() { + } + + @ApplicationScoped + public static class MyService { + private String hello() { + return "foobar"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerFieldBeanInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerFieldBeanInvokerTest.java new file mode 100644 index 000000000..ee62bed28 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerFieldBeanInvokerTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ProducerFieldBeanInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ProducerFieldBeanInvokerTest.class) + .withClasses(MyService.class, MyProducer.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + bean.producerField() + .type() + .asClass() + .declaration() + .methods() + .stream() + .filter(it -> "hello".equals(it.name())) + .forEach(it -> invokers.createInvoker(bean, it).build()); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "cb") + public void trigger() { + } + + public static class MyService { + public String hello() { + return "foobar"; + } + } + + @ApplicationScoped + public static class MyProducer { + @Produces + public static MyService producer = new MyService(); + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerMethodBeanInvokerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerMethodBeanInvokerTest.java new file mode 100644 index 000000000..6aa68c2be --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/invalid/ProducerMethodBeanInvokerTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2024, 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.invokers.invalid; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.spi.DeploymentException; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ProducerMethodBeanInvokerTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ProducerMethodBeanInvokerTest.class) + .withClasses(MyService.class, MyProducer.class) + .withBuildCompatibleExtension(TestExtension.class) + .build(); + } + + public static class TestExtension implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + bean.producerMethod() + .returnType() + .asClass() + .declaration() + .methods() + .stream() + .filter(it -> "hello".equals(it.name())) + .forEach(it -> invokers.createInvoker(bean, it).build()); + } + } + + @Test + @SpecAssertion(section = Sections.BUILDING_INVOKER, id = "ca") + public void trigger() { + } + + public static class MyService { + public String hello() { + return "foobar"; + } + } + + @ApplicationScoped + public static class MyProducer { + @Produces + public static MyService produce() { + return new MyService(); + } + } +} diff --git a/impl/src/main/resources/tck-audit-cdi.xml b/impl/src/main/resources/tck-audit-cdi.xml index 1c604e548..2c60e0cf6 100644 --- a/impl/src/main/resources/tck-audit-cdi.xml +++ b/impl/src/main/resources/tck-audit-cdi.xml @@ -5908,6 +5908,168 @@ +
+ + + CDI-based frameworks often need to invoke application methods declared on managed beans. + Frameworks cannot invoke application methods directly, because they are not compiled against the application code. + However, during application deployment, frameworks may observe application methods through CDI extensions and build an |Invoker| for each relevant method. + The invokers can then be used at application runtime to invoke the methods indirectly. + + Basic test of method invokers + +
+ +
+ + The CDI container allows building an |Invoker| for a method of an enabled managed bean. + + + + Invalid target methods are: private methods, constructors, + methods declared on the |java.lang.Object| class, except of the |toString()| method, + methods that are not declared on the bean class of the target bean or inherited from its supertypes. + Attempting to build an invoker for an invalid target method leads to a deployment problem. + + + Test for private method + + + Test for constructor + + + Test for |java.lang.Object| method + + + Test for method from a different class + + + Test for public, protected and package-private methods + + + + When the target bean is not a managed bean, attempting to build an invoker leads to a deployment problem. + + Test for a producer method + + + Test for a producer field + + + + When the target bean is an interceptor, attempting to build an invoker leads to a deployment problem. + + + The only way to build an invoker is using the |InvokerBuilder|. + +
+ +
+ + Calling |invoke()| invokes the target method on given |instance| of the target bean, passing given |arguments|, and propagates back the return value or thrown exception. + + + The |instance| and |arguments| may be contextual or non-contextual objects. + + + A single invoker instance may be used to perform multiple, possibly concurrent, invocations of the target method, possibly on different instances of the target bean, possibly with different arguments. + + + Whenever a direct invocation of a method on an object is a business method invocation, an indirect invocation of that method on that object through an invoker is also a business method invocation. + +
+ +
+ + If the target method is |static|, the |instance| is ignored; by convention, it should be |null|. + + + If the target method is not |static| and |instance| is |null|, a |RuntimeException| is thrown. + + + If the target method is not |static| and the |instance| is not permissible for the target method, a |RuntimeException| is thrown. + + + The |instance| is permissible for the target method when: + + the |instance| is a contextual reference for the target bean and the bean type that declares the target method + + + the |instance| is a contextual reference for the target bean (regardless of the bean type) and the target method is declared on an interface that is present in the set of bean types of the target bean + + + the |instance| is a non-contextual object and the class of the |instance| declares the target method or inherits it from a supertype + + + + Correspondence between given |arguments| and declared parameters of the target method is positional: the Nth element of the |arguments| array is passed as the Nth argument to the target method. + + + If the target method is a variable arity method, the last element of the |arguments| array corresponds to the variable arity parameter (and therefore must be an array). + + + When passing an argument to the method, the applicable method invocation conversion is performed. + + + If the target method declares no parameter, |arguments| are ignored. + + + If the target method declares any parameter and |arguments| is |null|, |RuntimeException| is thrown. + + + If the |arguments| array has fewer elements than the number of parameters of the target method, |RuntimeException| is thrown. + + + If the |arguments| array has more elements than the number of parameters of the target method, the excess elements are ignored. + + + If a method invocation conversion does not exist from the class of some of the |arguments| (or from the null type if the argument is |null|) to the declared type of the corresponding parameter of the target method, |RuntimeException| is thrown. + + + If the target method returns normally, its return value is returned (after boxing conversion if the target method's return type is a primitive type), unless the target method is declared |void|, in which case |null| is returned. + + + If the target method throws an exception, it is rethrown directly. + +
+ +
+ + + |InvokerBuilder| can be obtained in build compatible extensions from |InvokerFactory.createInvoker()|. + An |InvokerFactory| may be declared as a parameter of |@Registration| extension methods. + + The target bean of the created invoker is the bean represented by the |BeanInfo| object passed to |createInvoker()|. + The target method of the created invoker is the method represented by the |MethodInfo| object passed to |createInvoker()|. + + Calling |InvokerBuilder.build()| produces an opaque token (|InvokerInfo|) that can be passed as a parameter to a |SyntheticBeanBuilder| or |SyntheticObserverBuilder| and materializes as an |Invoker| at application runtime. + + Basic test of method invokers. + +
+ +
+
+ +
+ + When the target bean is a decorator, attempting to build an invoker leads to a deployment problem. + +
+ +
+ + + |InvokerBuilder| can be obtained in portable extensions from |ProcessManagedBean.createInvoker()|. + + The target bean of the created invoker is the bean for which the |ProcessManagedBean| event was fired. + The target method of the created invoker is the method represented by the |AnnotatedMethod| object passed to |createInvoker()|. + + Calling |InvokerBuilder.build()| produces an |Invoker| which should be stored for usage at application runtime. + + +
+
From 931215dd4ea6cbc9aefc2109c825d4b02156f449 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Mon, 29 Jan 2024 10:56:54 +0100 Subject: [PATCH 2/3] initial TCK tests for invoker lookups --- .../invokers/InvokerHolderExtensionBase.java | 13 +- .../ArgumentArraySizeWithLookupTest.java | 110 +++++++++++++++ .../lookup/ArgumentLookupBeanManagerTest.java | 132 ++++++++++++++++++ .../lookup/ArgumentLookupDependentTest.java | 112 +++++++++++++++ .../lookup/ArgumentLookupEventTest.java | 96 +++++++++++++ .../lookup/ArgumentLookupInstanceTest.java | 114 +++++++++++++++ .../invokers/lookup/ArgumentLookupTest.java | 110 +++++++++++++++ ...gumentLookupEqualToNumberOfParamsTest.java | 83 +++++++++++ ...ntLookupGreaterThanNumberOfParamsTest.java | 83 +++++++++++ .../BadArgumentLookupLessThanZeroTest.java | 83 +++++++++++ .../lookup/InstanceLookupDependentTest.java | 104 ++++++++++++++ .../InstanceLookupStaticMethodTest.java | 101 ++++++++++++++ .../invokers/lookup/InstanceLookupTest.java | 103 ++++++++++++++ .../invokers/lookup/LookupAmbiguousTest.java | 98 +++++++++++++ .../lookup/LookupUnsatisfiedTest.java | 81 +++++++++++ impl/src/main/resources/tck-audit-cdi.xml | 84 +++++++++++ 16 files changed, 1506 insertions(+), 1 deletion(-) create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentArraySizeWithLookupTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupBeanManagerTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupDependentTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupEventTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupInstanceTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupEqualToNumberOfParamsTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupGreaterThanNumberOfParamsTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupLessThanZeroTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupDependentTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupStaticMethodTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupAmbiguousTest.java create mode 100644 impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupUnsatisfiedTest.java diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java index e627811b3..61880508f 100644 --- a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/InvokerHolderExtensionBase.java @@ -19,20 +19,31 @@ import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.InvokerBuilder; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; public abstract class InvokerHolderExtensionBase { private final Map invokers = new LinkedHashMap<>(); protected final void registerInvokers(BeanInfo bean, InvokerFactory invokers, Set methods) { + registerInvokers(bean, invokers, methods, builder -> {}); + } + + protected final void registerInvokers(BeanInfo bean, InvokerFactory invokers, Set methods, + Consumer> action) { bean.declaringClass() .methods() .stream() .filter(it -> methods.contains(it.name())) - .forEach(it -> registerInvoker(it.name(), invokers.createInvoker(bean, it).build())); + .forEach(it -> { + InvokerBuilder builder = invokers.createInvoker(bean, it); + action.accept(builder); + registerInvoker(it.name(), builder.build()); + }); } protected final void registerInvoker(String id, InvokerInfo invoker) { diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentArraySizeWithLookupTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentArraySizeWithLookupTest.java new file mode 100644 index 000000000..f49711094 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentArraySizeWithLookupTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentArraySizeWithLookupTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentArraySizeWithLookupTest.class) + .withClasses(MyService.class, MyDependency1.class, MyDependency2.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder + .withArgumentLookup(0) + .withArgumentLookup(1)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "f") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + assertThrows(RuntimeException.class, () -> { + invoker.invoke(service, null); + }); + assertThrows(RuntimeException.class, () -> { + invoker.invoke(service, new Object[]{}); + }); + assertThrows(RuntimeException.class, () -> { + invoker.invoke(service, new Object[]{null}); + }); + assertEquals("foobar_1_2", invoker.invoke(service, new Object[]{null, null})); + assertEquals("foobar_1_2", invoker.invoke(service, new Object[]{null, null, null})); + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency1 dependency1, MyDependency2 dependency2) { + return "foobar_" + dependency1 + "_" + dependency2; + } + } + + @Dependent + static class MyDependency1 { + @Override + public String toString() { + return "1"; + } + } + + @Dependent + static class MyDependency2 { + @Override + public String toString() { + return "2"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupBeanManagerTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupBeanManagerTest.java new file mode 100644 index 000000000..39fe38550 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupBeanManagerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.util.TypeLiteral; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentLookupBeanManagerTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentLookupBeanManagerTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "de") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "i") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + assertEquals("foobar0", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar1", invoker.invoke(service, new Object[]{null})); + + assertEquals(MyService.observed, List.of("foo", "bar", "foo", "bar")); + + assertEquals(2, MyDependency.CREATED); + assertEquals(2, MyDependency.DESTROYED); + } + + @ApplicationScoped + static class MyService { + static final List observed = new ArrayList<>(); + + public String hello(BeanManager beanManager) { + Instance instance = beanManager.createInstance(); + MyDependency dependency = instance.select(MyDependency.class).get(); + int id = dependency.getId(); + instance.destroy(dependency); + + beanManager.getEvent().select(new TypeLiteral>() {}).fire(List.of("foo", "bar")); + + return "foobar" + id; + } + + public void observe(@Observes List event) { + observed.addAll(event); + } + } + + @Dependent + static class MyDependency { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public int getId() { + return id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupDependentTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupDependentTest.java new file mode 100644 index 000000000..80c7e10dc --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupDependentTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentLookupDependentTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentLookupDependentTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "db") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "i") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + assertEquals("foobar0", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar1", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar2", invoker.invoke(service, new Object[]{null})); + assertEquals(3, MyDependency.CREATED); + assertEquals(3, MyDependency.DESTROYED); + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + @Dependent + static class MyDependency { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public int getId() { + return id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupEventTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupEventTest.java new file mode 100644 index 000000000..65692d270 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupEventTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.event.Event; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentLookupEventTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentLookupEventTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "dd") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + invoker.invoke(service, new Object[]{null}); + invoker.invoke(service, new Object[]{null}); + assertEquals(MyService.observed, List.of("foo", "bar", "foo", "bar")); + } + + @ApplicationScoped + static class MyService { + static final List observed = new ArrayList<>(); + + public void hello(Event> event) { + event.fire(List.of("foo", "bar")); + } + + public void observe(@Observes List event) { + observed.addAll(event); + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupInstanceTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupInstanceTest.java new file mode 100644 index 000000000..e85682b42 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupInstanceTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Instance; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentLookupInstanceTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentLookupInstanceTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "dc") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "i") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + assertEquals("foobar0_MyDependency", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar1_MyDependency", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar2_MyDependency", invoker.invoke(service, new Object[]{null})); + assertEquals(3, MyDependency.CREATED); + assertEquals(3, MyDependency.DESTROYED); + } + + @ApplicationScoped + static class MyService { + public String hello(Instance instance) { + String beanClass = instance.getHandle().getBean().getBeanClass().getSimpleName(); + MyDependency dependency = instance.get(); + return "foobar" + dependency.getId() + "_" + beanClass; + } + } + + @Dependent + static class MyDependency { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public int getId() { + return id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupTest.java new file mode 100644 index 000000000..7e3e8f2d7 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/ArgumentLookupTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class ArgumentLookupTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(ArgumentLookupTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "da") + public void test(MyService service, InvokerHolder invokers) throws Exception { + Invoker invoker = invokers.get("hello"); + assertEquals("foobar0", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar0", invoker.invoke(service, new Object[]{null})); + assertEquals("foobar0", invoker.invoke(service, new Object[]{null})); + assertEquals(1, MyDependency.CREATED); + assertEquals(0, MyDependency.DESTROYED); + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + @ApplicationScoped + static class MyDependency { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public int getId() { + return id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupEqualToNumberOfParamsTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupEqualToNumberOfParamsTest.java new file mode 100644 index 000000000..05c5fef7c --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupEqualToNumberOfParamsTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +@SpecVersion(spec = "cdi", version = "4.1") +public class BadArgumentLookupEqualToNumberOfParamsTest extends AbstractTest { + @Deployment + @ShouldThrowException(IllegalArgumentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(BadArgumentLookupEqualToNumberOfParamsTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers, Messages msg) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> { + try { + builder.withArgumentLookup(1); + } catch (IllegalArgumentException expected) { + msg.error(expected); + } + }); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "ec") + public void trigger() { + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + @ApplicationScoped + static class MyDependency { + public int getId() { + return 0; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupGreaterThanNumberOfParamsTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupGreaterThanNumberOfParamsTest.java new file mode 100644 index 000000000..499e0d0a9 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupGreaterThanNumberOfParamsTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +@SpecVersion(spec = "cdi", version = "4.1") +public class BadArgumentLookupGreaterThanNumberOfParamsTest extends AbstractTest { + @Deployment + @ShouldThrowException(IllegalArgumentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(BadArgumentLookupGreaterThanNumberOfParamsTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers, Messages msg) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> { + try { + builder.withArgumentLookup(2); + } catch (IllegalArgumentException expected) { + msg.error(expected); + } + }); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "eb") + public void trigger() { + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + @ApplicationScoped + static class MyDependency { + public int getId() { + return 0; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupLessThanZeroTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupLessThanZeroTest.java new file mode 100644 index 000000000..37f312600 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/BadArgumentLookupLessThanZeroTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Messages; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +@SpecVersion(spec = "cdi", version = "4.1") +public class BadArgumentLookupLessThanZeroTest extends AbstractTest { + @Deployment + @ShouldThrowException(IllegalArgumentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(BadArgumentLookupLessThanZeroTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers, Messages msg) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> { + try { + builder.withArgumentLookup(-1); + } catch (IllegalArgumentException expected) { + msg.error(expected); + } + }); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "ea") + public void trigger() { + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + @ApplicationScoped + static class MyDependency { + public int getId() { + return 0; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupDependentTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupDependentTest.java new file mode 100644 index 000000000..2e5b06b87 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupDependentTest.java @@ -0,0 +1,104 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InstanceLookupDependentTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InstanceLookupDependentTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), InvokerBuilder::withInstanceLookup); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "bb") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "i") + public void test(InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals("foobar0", hello.invoke(null, null)); + assertEquals("foobar1", hello.invoke(null, null)); + assertEquals("foobar2", hello.invoke(null, null)); + assertEquals(3, MyService.CREATED); + assertEquals(3, MyService.DESTROYED); + } + + @Dependent + static class MyService { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public String hello() { + return "foobar" + id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupStaticMethodTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupStaticMethodTest.java new file mode 100644 index 000000000..911c412f1 --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupStaticMethodTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InstanceLookupStaticMethodTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InstanceLookupStaticMethodTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), InvokerBuilder::withInstanceLookup); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "c") + public void test(InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals("foobar", hello.invoke(null, null)); + assertEquals("foobar", hello.invoke(null, null)); + assertEquals("foobar", hello.invoke(null, null)); + assertEquals(0, MyService.CREATED); + assertEquals(0, MyService.DESTROYED); + } + + @ApplicationScoped + static class MyService { + static int CREATED = 0; + + static int DESTROYED = 0; + + @PostConstruct + public void init() { + CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public static String hello() { + return "foobar"; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupTest.java new file mode 100644 index 000000000..12a45d37b --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/InstanceLookupTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.invoke.Invoker; +import jakarta.enterprise.invoke.InvokerBuilder; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +import static org.testng.Assert.assertEquals; + +@SpecVersion(spec = "cdi", version = "4.1") +public class InstanceLookupTest extends AbstractTest { + @Deployment + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(InstanceLookupTest.class) + .withClasses(MyService.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), InvokerBuilder::withInstanceLookup); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test(dataProvider = ARQUILLIAN_DATA_PROVIDER) + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "a") + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "ba") + public void test(InvokerHolder invokers) throws Exception { + Invoker hello = invokers.get("hello"); + assertEquals("foobar0", hello.invoke(null, null)); + assertEquals("foobar0", hello.invoke(null, null)); + assertEquals("foobar0", hello.invoke(null, null)); + assertEquals(1, MyService.CREATED); + assertEquals(0, MyService.DESTROYED); + } + + @ApplicationScoped + static class MyService { + static int CREATED = 0; + + static int DESTROYED = 0; + + private int id; + + @PostConstruct + public void init() { + this.id = CREATED++; + } + + @PreDestroy + public void destroy() { + DESTROYED++; + } + + public String hello() { + return "foobar" + id; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupAmbiguousTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupAmbiguousTest.java new file mode 100644 index 000000000..cbd5c477a --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupAmbiguousTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.inject.spi.DeploymentException; +import jakarta.inject.Singleton; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +@SpecVersion(spec = "cdi", version = "4.1") +public class LookupAmbiguousTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(LookupAmbiguousTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "gb") + public void trigger() { + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + interface MyDependency { + int getId(); + } + + @ApplicationScoped + static class MyDependency1 implements MyDependency { + @Override + public int getId() { + return 1; + } + } + + @ApplicationScoped + static class MyDependency2 implements MyDependency { + @Override + public int getId() { + return 2; + } + } +} diff --git a/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupUnsatisfiedTest.java b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupUnsatisfiedTest.java new file mode 100644 index 000000000..654423b0f --- /dev/null +++ b/impl/src/main/java/org/jboss/cdi/tck/tests/invokers/lookup/LookupUnsatisfiedTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024, 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.invokers.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.build.compatible.spi.BeanInfo; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.InvokerFactory; +import jakarta.enterprise.inject.build.compatible.spi.Registration; +import jakarta.enterprise.inject.build.compatible.spi.Synthesis; +import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents; +import jakarta.enterprise.inject.spi.DeploymentException; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.ShouldThrowException; +import org.jboss.cdi.tck.AbstractTest; +import org.jboss.cdi.tck.cdi.Sections; +import org.jboss.cdi.tck.shrinkwrap.WebArchiveBuilder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolder; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderCreator; +import org.jboss.cdi.tck.tests.invokers.InvokerHolderExtensionBase; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.test.audit.annotations.SpecAssertion; +import org.jboss.test.audit.annotations.SpecVersion; +import org.testng.annotations.Test; + +import java.util.Set; + +@SpecVersion(spec = "cdi", version = "4.1") +public class LookupUnsatisfiedTest extends AbstractTest { + @Deployment + @ShouldThrowException(DeploymentException.class) + public static WebArchive createTestArchive() { + return new WebArchiveBuilder() + .withTestClass(LookupUnsatisfiedTest.class) + .withClasses(MyService.class, MyDependency.class) + .withBuildCompatibleExtension(TestExtension.class) + .withClasses(InvokerHolder.class, InvokerHolderCreator.class, InvokerHolderExtensionBase.class) + .build(); + } + + public static class TestExtension extends InvokerHolderExtensionBase implements BuildCompatibleExtension { + @Registration(types = MyService.class) + public void myServiceRegistration(BeanInfo bean, InvokerFactory invokers) { + registerInvokers(bean, invokers, Set.of("hello"), builder -> builder.withArgumentLookup(0)); + } + + @Synthesis + public void synthesis(SyntheticComponents syn) { + synthesizeInvokerHolder(syn); + } + } + + @Test + @SpecAssertion(section = Sections.CONFIGURING_LOOKUPS, id = "ga") + public void trigger() { + } + + @ApplicationScoped + static class MyService { + public String hello(MyDependency dependency) { + return "foobar" + dependency.getId(); + } + } + + interface MyDependency { + int getId(); + } +} diff --git a/impl/src/main/resources/tck-audit-cdi.xml b/impl/src/main/resources/tck-audit-cdi.xml index 2c60e0cf6..8c4ac59c1 100644 --- a/impl/src/main/resources/tck-audit-cdi.xml +++ b/impl/src/main/resources/tck-audit-cdi.xml @@ -6048,6 +6048,90 @@ +
+ + The |InvokerBuilder| allows specifying that the |instance| or any of the |arguments| passed to |Invoker.invoke()| should be ignored and a value should be looked up from the CDI container instead. + + + When |withInstanceLookup()| is called on an invoker builder and the target method is not |static|, the |invoke()| method of the built invoker shall ignore the |instance| argument and instead obtain and use a contextual reference for the target bean and the bean type that declares the target method. + + Test with target bean that is |@ApplicationScoped| + + + Test with target bean that is |@Dependent| + + + + Calling |withInstanceLookup()| on an invoker builder for a |static| target method has no effect. + + + + When |withArgumentLookup()| is called on an invoker builder, the |invoke()| method of the built invoker shall ignore the given element of the |arguments| array and instead: + + 1. identify a bean according to the rules of typesafe resolution, as defined in `Performing typesafe resolution`, where the required type is the declared type of the corresponding parameter of the target method and the required qualifiers are all qualifiers present on the parameter, resolving ambiguities according to `Unsatisfied and ambiguous dependencies`; + 2. obtain and use a contextual reference for the identified bean and the declared type of the parameter. + + + Test with parameter that resolves to an |@ApplicationScoped| bean + + + Test with parameter that resolves to a |@Dependent| bean + + + Test with parameter that resolves to an |Instance| bean + + + Test with parameter that resolves to an |Event| bean + + + Test with parameter that resolves to a |BeanManager| bean + + + + Calling |withArgumentLookup()| with |position| less than 0 or greater than or equal to the number of parameters of the target method leads to an |IllegalArgumentException|. + + Test for position less than zero + + + Test for position greater than the number of parameters + + + Test for position equal to the number of parameters + + + + + Configuring a lookup using |withInstanceLookup()| or |withArgumentLookup()| does not relax the requirements defined in `Behavior of |invoke()|`. + Notably, the |arguments| array must still have an element for each argument, regardless of whether a lookup was configured for it. + This means that for a target method with N parameters, the |arguments| array must always have at least N elements. + + + + + During deployment validation, implementations are required to identify all looked up beans for all built invokers, as described above. + It is a deployment problem if an attempt to identify a looked up bean results in an unsatisfied dependency or an ambiguous dependency that is not resolvable. + + + Test for unsatisfied lookup + + + Test for unresolvable ambiguous lookup + + + + Implementations are permitted to remember the identified beans and not repeat the resolution process for each invocation of |Invoker.invoke()|. + + + All instances of |@Dependent| looked up beans obtained during |Invoker.invoke()| are destroyed before the |invoke()| method returns or throws. + + + The order in which the instances of |@Dependent| looked up beans are destroyed is not specified. + + + The order in which instances of looked up beans are obtained during |Invoker.invoke()| in not specified. + +
+
From e14c22c6d770566184f948395f30c86726ab18d1 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Wed, 17 Jan 2024 16:57:15 +0100 Subject: [PATCH 3/3] synchronize CDI TCK audit XML in 'web' from 'impl' --- web/src/main/resources/tck-audit-cdi.xml | 524 ++++++++++++++++++++++- 1 file changed, 516 insertions(+), 8 deletions(-) diff --git a/web/src/main/resources/tck-audit-cdi.xml b/web/src/main/resources/tck-audit-cdi.xml index 50fc7cdc3..8c4ac59c1 100644 --- a/web/src/main/resources/tck-audit-cdi.xml +++ b/web/src/main/resources/tck-audit-cdi.xml @@ -377,8 +377,8 @@ - If there are two different stereotypes declared by the bean that declare different default scopes, then there is no default scope and the bean - must explicitly declare a scope. If it does not explicitly declare a scope, the container automatically + If there are two different stereotypes present on the bean, directly, indirectly, or transitively, that declare different default scopes, + then there is no default scope and the bean must explicitly declare a scope. If it does not explicitly declare a scope, the container automatically detects the problem and treats it as a definition error. @@ -723,6 +723,20 @@ +
+ + A stereotype may declare a @Priority annotation which functions as a means of enabling and ordering affected beans. + + + + If there are two different stereotypes present on a bean, directly, indirectly, or transitively, that declare + different priority values, then the bean must explicitly declare a @Priority annotation. If the bean does not + explicitly declare priority, the container automatically detects the problem and treats it as a definition error. + + + +
+
A stereotype may declare other stereotypes. @@ -3282,6 +3296,7 @@ The method |isResolvable()| returns true if there is exactly one bean found, or false otherwise. + @@ -3302,6 +3317,60 @@ + + The |getHandle()| method must: + + Return an initialized contextual reference |Handle| for a bean that has the required type and qualifiers + and is eligible for injection. The contextual reference must be resolved lazily, i.e. when first needed. + + + + Throw UnsatisfiedResolutionException if there is no bean with given type and qualifiers. + + + Throw AmbiguousResolutionException if there is more than one bean given type and qualifiers. + + + + + + The |handles()| method must: + + Allow iterating over contextual reference handles for all beans that have the required type and required qualifiers and are eligible for injection. + + + + Return stateless Iterable. Therefore, each Iterable#iterator() produces a new set of handles. + + + +
+ +
+ + The get() method returns a contextual reference object. + + The contextual reference is resolved lazily. + + + Test IllegalStateException is thrown if invoked on Handle that previously successfully destroyed its underlying contextual reference. + + + + + The destroy() method destroys the contextual instance and is a no-op if: + + + called multiple times + + + the producing Instance does not exist + the handle does not hold a contextual reference, i.e. get() was never called + + + the handle does not hold a contextual reference, i.e. get() was never called + +
@@ -5108,6 +5177,13 @@ + + The Priority annotation can be used to enable and order interceptors associated with components that use interceptor bindings. + The required value element of the Priority annotation determines the ordering. + Interceptors with smaller priority values are called first. + This is defined in the Interceptors 2.0 spec, 5.2.1. Use of the Priority Annotation in Ordering Interceptors. + +
@@ -5327,7 +5403,7 @@ The built-in implementation must be a passivation capable dependency, as defined in Section 6.6.2, "Passivation capable - dependencies". + dependencies (CDI Full)".
@@ -5726,16 +5802,17 @@ -
+
- If an event is asynchronous, and an exception is thrown by any of its notified observers, the CompletionStage returned by fireAsync will - complete exceptionally with java.util.concurrent.CompletionException exception. + If an event is asynchronous, and an exception is thrown by one or more of its notified observers, the + `CompletionStage` returned by `fireAsync` will complete exceptionally with + `java.util.concurrent.CompletionException`. java.util.concurrent.CompletionException contains all exceptions thrown by observers as suppressed exceptions. They can be accessed as an - array of throwable with the getSuppressed method. + array of `Throwable` with the `getSuppressed` method.
@@ -5795,6 +5872,414 @@
+
+ +
+ + + Implementations are required to fire a startup event during application initialization. + + This must be done synchronously with an event payload of jakarta.enterprise.event.Startup and qualifier jakarta.enterprise.inject.Any + + + + This event is fired after the event with qualifier @Initialized(ApplicationScope.class) but before processing requests. + + + + Applications must never manually fire any events with payload type jakarta.enterprise.event.Startup. + +
+ +
+ + + Implementations are required to fire a shutdown event during application shutdown. + + This must be done synchronously with an event payload of jakarta.enterprise.event.Shutdown and qualifier jakarta.enterprise.inject.Any. + + + + This event is fired during CDI container shutdown but not later than the event with qualifier @BeforeDestroyed(ApplicationScoped.class). + + + + Applications must never manually fire any events with payload type jakarta.enterprise.event.Shutdown. + +
+ +
+ + + CDI-based frameworks often need to invoke application methods declared on managed beans. + Frameworks cannot invoke application methods directly, because they are not compiled against the application code. + However, during application deployment, frameworks may observe application methods through CDI extensions and build an |Invoker| for each relevant method. + The invokers can then be used at application runtime to invoke the methods indirectly. + + Basic test of method invokers + +
+ +
+ + The CDI container allows building an |Invoker| for a method of an enabled managed bean. + + + + Invalid target methods are: private methods, constructors, + methods declared on the |java.lang.Object| class, except of the |toString()| method, + methods that are not declared on the bean class of the target bean or inherited from its supertypes. + Attempting to build an invoker for an invalid target method leads to a deployment problem. + + + Test for private method + + + Test for constructor + + + Test for |java.lang.Object| method + + + Test for method from a different class + + + Test for public, protected and package-private methods + + + + When the target bean is not a managed bean, attempting to build an invoker leads to a deployment problem. + + Test for a producer method + + + Test for a producer field + + + + When the target bean is an interceptor, attempting to build an invoker leads to a deployment problem. + + + The only way to build an invoker is using the |InvokerBuilder|. + +
+ +
+ + Calling |invoke()| invokes the target method on given |instance| of the target bean, passing given |arguments|, and propagates back the return value or thrown exception. + + + The |instance| and |arguments| may be contextual or non-contextual objects. + + + A single invoker instance may be used to perform multiple, possibly concurrent, invocations of the target method, possibly on different instances of the target bean, possibly with different arguments. + + + Whenever a direct invocation of a method on an object is a business method invocation, an indirect invocation of that method on that object through an invoker is also a business method invocation. + +
+ +
+ + If the target method is |static|, the |instance| is ignored; by convention, it should be |null|. + + + If the target method is not |static| and |instance| is |null|, a |RuntimeException| is thrown. + + + If the target method is not |static| and the |instance| is not permissible for the target method, a |RuntimeException| is thrown. + + + The |instance| is permissible for the target method when: + + the |instance| is a contextual reference for the target bean and the bean type that declares the target method + + + the |instance| is a contextual reference for the target bean (regardless of the bean type) and the target method is declared on an interface that is present in the set of bean types of the target bean + + + the |instance| is a non-contextual object and the class of the |instance| declares the target method or inherits it from a supertype + + + + Correspondence between given |arguments| and declared parameters of the target method is positional: the Nth element of the |arguments| array is passed as the Nth argument to the target method. + + + If the target method is a variable arity method, the last element of the |arguments| array corresponds to the variable arity parameter (and therefore must be an array). + + + When passing an argument to the method, the applicable method invocation conversion is performed. + + + If the target method declares no parameter, |arguments| are ignored. + + + If the target method declares any parameter and |arguments| is |null|, |RuntimeException| is thrown. + + + If the |arguments| array has fewer elements than the number of parameters of the target method, |RuntimeException| is thrown. + + + If the |arguments| array has more elements than the number of parameters of the target method, the excess elements are ignored. + + + If a method invocation conversion does not exist from the class of some of the |arguments| (or from the null type if the argument is |null|) to the declared type of the corresponding parameter of the target method, |RuntimeException| is thrown. + + + If the target method returns normally, its return value is returned (after boxing conversion if the target method's return type is a primitive type), unless the target method is declared |void|, in which case |null| is returned. + + + If the target method throws an exception, it is rethrown directly. + +
+ +
+ + + |InvokerBuilder| can be obtained in build compatible extensions from |InvokerFactory.createInvoker()|. + An |InvokerFactory| may be declared as a parameter of |@Registration| extension methods. + + The target bean of the created invoker is the bean represented by the |BeanInfo| object passed to |createInvoker()|. + The target method of the created invoker is the method represented by the |MethodInfo| object passed to |createInvoker()|. + + Calling |InvokerBuilder.build()| produces an opaque token (|InvokerInfo|) that can be passed as a parameter to a |SyntheticBeanBuilder| or |SyntheticObserverBuilder| and materializes as an |Invoker| at application runtime. + + Basic test of method invokers. + +
+ +
+ + The |InvokerBuilder| allows specifying that the |instance| or any of the |arguments| passed to |Invoker.invoke()| should be ignored and a value should be looked up from the CDI container instead. + + + When |withInstanceLookup()| is called on an invoker builder and the target method is not |static|, the |invoke()| method of the built invoker shall ignore the |instance| argument and instead obtain and use a contextual reference for the target bean and the bean type that declares the target method. + + Test with target bean that is |@ApplicationScoped| + + + Test with target bean that is |@Dependent| + + + + Calling |withInstanceLookup()| on an invoker builder for a |static| target method has no effect. + + + + When |withArgumentLookup()| is called on an invoker builder, the |invoke()| method of the built invoker shall ignore the given element of the |arguments| array and instead: + + 1. identify a bean according to the rules of typesafe resolution, as defined in `Performing typesafe resolution`, where the required type is the declared type of the corresponding parameter of the target method and the required qualifiers are all qualifiers present on the parameter, resolving ambiguities according to `Unsatisfied and ambiguous dependencies`; + 2. obtain and use a contextual reference for the identified bean and the declared type of the parameter. + + + Test with parameter that resolves to an |@ApplicationScoped| bean + + + Test with parameter that resolves to a |@Dependent| bean + + + Test with parameter that resolves to an |Instance| bean + + + Test with parameter that resolves to an |Event| bean + + + Test with parameter that resolves to a |BeanManager| bean + + + + Calling |withArgumentLookup()| with |position| less than 0 or greater than or equal to the number of parameters of the target method leads to an |IllegalArgumentException|. + + Test for position less than zero + + + Test for position greater than the number of parameters + + + Test for position equal to the number of parameters + + + + + Configuring a lookup using |withInstanceLookup()| or |withArgumentLookup()| does not relax the requirements defined in `Behavior of |invoke()|`. + Notably, the |arguments| array must still have an element for each argument, regardless of whether a lookup was configured for it. + This means that for a target method with N parameters, the |arguments| array must always have at least N elements. + + + + + During deployment validation, implementations are required to identify all looked up beans for all built invokers, as described above. + It is a deployment problem if an attempt to identify a looked up bean results in an unsatisfied dependency or an ambiguous dependency that is not resolvable. + + + Test for unsatisfied lookup + + + Test for unresolvable ambiguous lookup + + + + Implementations are permitted to remember the identified beans and not repeat the resolution process for each invocation of |Invoker.invoke()|. + + + All instances of |@Dependent| looked up beans obtained during |Invoker.invoke()| are destroyed before the |invoke()| method returns or throws. + + + The order in which the instances of |@Dependent| looked up beans are destroyed is not specified. + + + The order in which instances of looked up beans are obtained during |Invoker.invoke()| in not specified. + +
+ +
+
+ +
+ + When the target bean is a decorator, attempting to build an invoker leads to a deployment problem. + +
+ +
+ + + |InvokerBuilder| can be obtained in portable extensions from |ProcessManagedBean.createInvoker()|. + + The target bean of the created invoker is the bean for which the |ProcessManagedBean| event was fired. + The target method of the created invoker is the method represented by the |AnnotatedMethod| object passed to |createInvoker()|. + + Calling |InvokerBuilder.build()| produces an |Invoker| which should be stored for usage at application runtime. + + +
+ + +
+ + The container provides a built-in bean with bean type |BeanContainer|, scope |@Dependent| and qualifier |@Default|. + + + Test the bean type. + + + + Test the scope. + + + + Test the qualifier. + + +
+ +
+
+ +
+ + A build compatible extension is a service provider of the jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension interface, declared in META-INF/services. + + + The invocation order for extension methods may be controlled using the @Priority annotation. If an extension + method does not have the @Priority annotation, the default priority jakarta.interceptor.Interceptor.Priority.APPLICATION + 500 is assumed. + If two extension methods have equal priority, the ordering between them is undefined. Note that priority only affects + order of extension methods in a single phase. + + + At deployment time, CDI container does not have to be running, so calling CDI.current() from an extension + method, or attempting to access a running CDI container in any other way, results in non-portable behavior. + +
+ +
+ + Test that discovery phase changes are seen + + + Test that classes with bean defining annotations not added to scan are not seen in non-bean archives + + + Test that classes added to scan are seen in non-bean archives + +
+
+ + Extension methods annotated @Enhancement must declare exactly one parameter of one of the following types: + ClassConfig or ClassInfo + MethodConfig or MethodInfo + FieldConfig or FieldInfo + + + Test that a method with none of these parameters fails deployment. + + + + Test that a method with more than one of these parameters fails deployment. + + + + Test that a method with more than one of these parameters fails deployment. + + + + Test that enhancment phase annotation changes are seen + + + When an extension method declares a parameter of type ClassConfig or ClassInfo, it will be called for each + discovered class matching the criteria defined on the @Enhancement annotation + +
+
+ + Extension methods annotated @Registration must declare exactly one parameter of one of the following types: + BeanInfo + InterceptorInfo + ObserverInfo + + + Test that a method with none of these parameters fails deployment. + + + + Test that a method with more than one of these parameters fails deployment. + + + When an extension method declares a parameter of type BeanInfo, it will be called for each bean whose set + of bean types matches the criteria defined on the @Registration annotation. + + + + When an extension method declares a parameter of type ObserverInfo, it will be called for each observer + whose observed event type matches the criteria defined on the @Registration annotation. + + + + + Test that enhancment phase annotation changes are seen + +
+
+ + Test that synthesis phase beans are availalble for use by runtime + + + Test that synthesis observers are notified of fired events + +
+
+ + Test that validation phase controls test outcome + +
+ + +
+
+
A portable extension may integrate with the container by providing its own beans, interceptors and decorators to the container. @@ -5951,6 +6436,10 @@ An instance of |ObserverMethod| exists for every observer method of every enabled bean. + + + |getDeclaringBean()| returns the Bean object that declares the observer method. Return value is undefined for synthetic observers. +
@@ -6587,6 +7076,14 @@
+
+ + The method `BeanContainer.getContexts()` retrieves all context objects, active and inactive, + associated with the given scope, as defined in Section 2.5, "Scopes and contexts". + + +
+
The method |BeanManager.getELResolver()| returns the |jakarta.el.ELResolver| specified in Section 12.4, "Integration with Unified EL". @@ -7242,6 +7739,14 @@ interfaces. + + + As these lifecycle events are fired, the container must also execute build compatible extensions. Which phase + of build compatible extensions should be executed when is indicated in the description of the corresponding + lifecycle events. Build compatible extensions annotated @SkipIfPortableExtensionPresent must be ignored in + CDI Full, if given portable extension is present. + +
@@ -7543,6 +8048,9 @@ Set a callback to destroy a bean instance with destroyWith() or disposeWith() method. + + Set the priority of the bean, if it is an alternative, with priority() method. + If a |BeanConfigurator| has no scope specified, the default scope rules, defined in the Default Scope rules apply. @@ -8523,7 +9031,7 @@ |bean-discovery-mode| of |all|, or with no version number, or that is an empty file. - Test an archive which contains a |beans.xml| file with a version number of 1.1, with the |bean-discovery-mode| of |all|. + Test an archive which contains a |beans.xml| file with a version number of 1.1 (or later), with the |bean-discovery-mode| of |all|. Test an archive which contains a |beans.xml| file with no version number.