Refactor tests (#1300)
This commit is contained in:
parent
d55ecae2b2
commit
408d2fad10
23 changed files with 288 additions and 365 deletions
39
.github/workflows/test-external-links.yml
vendored
Normal file
39
.github/workflows/test-external-links.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Test External Links
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
schedule:
|
||||
- cron: '0 5 * * *'
|
||||
jobs:
|
||||
test:
|
||||
name: Keycloak documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build
|
||||
run: mvn install -B -DskipTests
|
||||
- name: Test
|
||||
run: mvn test -B -pl tests -Dtest=ExternalLinksTest
|
||||
test-product:
|
||||
name: Product documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build
|
||||
run: mvn install -B -Dproduct
|
||||
- name: Test
|
||||
run: mvn test -B -Dproduct -pl tests -Dtest=ExternalLinksTest
|
|
@ -1,7 +1,7 @@
|
|||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Test
|
||||
name: Test Guides
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -11,7 +11,7 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
name: Build and test Keycloak documentation
|
||||
name: Keycloak documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -19,10 +19,12 @@ jobs:
|
|||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build with Maven
|
||||
run: mvn package -B
|
||||
- name: Build
|
||||
run: mvn install -B -DskipTests
|
||||
- name: Test
|
||||
run: mvn test -B -pl tests -Dtest=!ExternalLinksTest
|
||||
build-product:
|
||||
name: Build and test Product documentation
|
||||
name: Product documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
@ -30,5 +32,7 @@ jobs:
|
|||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Build with Maven
|
||||
run: mvn package -B -Dproduct
|
||||
- name: Build
|
||||
run: mvn install -B -Dproduct
|
||||
- name: Test
|
||||
run: mvn test -B -Dproduct -pl tests -Dtest=!ExternalLinksTest
|
6
pom.xml
6
pom.xml
|
@ -21,6 +21,7 @@
|
|||
<version.compiler.plugin>3.6.1</version.compiler.plugin>
|
||||
<version.jar.plugin>3.0.2</version.jar.plugin>
|
||||
<version.install.plugin>2.5.2</version.install.plugin>
|
||||
<version.surefire.plugin>2.22.2</version.surefire.plugin>
|
||||
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
|
@ -129,6 +130,11 @@
|
|||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>${version.plugin.dependency}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${version.surefire.plugin}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>header-maven-plugin</artifactId>
|
||||
|
|
|
@ -83,9 +83,9 @@
|
|||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.documentation.test.utils.DocUtils;
|
||||
import org.keycloak.documentation.test.utils.LinkUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractDocsTest {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(AbstractDocsTest.class);
|
||||
|
||||
protected static final Config config = new Config();
|
||||
|
||||
protected static LinkUtils linkUtils;
|
||||
protected static String body;
|
||||
protected static Boolean verbose = System.getProperties().containsKey("verbose") ? true : false;
|
||||
|
||||
protected DocUtils utils = new DocUtils();
|
||||
|
||||
protected File guideDir;
|
||||
protected String guideUrl;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
linkUtils = new LinkUtils(config, verbose);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws IOException {
|
||||
guideDir = config.getGuideDir(getGuideDirName());
|
||||
guideUrl = config.getGuideBaseUrl() + "/" + config.getGuideUrlFragment(getGuideDirName()) + "/";
|
||||
|
||||
if (body == null) {
|
||||
if (config.isLoadFromFiles()) {
|
||||
File htmlFile = config.getGuideHtmlFile(getGuideDirName());
|
||||
body = utils.readBody(htmlFile);
|
||||
} else {
|
||||
log.info("Loading guide from '" + guideUrl);
|
||||
body = utils.readBody(new URL(guideUrl));
|
||||
}
|
||||
|
||||
body = rewriteLinksToGuides(body);
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
linkUtils.close();
|
||||
body = null;
|
||||
}
|
||||
|
||||
public abstract String getGuideDirName();
|
||||
|
||||
@Test
|
||||
public void checkVariables() {
|
||||
Set<String> missingVariables = utils.findMissingVariables(body, config.getIgnoredVariables());
|
||||
checkFailures("Variables not found ", missingVariables);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkIncludes() {
|
||||
Set<String> missingIncludes = utils.findMissingIncludes(body);
|
||||
checkFailures("Includes not found", missingIncludes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkImages() {
|
||||
Set<String> failures = linkUtils.findInvalidImages(body, guideDir, guideUrl);
|
||||
checkFailures("Images not found", failures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkInternalAnchors() {
|
||||
Set<String> invalidInternalAnchors = linkUtils.findInvalidInternalAnchors(body);
|
||||
checkFailures("Internal anchors not found", invalidInternalAnchors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkExternalLinks() throws IOException {
|
||||
List<LinkUtils.InvalidLink> invalidLinks = linkUtils.findInvalidLinks(body, config.getIgnoredLinks(), config.getIgnoredLinkRedirects());
|
||||
if (!invalidLinks.isEmpty()) {
|
||||
Set<String> failures = new HashSet<>();
|
||||
for (LinkUtils.InvalidLink l : invalidLinks) {
|
||||
failures.add(l.getLink() + " (" + l.getError() + ")");
|
||||
}
|
||||
throw new Failures("Invalid links", failures);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFailures(String message, Set<String> failures) {
|
||||
if (!failures.isEmpty()) {
|
||||
throw new Failures(message, failures);
|
||||
}
|
||||
}
|
||||
|
||||
private String rewriteLinksToGuides(String body) throws MalformedURLException {
|
||||
if (config.isLoadFromFiles()) {
|
||||
for (Map.Entry<String, String> e : config.getGuideFragmentToDir().entrySet()) {
|
||||
String originalUrl = config.getDocBaseUrl() + "/" + e.getKey() + "/";
|
||||
String replacementUrl = config.getGuideHtmlFile(e.getValue()).toURI().toURL().toString();
|
||||
|
||||
body = body.replace("href=\"" + originalUrl, "href=\"" + replacementUrl);
|
||||
}
|
||||
} else {
|
||||
body = body.replace("href=\"" + config.getDocBaseUrl(), "href=\"" + config.getGuideBaseUrl());
|
||||
}
|
||||
return body;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class AuthorizationServicesTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "authorization_services";
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,8 @@ public class Config {
|
|||
|
||||
private static final Logger log = LogManager.getLogger(Config.class);
|
||||
|
||||
protected static final Config instance = new Config();
|
||||
|
||||
private File docsRootDir;
|
||||
|
||||
private List<String> ignoredLinkRedirects;
|
||||
|
@ -34,7 +36,11 @@ public class Config {
|
|||
private Map<String, String> guideDirToFragment;
|
||||
private Map<String, String> guideFragmentToDir;
|
||||
|
||||
public Config() {
|
||||
public static Config getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Config() {
|
||||
docsRootDir = findDocsRoot();
|
||||
ignoredLinkRedirects = loadConfig("/ignored-link-redirects");
|
||||
ignoredVariables = loadConfig("/ignored-variables");
|
||||
|
@ -171,7 +177,7 @@ public class Config {
|
|||
|
||||
private List<String> loadConfig(String resource) {
|
||||
try {
|
||||
return IOUtils.readLines(AbstractDocsTest.class.getResourceAsStream(resource), "utf-8");
|
||||
return IOUtils.readLines(Config.class.getResourceAsStream(resource), "utf-8");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -179,7 +185,7 @@ public class Config {
|
|||
|
||||
private Map<String, String> loadConfigMap(String resource) {
|
||||
try {
|
||||
List<String> lines = IOUtils.readLines(AbstractDocsTest.class.getResourceAsStream(resource), "utf-8");
|
||||
List<String> lines = IOUtils.readLines(Config.class.getResourceAsStream(resource), "utf-8");
|
||||
Map<String, String> m = new HashMap<>();
|
||||
for (String l : lines) {
|
||||
String[] s = l.split("=");
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.keycloak.documentation.test.utils.LinkUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class ExternalLinksTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.keycloak.documentation.test.Guides#guides()")
|
||||
public void checkExternalLinks(String guideName) throws IOException {
|
||||
Guide guide = new Guide(guideName);
|
||||
List<LinkUtils.InvalidLink> invalidLinks = LinkUtils.getInstance().findInvalidLinks(guide);
|
||||
if (!invalidLinks.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Broken links (" + invalidLinks.size() + "):");
|
||||
|
||||
for (LinkUtils.InvalidLink l : invalidLinks) {
|
||||
sb.append("\n\t\t- " + l.getLink() + " (" + l.getError() + ")");
|
||||
}
|
||||
|
||||
Assertions.fail(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Set;
|
||||
|
||||
public class Failures extends AssertionError {
|
||||
|
||||
private Set<String> failures;
|
||||
|
||||
public Failures(String error, Set<String> failures) {
|
||||
super(error);
|
||||
this.failures = failures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace() {
|
||||
printStackTrace(System.out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintStream s) {
|
||||
for (String f : failures) {
|
||||
s.println("* " + f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter s) {
|
||||
for (String f : failures) {
|
||||
s.println("* " + f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
public class GettingStartedTest extends AbstractDocsTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void skipOnCommunity() {
|
||||
Assume.assumeTrue("Skipping product OpenShift guide testing in community", System.getProperties().containsKey("product"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "getting_started";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.keycloak.documentation.test.utils.DocUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
public class Guide {
|
||||
|
||||
private static final Logger log = LogManager.getLogger(Guide.class);
|
||||
|
||||
protected DocUtils utils = new DocUtils();
|
||||
|
||||
private String guide;
|
||||
|
||||
private String body;
|
||||
|
||||
private File guideDir;
|
||||
private String guideUrl;
|
||||
|
||||
public Guide(String guide) throws IOException {
|
||||
this.guide = guide;
|
||||
|
||||
Config config = Config.getInstance();
|
||||
|
||||
guideDir = config.getGuideDir(guide);
|
||||
guideUrl = config.getGuideBaseUrl() + "/" + config.getGuideUrlFragment(guide) + "/";
|
||||
|
||||
if (body == null) {
|
||||
if (config.isLoadFromFiles()) {
|
||||
File htmlFile = config.getGuideHtmlFile(guide);
|
||||
body = utils.readBody(htmlFile);
|
||||
} else {
|
||||
log.info("Loading guide from '" + guideUrl);
|
||||
body = utils.readBody(new URL(guideUrl));
|
||||
}
|
||||
|
||||
body = rewriteLinksToGuides(config, body);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public File getDir() {
|
||||
return guideDir;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return guideUrl;
|
||||
}
|
||||
|
||||
private String rewriteLinksToGuides(Config config, String body) throws MalformedURLException {
|
||||
if (config.isLoadFromFiles()) {
|
||||
for (Map.Entry<String, String> e : config.getGuideFragmentToDir().entrySet()) {
|
||||
String originalUrl = config.getDocBaseUrl() + "/" + e.getKey() + "/";
|
||||
String replacementUrl = config.getGuideHtmlFile(e.getValue()).toURI().toURL().toString();
|
||||
|
||||
body = body.replace("href=\"" + originalUrl, "href=\"" + replacementUrl);
|
||||
}
|
||||
} else {
|
||||
body = body.replace("href=\"" + config.getDocBaseUrl(), "href=\"" + config.getGuideBaseUrl());
|
||||
}
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.keycloak.documentation.test.utils.DocUtils;
|
||||
import org.keycloak.documentation.test.utils.LinkUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
public class GuideTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.keycloak.documentation.test.Guides#guides()")
|
||||
public void checkVariables(String guideName) throws IOException {
|
||||
Set<String> missingVariables = DocUtils.findMissingVariables(new Guide(guideName));
|
||||
checkFailures("Variables not found ", missingVariables);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.keycloak.documentation.test.Guides#guides()")
|
||||
public void checkIncludes(String guideName) throws IOException {
|
||||
Set<String> missingIncludes = DocUtils.findMissingIncludes(new Guide(guideName));
|
||||
checkFailures("Includes not found", missingIncludes);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.keycloak.documentation.test.Guides#guides()")
|
||||
public void checkImages(String guideName) throws IOException {
|
||||
Set<String> failures = LinkUtils.getInstance().findInvalidImages(new Guide(guideName));
|
||||
checkFailures("Images not found", failures);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.keycloak.documentation.test.Guides#guides()")
|
||||
public void checkInternalAnchors(String guideName) throws IOException {
|
||||
Set<String> invalidInternalAnchors = LinkUtils.getInstance().findInvalidInternalAnchors(new Guide(guideName));
|
||||
checkFailures("Internal anchors not found", invalidInternalAnchors);
|
||||
}
|
||||
|
||||
private void checkFailures(String message, Set<String> failures) {
|
||||
if (!failures.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(message + " (" + failures.size() + "):");
|
||||
|
||||
for (String f : failures) {
|
||||
sb.append("\n\t\t- " + f);
|
||||
}
|
||||
|
||||
Assertions.fail(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class Guides {
|
||||
|
||||
private static String[] guides;
|
||||
static {
|
||||
boolean product = System.getProperties().containsKey("product");
|
||||
|
||||
List<String> g = new LinkedList<>();
|
||||
g.add("authorization_services");
|
||||
g.add("release_notes");
|
||||
g.add("securing_apps");
|
||||
g.add("server_admin");
|
||||
g.add("server_development");
|
||||
g.add("server_installation");
|
||||
g.add("upgrading");
|
||||
|
||||
if (product) {
|
||||
g.add("getting_started");
|
||||
g.add("openshift");
|
||||
}
|
||||
|
||||
guides = g.toArray(new String[g.size()]);
|
||||
}
|
||||
|
||||
public static String[] guides() {
|
||||
return guides;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
public class OpenShiftTest extends AbstractDocsTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void skipOnCommunity() {
|
||||
Assume.assumeTrue("Skipping product OpenShift guide testing in community", System.getProperties().containsKey("product"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "openshift";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class ReleaseNotesTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "release_notes";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class SecuringAppsTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "securing_apps";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class ServerAdminTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "server_admin";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class ServerDeveloperTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "server_development";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class ServerInstallationTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "server_installation";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package org.keycloak.documentation.test;
|
||||
|
||||
public class UpgradingTest extends AbstractDocsTest {
|
||||
|
||||
@Override
|
||||
public String getGuideDirName() {
|
||||
return "upgrading";
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,8 @@ package org.keycloak.documentation.test.utils;
|
|||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.keycloak.documentation.test.Config;
|
||||
import org.keycloak.documentation.test.Guide;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -16,7 +18,7 @@ import java.util.regex.Pattern;
|
|||
|
||||
public class DocUtils {
|
||||
|
||||
public String readBody(File htmlFile) throws IOException {
|
||||
public static String readBody(File htmlFile) throws IOException {
|
||||
String s = FileUtils.readFileToString(htmlFile, "utf-8");
|
||||
|
||||
Pattern p = Pattern.compile("<body.*?>(.*?)</body>.*?",Pattern.DOTALL);
|
||||
|
@ -26,7 +28,7 @@ public class DocUtils {
|
|||
return m.group(1);
|
||||
}
|
||||
|
||||
public String readBody(URL url) throws IOException {
|
||||
public static String readBody(URL url) throws IOException {
|
||||
HttpURLConnection connection = null;
|
||||
|
||||
try {
|
||||
|
@ -60,10 +62,11 @@ public class DocUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public Set<String> findMissingVariables(String body, List<String> ignoredVariables) {
|
||||
public static Set<String> findMissingVariables(Guide guide) {
|
||||
List<String> ignoredVariables = Config.getInstance().getIgnoredVariables();
|
||||
Set<String> missingVariables = new HashSet<>();
|
||||
Pattern p = Pattern.compile("[^$/=\n]\\{([^ }\"]*)}");
|
||||
Matcher m = p.matcher(body);
|
||||
Matcher m = p.matcher(guide.getBody());
|
||||
while (m.find()) {
|
||||
String key = m.group(1);
|
||||
if (!key.isEmpty() && !ignoredVariables.contains(key)) {
|
||||
|
@ -73,10 +76,10 @@ public class DocUtils {
|
|||
return missingVariables;
|
||||
}
|
||||
|
||||
public Set<String> findMissingIncludes(String body) {
|
||||
public static Set<String> findMissingIncludes(Guide guide) {
|
||||
Set<String> missingIncludes = new HashSet<>();
|
||||
Pattern p = Pattern.compile("Unresolved directive.*");
|
||||
Matcher m = p.matcher(body);
|
||||
Matcher m = p.matcher(guide.getBody());
|
||||
if (m.find()) {
|
||||
missingIncludes.add(m.group());
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
|
|||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
|
||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpStatus;
|
||||
|
@ -19,11 +17,6 @@ import org.apache.hc.core5.http.io.entity.EntityUtils;
|
|||
import org.apache.hc.core5.util.TimeValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class HttpUtils {
|
||||
|
||||
|
@ -86,7 +79,6 @@ public class HttpUtils {
|
|||
try {
|
||||
client.execute(method, responseHandler);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
response.setError("exception " + e.getMessage());
|
||||
response.setSuccess(false);
|
||||
}
|
||||
|
@ -104,50 +96,11 @@ public class HttpUtils {
|
|||
.disableRedirectHandling()
|
||||
.setConnectionManager(
|
||||
PoolingHttpClientConnectionManagerBuilder.create()
|
||||
.setSSLSocketFactory(new NoopSSLConnectionSocketFactory())
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static class NoopSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
|
||||
private static SSLContext sslContext;
|
||||
|
||||
static {
|
||||
try {
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(
|
||||
null,
|
||||
new X509TrustManager[] {
|
||||
new X509TrustManager() {
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
}
|
||||
},
|
||||
null
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public NoopSSLConnectionSocketFactory() {
|
||||
super(sslContext, new NoopHostnameVerifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifySession(String hostname, SSLSession sslSession) throws SSLException {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
|
||||
private boolean success;
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.apache.commons.io.FileUtils;
|
|||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.keycloak.documentation.test.Config;
|
||||
import org.keycloak.documentation.test.Guide;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -18,16 +19,18 @@ public class LinkUtils {
|
|||
|
||||
private static final Logger logger = LogManager.getLogger(LinkUtils.class);
|
||||
|
||||
private static final LinkUtils instance = new LinkUtils();
|
||||
|
||||
private HttpUtils http = new HttpUtils();
|
||||
private Config config;
|
||||
private File verifiedLinksCacheFile;
|
||||
private boolean verbose;
|
||||
private Map<String, Long> verifiedLinks;
|
||||
|
||||
public LinkUtils(Config config, boolean verbose) {
|
||||
this.config = config;
|
||||
this.verifiedLinksCacheFile = config.getVerifiedLinksCache();
|
||||
this.verbose = verbose;
|
||||
public static LinkUtils getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private LinkUtils() {
|
||||
this.verifiedLinksCacheFile = Config.getInstance().getVerifiedLinksCache();
|
||||
this.verifiedLinks = loadCheckedLinksCache();
|
||||
}
|
||||
|
||||
|
@ -35,15 +38,15 @@ public class LinkUtils {
|
|||
saveCheckedLinksCache();
|
||||
}
|
||||
|
||||
public Set<String> findInvalidInternalAnchors(String body) {
|
||||
public Set<String> findInvalidInternalAnchors(Guide guide) {
|
||||
Set<String> invalidInternalAnchors = new HashSet<>();
|
||||
Pattern p = Pattern.compile("<a href=\"([^ \"]*)[^>]*\">");
|
||||
Matcher m = p.matcher(body);
|
||||
Matcher m = p.matcher(guide.getBody());
|
||||
while (m.find()) {
|
||||
String link = m.group(1);
|
||||
|
||||
if (link.startsWith("#")) {
|
||||
if (!body.contains("id=\"" + link.substring(1) + "\"")) {
|
||||
if (!guide.getBody().contains("id=\"" + link.substring(1) + "\"")) {
|
||||
invalidInternalAnchors.add(link.substring(1));
|
||||
}
|
||||
}
|
||||
|
@ -51,14 +54,14 @@ public class LinkUtils {
|
|||
return invalidInternalAnchors;
|
||||
}
|
||||
|
||||
public List<InvalidLink> findInvalidLinks(String body, List<String> ignoredLinks, List<String> ignoredLinkRedirects) throws IOException {
|
||||
public List<InvalidLink> findInvalidLinks(Guide guide) throws IOException {
|
||||
List<InvalidLink> invalidLinks = new LinkedList<>();
|
||||
Pattern p = Pattern.compile("<a href=\"([^ \"]*)[^>]*\">");
|
||||
Matcher m = p.matcher(body);
|
||||
Matcher m = p.matcher(guide.getBody());
|
||||
while (m.find()) {
|
||||
String link = m.group(1);
|
||||
|
||||
if (verifyLink(link, ignoredLinks, invalidLinks)) {
|
||||
if (verifyLink(link, Config.getInstance().getIgnoredLinks(), invalidLinks)) {
|
||||
if (link.startsWith("http")) {
|
||||
String anchor = link.contains("#") ? link.split("#")[1] : null;
|
||||
String error = null;
|
||||
|
@ -66,7 +69,7 @@ public class LinkUtils {
|
|||
HttpUtils.Response response = anchor != null ? http.load(link) : http.isValid(link);
|
||||
|
||||
if (response.getRedirectLocation() != null) {
|
||||
if (!validRedirect(response.getRedirectLocation(), ignoredLinkRedirects)) {
|
||||
if (!validRedirect(response.getRedirectLocation(), Config.getInstance().getIgnoredLinkRedirects())) {
|
||||
error = "invalid redirect to " + response.getRedirectLocation();
|
||||
}
|
||||
} else if (response.isSuccess() && anchor != null) {
|
||||
|
@ -79,16 +82,8 @@ public class LinkUtils {
|
|||
|
||||
if (error == null) {
|
||||
verifiedLinks.put(link, System.currentTimeMillis());
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("[OK] " + link);
|
||||
}
|
||||
} else {
|
||||
invalidLinks.add(new InvalidLink(link, error));
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("[BAD] " + link);
|
||||
}
|
||||
}
|
||||
} else if (link.startsWith("file")) {
|
||||
File f = new File(new URL(link).getFile());
|
||||
|
@ -110,36 +105,28 @@ public class LinkUtils {
|
|||
return invalidLinks;
|
||||
}
|
||||
|
||||
public Set<String> findInvalidImages(String body, File guideDir, String guideUrl) {
|
||||
public Set<String> findInvalidImages(Guide guide) {
|
||||
Set<String> missingImages = new HashSet<>();
|
||||
Pattern p = Pattern.compile("<img src=\"([^ \"]*)[^>]*\"");
|
||||
Matcher m = p.matcher(body);
|
||||
Matcher m = p.matcher(guide.getBody());
|
||||
while (m.find()) {
|
||||
String image = m.group(1);
|
||||
if (config.isLoadFromFiles()) {
|
||||
File f = new File(guideDir, image);
|
||||
if (Config.getInstance().isLoadFromFiles()) {
|
||||
File f = new File(guide.getDir(), image);
|
||||
if (!f.isFile()) {
|
||||
missingImages.add(image);
|
||||
}
|
||||
} else {
|
||||
if (image.startsWith("./")) {
|
||||
image = guideUrl + image;
|
||||
image = guide.getUrl() + image;
|
||||
}
|
||||
|
||||
if (!verifiedLinks.containsKey(image)) {
|
||||
boolean valid = http.isValid(image).isSuccess();
|
||||
if (valid) {
|
||||
verifiedLinks.put(image, System.currentTimeMillis());
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("[OK] " + image);
|
||||
}
|
||||
} else {
|
||||
missingImages.add(image);
|
||||
|
||||
if (verbose) {
|
||||
System.out.println("[BAD] " + image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue