diff --git a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy
index 7ffd956f..39c71c79 100644
--- a/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy
+++ b/htmlSanityCheck-core/src/test/groovy/org/aim42/htmlsanitycheck/check/BrokenHttpLinksCheckerSpec.groovy
@@ -4,7 +4,7 @@ import org.aim42.htmlsanitycheck.Configuration
import org.aim42.htmlsanitycheck.collect.SingleCheckResults
import org.aim42.htmlsanitycheck.html.HtmlConst
import org.aim42.htmlsanitycheck.html.HtmlPage
-import org.aim42.htmlsanitycheck.tools.Web
+import org.aim42.htmlsanitycheck.test.dns.CustomHostNameResolver
import org.wiremock.integrations.testcontainers.WireMockContainer
import spock.lang.Ignore
import spock.lang.IgnoreIf
@@ -12,6 +12,10 @@ import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll
+import java.lang.reflect.Field
+import java.lang.reflect.Proxy
+
+
// see end-of-file for license information
@@ -29,19 +33,17 @@ class BrokenHttpLinksCheckerSpec extends Specification {
.withMappingFromResource("mappings.json")
.withExposedPorts(8080)
+ @Shared
+ CustomHostNameResolver customHostNameResolver = new CustomHostNameResolver()
+
/** executed once before all specs are executed **/
def setupSpec() {
wireMockServer.start()
port = wireMockServer.getMappedPort(8080)
- }
-
- /** executed once after all specs are executed **/
- def cleanupSpec() {
- wireMockServer.stop()
+ registerCustomDnsResolver()
}
/* executed before every single spec */
-
def setup() {
myConfig = new Configuration()
brokenHttpLinksChecker = new BrokenHttpLinksChecker( myConfig )
@@ -49,6 +51,36 @@ class BrokenHttpLinksCheckerSpec extends Specification {
collector = new SingleCheckResults()
}
+
+ /** executed once after all specs are executed **/
+ def cleanupSpec() {
+ wireMockServer.stop()
+ }
+
+
+ // Custom method to register the DNS resolver
+ private void registerCustomDnsResolver() {
+ try {
+ Field implField = InetAddress.class.getDeclaredField("impl");
+ implField.setAccessible(true);
+ Object currentImpl = implField.get(null);
+
+ Proxy newImpl = (Proxy) Proxy.newProxyInstance(
+ currentImpl.getClass().getClassLoader(),
+ currentImpl.getClass().getInterfaces(),
+ (proxy, method, args) -> {
+ if ("lookupAllHostAddr".equals(method.getName()) && args.length == 1 && args[0] instanceof String) {
+ return customHostNameResolver.resolve((String) args[0]);
+ }
+ return method.invoke(currentImpl, args);
+ }
+ );
+
+ implField.set(null, newImpl);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to register custom DNS resolver", e);
+ }
+ }
/**
* checking for internet connectivity is a somewhat brittle - as there's no such thing as "the internet"
* (the checker will most likely use google.com as a proxy for "internet"
@@ -80,7 +112,7 @@ class BrokenHttpLinksCheckerSpec extends Specification {
def "one syntactically correct http URL is ok"() {
given: "an HTML page with a single correct anchor/link"
String HTML = """$HtmlConst.HTML_HEAD
- google
+ google
$HtmlConst.HTML_END """
htmlPage = new HtmlPage(HTML)
diff --git a/htmlSanityCheck-core/src/test/java/org/aim42/htmlsanitycheck/test/dns/CustomHostNameResolver.java b/htmlSanityCheck-core/src/test/java/org/aim42/htmlsanitycheck/test/dns/CustomHostNameResolver.java
new file mode 100644
index 00000000..81d65de0
--- /dev/null
+++ b/htmlSanityCheck-core/src/test/java/org/aim42/htmlsanitycheck/test/dns/CustomHostNameResolver.java
@@ -0,0 +1,36 @@
+package org.aim42.htmlsanitycheck.test.dns;
+
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class CustomHostNameResolver {
+
+ public static final String WIREMOCK_HOST = "my.custom.mocked.host";
+ private static Object originalResolver;
+
+ static {
+ try {
+ Field implField = InetAddress.class.getDeclaredField("impl");
+ implField.setAccessible(true);
+ originalResolver = implField.get(null);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to setup fallback DNS resolver", e);
+ }
+ }
+
+ public InetAddress[] resolve(String hostname) throws UnknownHostException {
+ // Custom DNS resolution logic
+ if (WIREMOCK_HOST.equals(hostname)) {
+ return new InetAddress[]{InetAddress.getByAddress("localhost", new byte[]{127, 0, 0, 1})};
+ }
+ // Fallback to original resolver using reflection
+ try {
+ return (InetAddress[]) originalResolver.getClass()
+ .getMethod("lookupAllHostAddr", String.class)
+ .invoke(originalResolver, hostname);
+ } catch (Exception e) {
+ throw new UnknownHostException("Failed to resolve hostname: " + hostname);
+ }
+ }
+}
\ No newline at end of file