-
-
Save nipafx/a21f1d1c5211617453e43a88c9df439c to your computer and use it in GitHub Desktop.
Partial implementation of `DisabledIfUnreachable`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.junit.jupiter.api.extension.ExtendWith; | |
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) | |
@Retention(RetentionPolicy.RUNTIME) | |
@ExtendWith(EnabledIfReachableCondition.class) | |
public @interface EnabledIfReachable { | |
String url(); | |
int timeoutMillis(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.junit.jupiter.api.extension.ConditionEvaluationResult; | |
import org.junit.jupiter.api.extension.ExecutionCondition; | |
import org.junit.jupiter.api.extension.ExtensionContext; | |
import java.io.IOException; | |
import java.lang.reflect.AnnotatedElement; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import static java.lang.String.format; | |
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; | |
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; | |
import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; | |
class EnabledIfReachableCondition implements ExecutionCondition { | |
private static final ConditionEvaluationResult ENABLED_BY_DEFAULT = | |
enabled("@EnabledIfReachable is not present"); | |
@Override | |
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { | |
AnnotatedElement element = context | |
.getElement() | |
.orElseThrow(IllegalStateException::new); | |
return findAnnotation(element, EnabledIfReachable.class) | |
.map(annotation -> disableIfUnreachable(annotation, element)) | |
.orElse(ENABLED_BY_DEFAULT); | |
} | |
private ConditionEvaluationResult disableIfUnreachable(EnabledIfReachable annotation, AnnotatedElement element) { | |
String url = annotation.url(); | |
int timeoutMillis = annotation.timeoutMillis(); | |
boolean reachable = pingUrl(url, timeoutMillis); | |
if (reachable) | |
return enabled(format("%s is enabled because %s is reachable", element, url)); | |
else | |
return disabled(format( | |
"%s is disabled because %s could not be reached in %dms", | |
element, url, timeoutMillis)); | |
} | |
/** | |
* Pings a HTTP URL. This effectively sends a HEAD request and returns | |
* <code>true</code> if the response code is in the 200-399 range. | |
* | |
* (From BalusC on StackOverflow: | |
* - https://stackoverflow.com/a/3584332/2525313 | |
* - https://stackoverflow.com/users/157882/balusc) | |
* | |
* @param url | |
* The HTTP URL to be pinged. | |
* @param timeoutMillis | |
* The timeout in millis for both the connection timeout and the | |
* response read timeout. Note that the total timeout is effectively | |
* two times the given timeout. | |
* | |
* @return <code>true</code> if the given HTTP URL has returned response | |
* code 200-399 on a HEAD request within the given timeout, otherwise | |
* <code>false</code>. | |
*/ | |
private static boolean pingUrl(String url, int timeoutMillis) { | |
// Otherwise an exception may be thrown on invalid SSL certificates | |
String httpUrl = url.replaceFirst("^https", "http"); | |
try { | |
HttpURLConnection connection = (HttpURLConnection) new URL(httpUrl).openConnection(); | |
connection.setConnectTimeout(timeoutMillis); | |
connection.setReadTimeout(timeoutMillis); | |
connection.setRequestMethod("HEAD"); | |
int responseCode = connection.getResponseCode(); | |
return (200 <= responseCode && responseCode <= 399); | |
} catch (IOException exception) { | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment