diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java
index 5ff2ad56..840a90c6 100644
--- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java
+++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/check/BrokenHttpLinksChecker.java
@@ -169,10 +169,10 @@ else if (Web.HTTP_REDIRECT_CODES.contains(responseCode)) {
firstConnection.disconnect();
} catch (UnknownHostException exception) {
- Finding unknownHostFinding = new Finding("Unknown host with href=" + href);
+ Finding unknownHostFinding = new Finding("Unknown host with href=" + href, exception);
getCheckingResults().addFinding(unknownHostFinding);
} catch (IOException exception) {
- Finding someException = new Finding("exception " + exception + " with href=" + href);
+ Finding someException = new Finding("exception " + exception + " with href=" + href, exception);
getCheckingResults().addFinding(someException);
}
}
diff --git a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java
index e65dbeb6..8a26bf44 100644
--- a/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java
+++ b/htmlSanityCheck-core/src/main/java/org/aim42/htmlsanitycheck/collect/Finding.java
@@ -6,6 +6,7 @@
import lombok.Setter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -22,6 +23,7 @@ public class Finding {
// suggestions are ordered: getAt(0) yields the best, getAt(1) the second and so forth
@Setter
List suggestions;
+ Throwable throwable;
public Finding() {
this("");
@@ -34,14 +36,18 @@ public Finding() {
* @param whatIsTheProblem An explanation of what went wrong (i.e., name of the missing file)
*/
public Finding(String whatIsTheProblem) {
- this(whatIsTheProblem, 1, new ArrayList<>(3));
+ this(whatIsTheProblem, 1, new ArrayList<>(3), null);
+ }
+
+ public Finding(final String whatIsTheProblem, final Throwable throwable) {
+ this(whatIsTheProblem, 1, new ArrayList<>(1), throwable);
}
/**
* Finding with explanation and several occurrences
*/
public Finding(String whatIsTheProblem, int nrOfOccurrences) {
- this(whatIsTheProblem, nrOfOccurrences, new ArrayList<>(3));
+ this(whatIsTheProblem, nrOfOccurrences, new ArrayList<>(3), null);
}
@@ -49,13 +55,17 @@ public Finding(String whatIsTheProblem, int nrOfOccurrences) {
* Most general constructor:
* create Finding with explanation and nrOfOccurrences
*
- * @param whatIsTheProblem An explanation of what went wrong (i.e. name of missing file)
+ * @param whatIsTheProblem An explanation of what went wrong (i.e., name of the missing file).
+ * @param nrOfOccurrences The number of occurrences of a specific issue or event.
+ * @param suggestions A list of suggestions related to resolving or addressing the issue.
+ * @param throwable The throwable instance representing an exception or error related to this occurrence.
*/
- public Finding(String whatIsTheProblem, int nrOfOccurrences, List suggestions) {
+ public Finding(String whatIsTheProblem, int nrOfOccurrences,
+ List suggestions, Throwable throwable) {
this.whatIsTheProblem = whatIsTheProblem;
this.nrOfOccurrences = nrOfOccurrences;
this.suggestions = suggestions;
-
+ this.throwable = throwable;
}
/**
@@ -65,15 +75,20 @@ public Finding(String whatIsTheProblem, int nrOfOccurrences, List sugges
* @param suggestions what could have been meant
*/
public Finding(String whatIsTheProblem, List suggestions) {
- this(whatIsTheProblem, 1, suggestions);
+ this(whatIsTheProblem, 1, suggestions, null);
}
@Override
public String toString() {
String refCount = (nrOfOccurrences > 1) ? String.format(" (reference count: %d)", nrOfOccurrences) : "";
String suggestionStr = (!suggestions.isEmpty()) ? "\n (Suggestions: " + String.join(",", suggestions) + ")" : "";
+ String stackTrace = (null != throwable)
+ ? "\nStackTrace:\n\t" + String.join("\n\t", Arrays.stream(throwable.getStackTrace())
+ .map(StackTraceElement::toString)
+ .toArray(String[]::new))
+ : "";
- return whatIsTheProblem + refCount + (suggestionStr.isEmpty() ? "" : suggestionStr);
+ return whatIsTheProblem + refCount + suggestionStr + stackTrace;
}
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 0e102db2..41904de7 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
@@ -275,6 +275,27 @@ class BrokenHttpLinksCheckerSpec extends Specification {
collector?.getFindings()?.first()?.whatIsTheProblem?.contains("suspicious")
}
+
+ def "expect an unknown host exception"() {
+ given: "an HTML page with a link to a non-resolvable hostname"
+ String unknownHost = "http://nonexistent-host.fake"
+ String HTML = """$HtmlConst.HTML_HEAD
+ Broken Link
+ $HtmlConst.HTML_END """
+
+ htmlPage = new HtmlPage(HTML)
+
+ when: "the page is checked"
+ collector = brokenHttpLinksChecker.performCheck(htmlPage)
+
+ then: "the exception is caught and an appropriate problem is recorded"
+ collector.getFindings()?.size() == 1
+
+ and: "the problem describes the unknown host exception"
+ collector.getFindings()?.first()?.whatIsTheProblem?.contains("Unknown host with href=")
+ collector.getFindings()?.first()?.whatIsTheProblem?.contains("nonexistent-host.fake")
+ collector.getFindings()?.first()?.throwable instanceof UnknownHostException
+ }
}
/************************************************************************