diff --git a/bom/runtime/pom.xml b/bom/runtime/pom.xml index fbd5f4c9aea33..96539bdc26c7d 100644 --- a/bom/runtime/pom.xml +++ b/bom/runtime/pom.xml @@ -30,7 +30,7 @@ 1.0.1 1.3.1 1.0 - 1.3.3 + 1.3.4 1.3.9 2.1.0 2.2.0 diff --git a/build-parent/pom.xml b/build-parent/pom.xml index a949ab3fa9c5a..09dc121c2fc14 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -61,7 +61,7 @@ 2.1.0 2.0.2 1.0 - 1.2.1 + 1.3.4 1.1.2 1.3.1 1.0.1 diff --git a/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java b/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java index 56edb24c7361c..bc06a876170a2 100644 --- a/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java +++ b/extensions/rest-client/deployment/src/main/java/io/quarkus/restclient/deployment/RestClientProcessor.java @@ -138,33 +138,9 @@ void processInterfaces(CombinedIndexBuildItem combinedIndexBuildItem, Set returnTypes = new HashSet<>(); IndexView index = combinedIndexBuildItem.getIndex(); - for (AnnotationInstance annotation : index.getAnnotations(PATH)) { - AnnotationTarget target = annotation.target(); - ClassInfo theInfo; - if (target.kind() == AnnotationTarget.Kind.CLASS) { - theInfo = target.asClass(); - } else if (target.kind() == AnnotationTarget.Kind.METHOD) { - theInfo = target.asMethod().declaringClass(); - } else { - continue; - } - - if (!isRestClientInterface(index, theInfo)) { - continue; - } - interfaces.put(theInfo.name(), theInfo); - - // Find Return types - for (MethodInfo method : theInfo.methods()) { - Type type = method.returnType(); - if (!type.name().toString().contains("java.lang")) { - if (!returnTypes.contains(type)) { - returnTypes.add(type); - } - } - } - } + findInterfaces(index, interfaces, returnTypes, REGISTER_REST_CLIENT); + findInterfaces(index, interfaces, returnTypes, PATH); if (interfaces.isEmpty()) { return; @@ -207,16 +183,17 @@ public void register(RegistrationContext registrationContext) { // The spec is not clear whether we should add superinterfaces too - let's keep aligned with SmallRye for now configurator.addType(restClientName); configurator.addQualifier(REST_CLIENT); - final ScopeInfo scope = computeDefaultScope(config, entry); + final String configPrefix = computeConfigPrefix(restClientName.toString(), entry.getValue()); + final ScopeInfo scope = computeDefaultScope(config, entry, configPrefix); configurator.scope(scope); configurator.creator(m -> { // return new RestClientBase(proxyType, baseUri).create(); ResultHandle interfaceHandle = m.loadClass(restClientName.toString()); ResultHandle baseUriHandle = m.load(getAnnotationParameter(entry.getValue(), "baseUri")); - ResultHandle configKeyHandle = m.load(getAnnotationParameter(entry.getValue(), "configKey")); + ResultHandle configPrefixHandle = m.load(configPrefix); ResultHandle baseHandle = m.newInstance( MethodDescriptor.ofConstructor(RestClientBase.class, Class.class, String.class, String.class), - interfaceHandle, baseUriHandle, configKeyHandle); + interfaceHandle, baseUriHandle, configPrefixHandle); ResultHandle ret = m.invokeVirtualMethod( MethodDescriptor.ofMethod(RestClientBase.class, "create", Object.class), baseHandle); m.returnValue(ret); @@ -232,13 +209,62 @@ public void register(RegistrationContext registrationContext) { restClientRecorder.setSslEnabled(sslNativeConfig.isEnabled()); } - private ScopeInfo computeDefaultScope(Config config, Map.Entry entry) { - DotName restClientName = entry.getKey(); + private void findInterfaces(IndexView index, Map interfaces, Set returnTypes, + DotName annotationToFind) { + for (AnnotationInstance annotation : index.getAnnotations(annotationToFind)) { + AnnotationTarget target = annotation.target(); + ClassInfo theInfo; + if (target.kind() == AnnotationTarget.Kind.CLASS) { + theInfo = target.asClass(); + } else if (target.kind() == AnnotationTarget.Kind.METHOD) { + theInfo = target.asMethod().declaringClass(); + } else { + continue; + } + + if (!isRestClientInterface(index, theInfo)) { + continue; + } + + interfaces.put(theInfo.name(), theInfo); + + // Find Return types + processInterfaceReturnTypes(theInfo, returnTypes); + for (Type interfaceType : theInfo.interfaceTypes()) { + ClassInfo interfaceClassInfo = index.getClassByName(interfaceType.name()); + if (interfaceClassInfo != null) { + processInterfaceReturnTypes(interfaceClassInfo, returnTypes); + } + } + } + } + + private void processInterfaceReturnTypes(ClassInfo classInfo, Set returnTypes) { + for (MethodInfo method : classInfo.methods()) { + Type type = method.returnType(); + if (!type.name().toString().contains("java.lang")) { + if (!returnTypes.contains(type)) { + returnTypes.add(type); + } + } + } + } + + private String computeConfigPrefix(String interfaceName, ClassInfo classInfo) { + String propertyPrefixFromAnnotation = getAnnotationParameter(classInfo, "configKey"); + + if (propertyPrefixFromAnnotation != null && !propertyPrefixFromAnnotation.isEmpty()) { + return propertyPrefixFromAnnotation; + } + + return interfaceName; + } + + private ScopeInfo computeDefaultScope(Config config, Map.Entry entry, String configPrefix) { // Initialize a default @Dependent scope as per the spec ScopeInfo scopeInfo = BuiltinScope.DEPENDENT.getInfo(); - final String REST_SCOPE_FORMAT = "%s/" + RestClientBase.MP_REST + "/scope"; final Optional scopeConfig = config - .getOptionalValue(String.format(REST_SCOPE_FORMAT, restClientName.toString()), String.class); + .getOptionalValue(String.format(RestClientBase.REST_SCOPE_FORMAT, configPrefix), String.class); if (scopeConfig.isPresent()) { final DotName scope = DotName.createSimple(scopeConfig.get()); final BuiltinScope builtinScope = BuiltinScope.from(scope); @@ -247,7 +273,7 @@ private ScopeInfo computeDefaultScope(Config config, Map.Entry annotations = entry.getValue().annotations().keySet(); diff --git a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java index f41d9f2c76e7a..d0030473ce41b 100644 --- a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java +++ b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientBase.java @@ -1,8 +1,17 @@ package io.quarkus.restclient.runtime; +import java.io.*; import java.net.MalformedURLException; import java.net.URL; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import javax.net.ssl.HostnameVerifier; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; @@ -13,54 +22,194 @@ public class RestClientBase { public static final String MP_REST = "mp-rest"; public static final String REST_URL_FORMAT = "%s/" + MP_REST + "/url"; public static final String REST_URI_FORMAT = "%s/" + MP_REST + "/uri"; + public static final String REST_CONNECT_TIMEOUT_FORMAT = "%s/" + MP_REST + "/connectTimeout"; + public static final String REST_READ_TIMEOUT_FORMAT = "%s/" + MP_REST + "/readTimeout"; + public static final String REST_SCOPE_FORMAT = "%s/" + MP_REST + "/scope"; + public static final String REST_PROVIDERS = "%s/" + MP_REST + "/providers"; + public static final String REST_TRUST_STORE = "%s/" + MP_REST + "/trustStore"; + public static final String REST_TRUST_STORE_PASSWORD = "%s/" + MP_REST + "/trustStorePassword"; + public static final String REST_TRUST_STORE_TYPE = "%s/" + MP_REST + "/trustStoreType"; + public static final String REST_KEY_STORE = "%s/" + MP_REST + "/keyStore"; + public static final String REST_KEY_STORE_PASSWORD = "%s/" + MP_REST + "/keyStorePassword"; + public static final String REST_KEY_STORE_TYPE = "%s/" + MP_REST + "/keyStoreType"; + public static final String REST_HOSTNAME_VERIFIER = "%s/" + MP_REST + "/hostnameVerifier"; private final Class proxyType; private final String baseUriFromAnnotation; - private final String propertyPrefixFromAnnotation; + private final String propertyPrefix; private final Config config; - public RestClientBase(Class proxyType, String baseUriFromAnnotation, String propertyPrefixFromAnnotation) { + public RestClientBase(Class proxyType, String baseUriFromAnnotation, String propertyPrefix) { this.proxyType = proxyType; this.baseUriFromAnnotation = baseUriFromAnnotation; - this.propertyPrefixFromAnnotation = propertyPrefixFromAnnotation; this.config = ConfigProvider.getConfig(); + this.propertyPrefix = propertyPrefix; } public Object create() { RestClientBuilder builder = RestClientBuilder.newBuilder(); - String baseUrl = getBaseUrl(); + configureBaseUrl(builder); + configureTimeouts(builder); + configureProviders(builder); + configureSsl(builder); + + return builder.build(proxyType); + } + + private void configureSsl(RestClientBuilder builder) { + Optional maybeTrustStore = getOptionalProperty(REST_TRUST_STORE, String.class); + maybeTrustStore.ifPresent(trustStore -> registerTrustStore(trustStore, builder)); + + Optional maybeKeyStore = getOptionalProperty(REST_KEY_STORE, String.class); + maybeKeyStore.ifPresent(keyStore -> registerKeyStore(keyStore, builder)); + + Optional maybeHostnameVerifier = getOptionalProperty(REST_HOSTNAME_VERIFIER, String.class); + maybeHostnameVerifier.ifPresent(verifier -> registerHostnameVerifier(verifier, builder)); + } + + private void registerHostnameVerifier(String verifier, RestClientBuilder builder) { try { - return builder.baseUrl(new URL(baseUrl)).build(proxyType); - } catch (MalformedURLException e) { - throw new IllegalArgumentException("The value of URL was invalid " + baseUrl, e); - } catch (Exception e) { - if ("com.oracle.svm.core.jdk.UnsupportedFeatureError".equals(e.getClass().getCanonicalName())) { - throw new IllegalArgumentException(baseUrl - + " requires SSL support but it is disabled. You probably have set quarkus.ssl.native to false."); + Class verifierClass = Class.forName(verifier, true, Thread.currentThread().getContextClassLoader()); + builder.hostnameVerifier((HostnameVerifier) verifierClass.newInstance()); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Could not find hostname verifier class" + verifier, e); + } catch (InstantiationException | IllegalAccessException e) { + throw new RuntimeException( + "Failed to instantiate hostname verifier class. Make sure it has a public, no-argument constructor", e); + } catch (ClassCastException e) { + throw new RuntimeException("The provided hostname verifier " + verifier + " is not an instance of HostnameVerifier", + e); + } + } + + private void registerKeyStore(String keyStorePath, RestClientBuilder builder) { + Optional keyStorePassword = getOptionalProperty(REST_KEY_STORE_PASSWORD, String.class); + Optional keyStoreType = getOptionalProperty(REST_KEY_STORE_TYPE, String.class); + + try { + KeyStore keyStore = KeyStore.getInstance(keyStoreType.orElse("JKS")); + String password = keyStorePassword + .orElseThrow(() -> new IllegalArgumentException("No password provided for keystore")); + + try (InputStream input = locateStream(keyStorePath)) { + keyStore.load(input, password.toCharArray()); + } catch (IOException | CertificateException | NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Failed to initialize trust store from classpath resource " + keyStorePath, + e); } - throw e; + + builder.keyStore(keyStore, password); + } catch (KeyStoreException e) { + throw new IllegalArgumentException("Failed to initialize trust store from " + keyStorePath, e); + } + } + + private void registerTrustStore(String trustStorePath, RestClientBuilder builder) { + Optional maybeTrustStorePassword = getOptionalProperty(REST_TRUST_STORE_PASSWORD, String.class); + Optional maybeTrustStoreType = getOptionalProperty(REST_TRUST_STORE_TYPE, String.class); + + try { + KeyStore trustStore = KeyStore.getInstance(maybeTrustStoreType.orElse("JKS")); + String password = maybeTrustStorePassword + .orElseThrow(() -> new IllegalArgumentException("No password provided for truststore")); + + try (InputStream input = locateStream(trustStorePath)) { + trustStore.load(input, password.toCharArray()); + } catch (IOException | CertificateException | NoSuchAlgorithmException e) { + throw new IllegalArgumentException("Failed to initialize trust store from classpath resource " + trustStorePath, + e); + } + + builder.trustStore(trustStore); + } catch (KeyStoreException e) { + throw new IllegalArgumentException("Failed to initialize trust store from " + trustStorePath, e); } } - private String getBaseUrl() { - String prefix = proxyType.getName(); - if (propertyPrefixFromAnnotation != null && !propertyPrefixFromAnnotation.isEmpty()) { - prefix = propertyPrefixFromAnnotation; + private InputStream locateStream(String path) throws FileNotFoundException { + if (path.startsWith("classpath:")) { + path = path.replaceFirst("classpath:", ""); + InputStream resultStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); + if (resultStream == null) { + resultStream = getClass().getResourceAsStream(path); + } + if (resultStream == null) { + throw new IllegalArgumentException( + "Classpath resource " + path + " not found for MicroProfile Rest Client SSL configuration"); + } + return resultStream; + } else { + if (path.startsWith("file:")) { + path = path.replaceFirst("file:", ""); + } + File certificateFile = new File(path); + if (!certificateFile.isFile()) { + throw new IllegalArgumentException( + "Certificate file: " + path + " not found for MicroProfile Rest Client SSL configuration"); + } + return new FileInputStream(certificateFile); } - String propertyName = String.format(REST_URI_FORMAT, prefix); - Optional propertyOptional = config.getOptionalValue(propertyName, String.class); + } + + private void configureProviders(RestClientBuilder builder) { + Optional maybeProviders = getOptionalProperty(REST_PROVIDERS, String.class); + maybeProviders.ifPresent(providers -> registerProviders(builder, providers)); + } + + private void registerProviders(RestClientBuilder builder, String providersAsString) { + Stream.of(providersAsString.split(",")) + .map(String::trim) + .map(this::providerClassForName) + .forEach(builder::register); + } + + private Class providerClassForName(String name) { + try { + return Class.forName(name, true, Thread.currentThread().getContextClassLoader()); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Could not find provider class: " + name); + } + } + + private void configureTimeouts(RestClientBuilder builder) { + Optional connectTimeout = getOptionalProperty(REST_CONNECT_TIMEOUT_FORMAT, Long.class); + connectTimeout.ifPresent(timeout -> builder.connectTimeout(timeout, TimeUnit.MILLISECONDS)); + + Optional readTimeout = getOptionalProperty(REST_READ_TIMEOUT_FORMAT, Long.class); + readTimeout.ifPresent(timeout -> builder.readTimeout(timeout, TimeUnit.MILLISECONDS)); + } + + private void configureBaseUrl(RestClientBuilder builder) { + Optional propertyOptional = getOptionalProperty(REST_URI_FORMAT, String.class); if (!propertyOptional.isPresent()) { - propertyName = String.format(REST_URL_FORMAT, prefix); - propertyOptional = config.getOptionalValue(propertyName, String.class); + propertyOptional = getOptionalProperty(REST_URL_FORMAT, String.class); } if (((baseUriFromAnnotation == null) || baseUriFromAnnotation.isEmpty()) && !propertyOptional.isPresent()) { throw new IllegalArgumentException( String.format( "Unable to determine the proper baseUrl/baseUri. Consider registering using @RegisterRestClient(baseUri=\"someuri\", configKey=\"orkey\"), or by adding '%s' to your Quarkus configuration", - propertyName)); + propertyPrefix)); } - return propertyOptional.orElse(baseUriFromAnnotation); + String baseUrl = propertyOptional.orElse(baseUriFromAnnotation); + + try { + builder.baseUrl(new URL(baseUrl)); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("The value of URL was invalid " + baseUrl, e); + } catch (Exception e) { + if ("com.oracle.svm.core.jdk.UnsupportedFeatureError".equals(e.getClass().getCanonicalName())) { + throw new IllegalArgumentException(baseUrl + + " requires SSL support but it is disabled. You probably have set quarkus.ssl.native to false."); + } + throw e; + } + } + + private Optional getOptionalProperty(String propertyFormat, Class type) { + Optional interfaceNameValue = config.getOptionalValue(String.format(propertyFormat, proxyType.getName()), type); + return interfaceNameValue.isPresent() ? interfaceNameValue + : config.getOptionalValue(String.format(propertyFormat, propertyPrefix), type); } } diff --git a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientRecorder.java b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientRecorder.java index 2ecf17c874fbd..cd563e4aeaedb 100644 --- a/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientRecorder.java +++ b/extensions/rest-client/runtime/src/main/java/io/quarkus/restclient/runtime/RestClientRecorder.java @@ -49,19 +49,23 @@ public InjectorFactory getInjectorFactory() { if (useBuiltIn) { RegisterBuiltin.register(clientProviderFactory); - registerProviders(clientProviderFactory, contributedProviders); + registerProviders(clientProviderFactory, contributedProviders, false); } else { - registerProviders(clientProviderFactory, providersToRegister); + providersToRegister.removeAll(contributedProviders); + registerProviders(clientProviderFactory, providersToRegister, true); + registerProviders(clientProviderFactory, contributedProviders, false); } RestClientBuilderImpl.setProviderFactory(clientProviderFactory); } - private static void registerProviders(ResteasyProviderFactory clientProviderFactory, Set providersToRegister) { + private static void registerProviders(ResteasyProviderFactory clientProviderFactory, Set providersToRegister, + Boolean isBuiltIn) { for (String providerToRegister : providersToRegister) { try { clientProviderFactory - .registerProvider(Thread.currentThread().getContextClassLoader().loadClass(providerToRegister.trim())); + .registerProvider(Thread.currentThread().getContextClassLoader().loadClass(providerToRegister.trim()), + isBuiltIn); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to find class for provider " + providerToRegister, e); } diff --git a/tcks/microprofile-fault-tolerance/tck-suite.xml b/tcks/microprofile-fault-tolerance/tck-suite.xml index 0a7a3f2e8e779..09a6ff27adf7e 100644 --- a/tcks/microprofile-fault-tolerance/tck-suite.xml +++ b/tcks/microprofile-fault-tolerance/tck-suite.xml @@ -45,6 +45,11 @@ + + + + + diff --git a/tcks/microprofile-metrics/rest/pom.xml b/tcks/microprofile-metrics/rest/pom.xml index c38c376f1af44..4856f1dc87861 100644 --- a/tcks/microprofile-metrics/rest/pom.xml +++ b/tcks/microprofile-metrics/rest/pom.xml @@ -31,6 +31,9 @@ tier=integration + + org.eclipse.microprofile.metrics.test.MpMetricTest + diff --git a/tcks/microprofile-rest-client/pom.xml b/tcks/microprofile-rest-client/pom.xml index 44c7620865e07..cb3595da13e43 100644 --- a/tcks/microprofile-rest-client/pom.xml +++ b/tcks/microprofile-rest-client/pom.xml @@ -19,9 +19,6 @@ org.apache.maven.plugins maven-surefire-plugin - - tck-suite.xml - false @@ -32,6 +29,19 @@ org.eclipse.microprofile.rest.client:microprofile-rest-client-tck + false + + **/*Test.java + + + + org.eclipse.microprofile.rest.client.tck.WiremockArquillianTest + org.eclipse.microprofile.rest.client.tck.ssl.AbstractSslTest + + + org.eclipse.microprofile.rest.client.tck.cditests.HasConversationScopeTest + org.eclipse.microprofile.rest.client.tck.cditests.HasSessionScopeTest + @@ -62,6 +72,22 @@ io.quarkus quarkus-rest-client + + io.quarkus + quarkus-jsonp + + + org.jboss.resteasy + resteasy-json-p-provider + + + io.quarkus + quarkus-jsonb + + + org.jboss.resteasy + resteasy-json-binding-provider + org.eclipse.microprofile.rest.client microprofile-rest-client-tck diff --git a/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/RestClientTckExtension.java b/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/RestClientTckExtension.java new file mode 100644 index 0000000000000..79e25e9423942 --- /dev/null +++ b/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/RestClientTckExtension.java @@ -0,0 +1,11 @@ +package io.quarkus.tck.restclient; + +import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; +import org.jboss.arquillian.core.spi.LoadableExtension; + +public class RestClientTckExtension implements LoadableExtension { + @Override + public void register(ExtensionBuilder builder) { + builder.service(ApplicationArchiveProcessor.class, SslArchiveProcessor.class); + } +} diff --git a/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SkipProblematicTests.java b/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SkipProblematicTests.java deleted file mode 100644 index 754067d63a555..0000000000000 --- a/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SkipProblematicTests.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.quarkus.tck.restclient; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.microprofile.rest.client.tck.ClientHeaderParamTest; -import org.eclipse.microprofile.rest.client.tck.InvokeWithJsonBProviderTest; -import org.eclipse.microprofile.rest.client.tck.InvokeWithJsonPProviderTest; -import org.eclipse.microprofile.rest.client.tck.asynctests.AsyncMethodTest; -import org.testng.IAnnotationTransformer; -import org.testng.IConfigurable; -import org.testng.IConfigureCallBack; -import org.testng.ITestNGMethod; -import org.testng.ITestResult; -import org.testng.annotations.ITestAnnotation; - -public class SkipProblematicTests implements IConfigurable, IAnnotationTransformer { - - private static final Set TESTS_THAT_THROW_CLASS_NOT_FOUND = new HashSet<>(Arrays.asList( - InvokeWithJsonBProviderTest.class.getName(), InvokeWithJsonPProviderTest.class.getName(), - ClientHeaderParamTest.class.getName())); - - private static final Set RACEY_TESTS = new HashSet<>(Arrays.asList( - //testAsyncInvocationInterceptorProvider is racey, as there is no guarantee the - //removeThreadId has been set by the time the test attempts to assert it, this is - //because the removeContext action happens after the response is provided, so the - //completion stage is complete before this method is called - AsyncMethodTest.class.getName())); - - private static final Set SKIP; - - static { - SKIP = new HashSet<>(); - SKIP.addAll(TESTS_THAT_THROW_CLASS_NOT_FOUND); - SKIP.addAll(RACEY_TESTS); - } - - // ensures that the methods annotated with @BeforeTest don't run (since this is where the exception is thrown) - @Override - public void run(IConfigureCallBack callBack, ITestResult testResult) { - ITestNGMethod method = testResult.getMethod(); - if (SKIP.contains(method.getTestClass().getName())) { - return; - } - - callBack.runConfigurationMethod(testResult); - } - - // ensures the actual tests method don't run - @Override - public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) { - String className = testClass != null ? testClass.getName() : testMethod.getDeclaringClass().getName(); - if (SKIP.contains(className)) { - annotation.setEnabled(false); - } - } -} diff --git a/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SslArchiveProcessor.java b/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SslArchiveProcessor.java new file mode 100644 index 0000000000000..5b3b4462d0e23 --- /dev/null +++ b/tcks/microprofile-rest-client/src/test/java/io/quarkus/tck/restclient/SslArchiveProcessor.java @@ -0,0 +1,27 @@ +package io.quarkus.tck.restclient; + +import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; +import org.jboss.arquillian.test.spi.TestClass; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; + +public class SslArchiveProcessor implements ApplicationArchiveProcessor { + @Override + public void process(Archive applicationArchive, TestClass testClass) { + // Only apply the processor to SSL tests + if (testClass.getName().contains("SslHostnameVerifierTest") || + testClass.getName().contains("SslMutualTest") || + testClass.getName().contains("SslTrustStoreTest") || + testClass.getName().contains("SslContextTest")) { + + if (!(applicationArchive instanceof WebArchive)) { + return; + } + + WebArchive war = applicationArchive.as(WebArchive.class); + + war.addAsResource(new StringAsset("quarkus.ssl.native=true"), "application.properties"); + } + } +} diff --git a/tcks/microprofile-rest-client/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/tcks/microprofile-rest-client/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension new file mode 100644 index 0000000000000..9dc06350b2d4e --- /dev/null +++ b/tcks/microprofile-rest-client/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension @@ -0,0 +1 @@ +io.quarkus.tck.restclient.RestClientTckExtension \ No newline at end of file diff --git a/tcks/microprofile-rest-client/tck-suite.xml b/tcks/microprofile-rest-client/tck-suite.xml deleted file mode 100644 index 22fb79ea36b46..0000000000000 --- a/tcks/microprofile-rest-client/tck-suite.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test-framework/arquillian/src/main/java/io/quarkus/arquillian/QuarkusTestNgCallbacks.java b/test-framework/arquillian/src/main/java/io/quarkus/arquillian/QuarkusTestNgCallbacks.java index 5f8bf4e77f7c5..5501a3211c719 100644 --- a/test-framework/arquillian/src/main/java/io/quarkus/arquillian/QuarkusTestNgCallbacks.java +++ b/test-framework/arquillian/src/main/java/io/quarkus/arquillian/QuarkusTestNgCallbacks.java @@ -9,8 +9,10 @@ import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; /** * Note that we cannot use event.getExecutor().invoke() directly because the callbacks would be invoked upon the original test @@ -57,6 +59,7 @@ static void invokeTestNgAfterMethods() throws IllegalAccessException, IllegalArg if (testInstance != null) { List afterMethods = new ArrayList<>(); collectCallbacks(testInstance.getClass(), afterMethods, AfterMethod.class); + collectCallbacks(testInstance.getClass(), afterMethods, AfterTest.class); for (Method m : afterMethods) { // we don't know the values for parameterized methods that TestNG allows, we just skip those if (m.getParameterCount() == 0) { @@ -72,6 +75,7 @@ static void invokeTestNgBeforeMethods() throws IllegalAccessException, IllegalAr if (testInstance != null) { List beforeMethods = new ArrayList<>(); collectCallbacks(testInstance.getClass(), beforeMethods, BeforeMethod.class); + collectCallbacks(testInstance.getClass(), beforeMethods, BeforeTest.class); for (Method m : beforeMethods) { // we don't know the values for parameterized methods that TestNG allows, we just skip those if (m.getParameterCount() == 0) {