Skip to content

Commit

Permalink
Add Findings with Throwable in exception contexts
Browse files Browse the repository at this point in the history
as we would like to be able to check more detailed
error conditions when the problems occur (#270).

Improve JavaDocs also (#343).
  • Loading branch information
ascheman committed Dec 14, 2024
1 parent 63bc92e commit 58afbe7
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.Setter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
Expand All @@ -18,14 +19,11 @@
public class Finding {

String whatIsTheProblem; // i.e., which image is missing, which link/anchor is undefined
int nrOfOccurrences;// how often does this specific finding occur in the checked-page
int nrOfOccurrences; // how often does this specific finding occur in the checked-page
// suggestions are ordered: getAt(0) yields the best, getAt(1) the second and so forth
@Setter
List<String> suggestions;

public Finding() {
this("");
}
Throwable throwable;

/**
* No finding should exist without giving an explanation ("whatIsTheProblem")
Expand All @@ -34,46 +32,68 @@ 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);
}

/**
* Finding with explanation and several occurrences
* Finding with explanation and several occurrences.
*
* @param whatIsTheProblem An explanation of what went wrong (i.e., name of the missing file).
* @param throwable The throwable instance representing an exception or error related to this occurrence.
*/
public Finding(String whatIsTheProblem, int nrOfOccurrences) {
this(whatIsTheProblem, nrOfOccurrences, new ArrayList<>(3));
public Finding(final String whatIsTheProblem, final Throwable throwable) {
this(whatIsTheProblem, 1, new ArrayList<>(1), throwable);
}

/**
* Finding with explanation and several occurrences.
*
* @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.
*/
public Finding(String whatIsTheProblem, int nrOfOccurrences) {
this(whatIsTheProblem, nrOfOccurrences, new ArrayList<>(3), null);
}

/**
* Most general constructor:
* create Finding with explanation and nrOfOccurrences
* Finding with explanation and several occurrences, as well as suggestions.
*
* @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.
*/
public Finding(String whatIsTheProblem, int nrOfOccurrences, List<String> suggestions) {
this.whatIsTheProblem = whatIsTheProblem;
this.nrOfOccurrences = nrOfOccurrences;
this.suggestions = suggestions;

this(whatIsTheProblem, nrOfOccurrences, suggestions, null);
}

/**
* Create Finding with explanation and suggestions
* Most general constructor: Create Finding with all attributes.
*
* @param whatIsTheProblem explanation what went wrong
* @param suggestions what could have been meant
* @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, List<String> suggestions) {
this(whatIsTheProblem, 1, suggestions);
public Finding(String whatIsTheProblem, int nrOfOccurrences,
List<String> suggestions, Throwable throwable) {
this.whatIsTheProblem = whatIsTheProblem;
this.nrOfOccurrences = nrOfOccurrences;
this.suggestions = suggestions;
this.throwable = throwable;
}


@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;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
<a href="${unknownHost}">Broken Link</a>
$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
}
}

/************************************************************************
Expand Down

0 comments on commit 58afbe7

Please sign in to comment.