From e8f2aee5236c48dcaa5adcb946cd23c80b6838b9 Mon Sep 17 00:00:00 2001 From: Jiyang Zhang <33189384+JiyangZhang@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:21:43 -0500 Subject: [PATCH 1/5] Add new exceptional tests (#541) --- .../extension/PropertiesParserTestCase.java | 10 +++++++++ .../servlet/BaseServletProtocolTestCase.java | 10 +++++++++ .../ServletCommandServiceTestCase.java | 21 +++++++++++++++++++ ...letProtocolDeploymentPackagerTestCase.java | 5 +++++ 4 files changed, 46 insertions(+) diff --git a/config/impl-base/src/test/java/org/jboss/arquillian/config/impl/extension/PropertiesParserTestCase.java b/config/impl-base/src/test/java/org/jboss/arquillian/config/impl/extension/PropertiesParserTestCase.java index 34ca67e4e..d9fab4230 100644 --- a/config/impl-base/src/test/java/org/jboss/arquillian/config/impl/extension/PropertiesParserTestCase.java +++ b/config/impl-base/src/test/java/org/jboss/arquillian/config/impl/extension/PropertiesParserTestCase.java @@ -468,6 +468,16 @@ public String get() { }); } + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfDescriptorIsNull() { + new PropertiesParser().addProperties(null, System.getProperties()); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfPropertiesIsNull() { + new PropertiesParser().addProperties(desc, null); + } + private void validate(String property, String value, ValueCallback callback) { validate(property, value, value, callback); } diff --git a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/BaseServletProtocolTestCase.java b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/BaseServletProtocolTestCase.java index c7f8464be..bcbf4c077 100644 --- a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/BaseServletProtocolTestCase.java +++ b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/BaseServletProtocolTestCase.java @@ -121,6 +121,16 @@ public void shouldThrowExceptionOnMissingNamedTargetedContext() throws Exception handler.locateTestServlet(testMethod); } + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionWhenNoConfig() throws Exception { + new ServletURIHandler(null, to(new HTTPContext("127.0.0.1", 8080).add(new Servlet(ServletMethodExecutor.ARQUILLIAN_SERVLET_NAME, "test")))); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionOnNoContexts() throws Exception { + new ServletURIHandler(new ServletProtocolConfiguration(), null); + } + private Collection to(HTTPContext... inputs) { List contexts = new ArrayList(); Collections.addAll(contexts, inputs); diff --git a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/ServletCommandServiceTestCase.java b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/ServletCommandServiceTestCase.java index a53317748..612a96bc0 100644 --- a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/ServletCommandServiceTestCase.java +++ b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/ServletCommandServiceTestCase.java @@ -103,4 +103,25 @@ public void shouldDisableCommandService() throws Exception { "Timeout exception should have been thrown", result.getThrowable().getMessage().contains("timeout")); } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfNoConfig() throws Exception { + new ServletMethodExecutor(null, createContexts(), new TestCommandCallback()); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfNoContexts() { + new ServletMethodExecutor(new ServletProtocolConfiguration(), null, new TestCommandCallback()); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfNoCallback() throws Exception { + new ServletMethodExecutor(new ServletProtocolConfiguration(), createContexts(), null); + } + + @Test(expected = IllegalArgumentException.class) + public void shouldThrowExceptionIfNoExecutor() throws Exception { + ServletMethodExecutor executor = new ServletMethodExecutor(new ServletProtocolConfiguration(), createContexts(), new TestCommandCallback()); + executor.invoke(null); + } } diff --git a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/v_2_5/ServletProtocolDeploymentPackagerTestCase.java b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/v_2_5/ServletProtocolDeploymentPackagerTestCase.java index 4772eac0a..0328751a0 100644 --- a/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/v_2_5/ServletProtocolDeploymentPackagerTestCase.java +++ b/protocols/servlet/src/test/java/org/jboss/arquillian/protocol/servlet/v_2_5/ServletProtocolDeploymentPackagerTestCase.java @@ -302,6 +302,11 @@ public void shouldThrowExceptionOnEnterpriseArchiveWithMultipleMarkedWebArchives processors()); } + @Test(expected = IllegalArgumentException.class) + public void shouldVerifyExceptionOnEmptyVersion() throws Exception { + Descriptors.create(WebAppDescriptor.class).version(""); + } + private Collection> createAuxiliaryArchives() { List> archives = new ArrayList>(); archives.add(ShrinkWrap.create(JavaArchive.class, "auxiliaryArchive1.jar")); From 94c40fc21c974aacd466a2cc7fac4ddd86ddb29b Mon Sep 17 00:00:00 2001 From: Benjamin Confino Date: Tue, 26 Mar 2024 16:22:31 +0000 Subject: [PATCH 2/5] preserve first exception in writeObject (#538) The first exception `e` will be unrelated to `e2`, and if we're reaching the second catch block that means we've failed to report `e` to the debugger. Packaging it in `e2` will ensure it is not lost. --- .../arquillian/protocol/servlet/runner/ServletTestRunner.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/ServletTestRunner.java b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/ServletTestRunner.java index 01fd0141b..1bb1d4624 100644 --- a/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/ServletTestRunner.java +++ b/protocols/servlet/src/main/java/org/jboss/arquillian/protocol/servlet/runner/ServletTestRunner.java @@ -201,7 +201,9 @@ private void writeObject(Object object, HttpServletResponse response) { try { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } catch (Exception e2) { - throw new RuntimeException("Could not write to output", e2); + RuntimeException runtimeException = new RuntimeException("Could not write to output", e2); + runtimeException.addSuppressed(e); + throw runtimeException; } } } From 2bc6e1c3af13a210c01a9e7ea5bbd159c5b58d1c Mon Sep 17 00:00:00 2001 From: Petr Beran Date: Thu, 4 Apr 2024 17:52:25 +0200 Subject: [PATCH 3/5] [ARQ-2232] Migrate CI to Github Actions (#545) --- .github/workflows/ci.yml | 93 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..9dab07da5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,93 @@ +name: Java CI with Maven + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + arquillian-build-jdk8: + name: Integration - JDK 8 + runs-on: ubuntu-latest + timeout-minutes: 10 + outputs: + SNAPSHOT_VERSION: ${{ steps.arq-version.outputs.SNAPSHOT_VERSION }} + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + name: JDK 8 setup + with: + java-version: 8 + distribution: 'temurin' + cache: maven + + - name: Build with Maven + run: mvn clean -B install + + - name: Version save + id: arq-version + run: | + VERSION=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + echo "SNAPSHOT_VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "Arquillian version: $VERSION" + + - name: Artifact upload + uses: actions/upload-artifact@v4 + with: + name: arquillian + path: ~/.m2/repository/org/jboss/ + + arquillian-build-jdk11: + name: Integration - JDK 11 + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + name: JDK 11 setup + with: + java-version: 11 + distribution: 'temurin' + cache: maven + + - name: Build with Maven + run: mvn clean -B install + + integration-wildfly-job: + runs-on: ubuntu-latest + name: Integration verification for WildFly + needs: arquillian-build-jdk8 + timeout-minutes: 300 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: arquillian + path: ~/.m2/repository/org/jboss + + - uses: actions/setup-java@v4 + name: JDK 17 setup + with: + java-version: 17 + distribution: 'temurin' + cache: maven + + - uses: actions/checkout@v4 + name: Checkout WildFly + with: + repository: wildfly/wildfly + + - name: WildFly integration + env: + SNAPSHOT_VERSION: ${{ needs.arquillian-build-jdk8.outputs.SNAPSHOT_VERSION }} + run: | + mvn clean install -Dquickly -Dversion.org.jboss.arquillian.core="$SNAPSHOT_VERSION" + mvn clean verify -f testsuite/integration -DallTests -Dversion.org.jboss.arquillian.core="$SNAPSHOT_VERSION" From 9e80313180d3eec9905b376e74c8e0c2f6ad1a37 Mon Sep 17 00:00:00 2001 From: Scott M Stark Date: Tue, 25 Jun 2024 13:19:37 -0600 Subject: [PATCH 4/5] Add support for specifying a custom mapper implementation for a DeployableContainer. (#553) Fixes #552 --- .../container/impl/ContainerImpl.java | 24 +++++--- .../impl/ContainerRegistryTestCase.java | 61 +++++++++++++++++++ .../arquillian/container/spi/Container.java | 8 +-- .../client/container/ConfigurationMapper.java | 36 +++++++++++ .../client/container/DeployableContainer.java | 11 ++++ 5 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java diff --git a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java index dbe3fe3e4..f1cf57978 100644 --- a/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java +++ b/container/impl-base/src/main/java/org/jboss/arquillian/container/impl/ContainerImpl.java @@ -20,6 +20,7 @@ import org.jboss.arquillian.config.descriptor.api.ProtocolDef; import org.jboss.arquillian.container.spi.Container; import org.jboss.arquillian.container.spi.ServerKillProcessor; +import org.jboss.arquillian.container.spi.client.container.ConfigurationMapper; import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration; import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.spi.client.container.LifecycleException; @@ -47,25 +48,25 @@ * @author Aslak Knutsen * @version $Revision: $ */ -public class ContainerImpl implements Container { +public class ContainerImpl implements Container { @Inject private Event event; @Inject @ContainerScoped - private InstanceProducer containerProducer; + private InstanceProducer> containerProducer; @Inject private Instance serviceLoader; - private DeployableContainer deployableContainer; + private DeployableContainer deployableContainer; private String name; private State state = State.STOPPED; private Throwable failureCause; private ContainerDef containerConfiguration; - public ContainerImpl(String name, DeployableContainer deployableContainer, ContainerDef containerConfiguration) { + public ContainerImpl(String name, DeployableContainer deployableContainer, ContainerDef containerConfiguration) { Validate.notNull(name, "Name must be specified"); Validate.notNull(deployableContainer, "DeployableContainer must be specified"); Validate.notNull(containerConfiguration, "ConfigurationConfiguration must be specified"); @@ -87,7 +88,7 @@ public String getName() { * @see org.jboss.arquillian.container.impl.ContainerT#getDeployableContainer() */ @Override - public DeployableContainer getDeployableContainer() { + public DeployableContainer getDeployableContainer() { return deployableContainer; } @@ -103,10 +104,15 @@ public ContainerDef getContainerConfiguration() { * @see org.jboss.arquillian.container.impl.ContainerT#createDeployableConfiguration() */ @Override - public ContainerConfiguration createDeployableConfiguration() throws Exception { - ContainerConfiguration config = SecurityActions.newInstance( - deployableContainer.getConfigurationClass(), new Class[0], new Object[0]); - MapObject.populate(config, containerConfiguration.getContainerProperties()); + public T createDeployableConfiguration() throws Exception { + Class configClass = (Class) deployableContainer.getConfigurationClass(); + T config = SecurityActions.newInstance(configClass, new Class[0], new Object[0]); + ConfigurationMapper mapper = deployableContainer.getConfigurationMapper(); + if(mapper != null) { + mapper.populateConfiguration(config, containerConfiguration); + } else { + MapObject.populate(config, containerConfiguration.getContainerProperties()); + } config.validate(); return config; } diff --git a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java index 8ab81eac2..6e5f85cf0 100644 --- a/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java +++ b/container/impl-base/src/test/java/org/jboss/arquillian/container/impl/ContainerRegistryTestCase.java @@ -16,10 +16,12 @@ */ package org.jboss.arquillian.container.impl; +import org.jboss.arquillian.config.descriptor.api.ContainerDef; import org.jboss.arquillian.config.descriptor.impl.ContainerDefImpl; import org.jboss.arquillian.container.spi.ConfigurationException; import org.jboss.arquillian.container.spi.Container; import org.jboss.arquillian.container.spi.ContainerRegistry; +import org.jboss.arquillian.container.spi.client.container.ConfigurationMapper; import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration; import org.jboss.arquillian.container.spi.client.container.DeployableContainer; import org.jboss.arquillian.container.spi.client.deployment.TargetDescription; @@ -140,6 +142,46 @@ public void shouldBeAbleToCreatePrivateContainerConfiguration() throws Exception ((PrivateDummyContainerConfiguration) container.createDeployableConfiguration()).getProperty()); } + @Test + public void shouldBeAbleToCreateContainerConfigurationCustomMapper() throws Exception { + ServiceLoader serviceLoader = Mockito.mock(ServiceLoader.class); + DeployableContainer deployableContainer = + Mockito.mock(DeployableContainer.class); + + Mockito.when(serviceLoader.onlyOne(Mockito.same(DeployableContainer.class))).thenReturn(deployableContainer); + Mockito.when(deployableContainer.getConfigurationClass()).thenReturn(CustomContainerConfiguration.class); + Mockito.when(deployableContainer.getConfigurationMapper()).thenReturn(new CustomMapper()); + + String name = "custom-container"; + String prop = "prop-value"; + String[] hosts = {"host1", "host2", "host3"}; + + ContainerRegistry registry = new LocalContainerRegistry(injector.get()); + ContainerDefImpl containerDef = new ContainerDefImpl(ARQUILLIAN_XML); + containerDef.setContainerName(name); + containerDef.property("property", prop); + containerDef.property("hosts", "host1,host2,host3"); + + registry.create(containerDef, serviceLoader); + + Container container = registry.getContainer(new TargetDescription(name)); + + Assert.assertEquals( + "Verify that the only registered container is returned as default", + name, container.getName()); + + CustomContainerConfiguration config = container.createDeployableConfiguration(); + Assert.assertEquals( + "Verify that the custom configuration 'property' was populated", + prop, + config.getProperty()); + + Assert.assertArrayEquals( + "Verify that the custom configuration 'hosts' was populated", + hosts, + config.getHosts()); + } + @Test public void shouldBeAbleToSpecifyTarget() throws Exception { String name = "some-name"; @@ -197,4 +239,23 @@ private static class PrivateDummyContainerConfiguration extends DummyContainerCo private PrivateDummyContainerConfiguration() { } } + private static class CustomContainerConfiguration extends DummyContainerConfiguration { + private String[] hosts; + public String[] getHosts() { + return hosts; + } + public void setHosts(String[] hosts) { + this.hosts = hosts; + } + } + private static class CustomMapper implements ConfigurationMapper { + @Override + public void populateConfiguration(CustomContainerConfiguration containerConfiguration, ContainerDef definition) { + String property = definition.getContainerProperty("property"); + containerConfiguration.setProperty(property); + String hostsString = definition.getContainerProperty("hosts"); + String[] hosts = hostsString.split(","); + containerConfiguration.setHosts(hosts); + } + } } diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java index 59f2b79ab..8ef4c6d37 100644 --- a/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java +++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/Container.java @@ -30,7 +30,7 @@ * @author Aslak Knutsen * @version $Revision: $ */ -public interface Container { +public interface Container { /** * @return the name @@ -40,7 +40,7 @@ public interface Container { /** * @return the deployableContainer */ - DeployableContainer getDeployableContainer(); + DeployableContainer getDeployableContainer(); /** * @return the containerConfiguration @@ -50,7 +50,7 @@ public interface Container { /** * @return the configuration */ - ContainerConfiguration createDeployableConfiguration() throws Exception; + T createDeployableConfiguration() throws Exception; boolean hasProtocolConfiguration(ProtocolDescription description); @@ -73,4 +73,4 @@ public interface Container { enum State { SETUP, SETUP_FAILED, STARTED, STARTED_FAILED, STOPPED, STOPPED_FAILED, KILLED, KILLED_FAILED; } -} \ No newline at end of file +} diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java new file mode 100644 index 000000000..d0d715e85 --- /dev/null +++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/ConfigurationMapper.java @@ -0,0 +1,36 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2024 Red Hat Inc. and/or its affiliates and other 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.arquillian.container.spi.client.container; + +import org.jboss.arquillian.config.descriptor.api.ContainerDef; + +/** + * An interface that {@link DeployableContainer} can use to control how the mapping + * from the externalized container definition, as found in an arquillian.xml file + * for example, is applied to the {@link ContainerConfiguration} instances + * + * @param the type of ContainerConfiguration + */ +public interface ConfigurationMapper { + /** + * + * @param containerConfiguration - the deployable container configuration instance to populate + * @param definition - the container definition from the ArquillianDescriptor that + * was parsed + */ + void populateConfiguration(T containerConfiguration, ContainerDef definition); +} diff --git a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java index 9e4425a91..513356a7b 100644 --- a/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java +++ b/container/spi/src/main/java/org/jboss/arquillian/container/spi/client/container/DeployableContainer.java @@ -37,6 +37,17 @@ public interface DeployableContainer { // ControllableContainer Class getConfigurationClass(); + /** + * Provide a mapping instance that takes the {@link org.jboss.arquillian.config.descriptor.api.ContainerDef} + * for the arquillian.xml or other configured descriptor and populates the container configuration + * instance from the descriptor values. + * + * @return A possibly null ConfigurationMapper. If null, the default logic to map from string based + * properties as implemented in org.jboss.arquillian.container.impl.MapObject will be used. + */ + default ConfigurationMapper getConfigurationMapper() { + return null; + } default void setup(T configuration) { } From 76ba1935dddf8c90839c75502d8c3dc38732c09a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:22:19 -0600 Subject: [PATCH 5/5] build(deps-dev): Bump org.slf4j:slf4j-simple from 2.0.1 to 2.0.12 (#537) Bumps org.slf4j:slf4j-simple from 2.0.1 to 2.0.12. --- updated-dependencies: - dependency-name: org.slf4j:slf4j-simple dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott M Stark --- testenrichers/cdi/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testenrichers/cdi/pom.xml b/testenrichers/cdi/pom.xml index 5c87acdaa..5a7e4c96b 100644 --- a/testenrichers/cdi/pom.xml +++ b/testenrichers/cdi/pom.xml @@ -25,7 +25,7 @@ 2.4.8.Final 2.2 - 2.0.1 + 2.0.12