diff --git a/wkd-java-cli/build.gradle b/wkd-java-cli/build.gradle index aa04d8b..f686ac0 100644 --- a/wkd-java-cli/build.gradle +++ b/wkd-java-cli/build.gradle @@ -27,6 +27,8 @@ dependencies { // Logging testImplementation "ch.qos.logback:logback-classic:$logbackVersion" implementation 'org.slf4j:slf4j-nop:1.7.36' + + testImplementation project(":wkd-test-suite") } test { diff --git a/wkd-java-cli/src/main/java/pgp/wkd/cli/CertNotFetchableException.java b/wkd-java-cli/src/main/java/pgp/wkd/cli/CertNotFetchableException.java new file mode 100644 index 0000000..5da94bb --- /dev/null +++ b/wkd-java-cli/src/main/java/pgp/wkd/cli/CertNotFetchableException.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package pgp.wkd.cli; + +public class CertNotFetchableException extends RuntimeException { + + public static final int ERROR_CODE = 3; + + public CertNotFetchableException(String message) { + super(message); + } + + public CertNotFetchableException(String message, Throwable e) { + super(message, e); + } +} diff --git a/wkd-java-cli/src/main/java/pgp/wkd/cli/MissingUserIdException.java b/wkd-java-cli/src/main/java/pgp/wkd/cli/MissingUserIdException.java index d3ba9eb..89c2c46 100644 --- a/wkd-java-cli/src/main/java/pgp/wkd/cli/MissingUserIdException.java +++ b/wkd-java-cli/src/main/java/pgp/wkd/cli/MissingUserIdException.java @@ -8,9 +8,11 @@ package pgp.wkd.cli; * Exception that gets thrown when an OpenPGP certificate is not carrying a User-ID binding for the email address * that was used to look the certificate up via WKD. */ -public class MissingUserIdException extends Exception { +public class MissingUserIdException extends RuntimeException { - public MissingUserIdException() { - super(); + public static final int ERROR_CODE = 7; + + public MissingUserIdException(String message) { + super(message); } } diff --git a/wkd-java-cli/src/main/java/pgp/wkd/cli/WKDCLI.java b/wkd-java-cli/src/main/java/pgp/wkd/cli/WKDCLI.java index 91b3b5d..29b2cd2 100644 --- a/wkd-java-cli/src/main/java/pgp/wkd/cli/WKDCLI.java +++ b/wkd-java-cli/src/main/java/pgp/wkd/cli/WKDCLI.java @@ -24,6 +24,19 @@ public class WKDCLI { public static int execute(String[] args) { return new CommandLine(WKDCLI.class) + .setExitCodeExceptionMapper(new CommandLine.IExitCodeExceptionMapper() { + @Override + public int getExitCode(Throwable exception) { + if (exception instanceof MissingUserIdException) { + return MissingUserIdException.ERROR_CODE; + } else if (exception instanceof CertNotFetchableException) { + return CertNotFetchableException.ERROR_CODE; + } + + // Others get mapped to 1 + return 1; + } + }) .setCommandName("wkdcli") .execute(args); } diff --git a/wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java b/wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java index 265cc11..d6529c6 100644 --- a/wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java +++ b/wkd-java-cli/src/main/java/pgp/wkd/cli/command/Fetch.java @@ -12,6 +12,7 @@ import pgp.wkd.AbstractWKDFetcher; import pgp.wkd.HttpUrlConnectionWKDFetcher; import pgp.wkd.WKDAddress; import pgp.wkd.WKDAddressHelper; +import pgp.wkd.cli.CertNotFetchableException; import pgp.wkd.cli.MissingUserIdException; import picocli.CommandLine; @@ -40,7 +41,7 @@ public class Fetch implements Runnable { ) boolean armor = false; - AbstractWKDFetcher fetcher = new HttpUrlConnectionWKDFetcher(); + public static AbstractWKDFetcher fetcher = new HttpUrlConnectionWKDFetcher(); @Override public void run() { @@ -65,7 +66,7 @@ public class Fetch implements Runnable { } } if (!containsEmail) { - throw new MissingUserIdException(); + throw new MissingUserIdException("Fetched certificate does not contain email address " + email); } if (armor) { @@ -77,12 +78,7 @@ public class Fetch implements Runnable { } } catch (IOException e) { - System.err.println("Could not fetch certificate."); - e.printStackTrace(); - System.exit(1); - } catch (MissingUserIdException e) { - System.err.println("Fetched certificate does not contain email address " + email); - System.exit(1); + throw new CertNotFetchableException("Certificate cannot be fetched.", e); } } } diff --git a/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/DirectoryBasedWkdFetcher.java b/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/DirectoryBasedWkdFetcher.java new file mode 100644 index 0000000..db0d7a3 --- /dev/null +++ b/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/DirectoryBasedWkdFetcher.java @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package pgp.wkd.cli.test_suite; + +import pgp.wkd.AbstractWKDFetcher; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.Path; + +public class DirectoryBasedWkdFetcher extends AbstractWKDFetcher { + + // The directory containing the .well-known subdirectory + private final Path rootPath; + + public DirectoryBasedWkdFetcher(Path rootPath) { + this.rootPath = rootPath; + } + + @Override + protected InputStream fetchUri(URI uri) throws IOException { + String path = uri.getPath(); + File file = rootPath.resolve(path.substring(1)).toFile(); // get rid of leading slash at start of path + FileInputStream fileIn = new FileInputStream(file); + return fileIn; + } +} diff --git a/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/TestSuiteTestRunner.java b/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/TestSuiteTestRunner.java new file mode 100644 index 0000000..a1718c4 --- /dev/null +++ b/wkd-java-cli/src/test/java/pgp/wkd/cli/test_suite/TestSuiteTestRunner.java @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package pgp.wkd.cli.test_suite; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import pgp.wkd.cli.WKDCLI; +import pgp.wkd.cli.command.Fetch; +import pgp.wkd.test_suite.TestCase; +import pgp.wkd.test_suite.TestSuite; +import pgp.wkd.test_suite.TestSuiteGenerator; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class TestSuiteTestRunner { + + private static TestSuite suite; + + @BeforeAll + public static void setup() throws Exception { + Path tempDir = Files.createTempDirectory("wkd-test"); + tempDir.toFile().deleteOnExit(); + Fetch.fetcher = new DirectoryBasedWkdFetcher(tempDir); + + String domain = "example.com"; + + TestSuiteGenerator generator = new TestSuiteGenerator(domain); + suite = generator.generateTestSuiteInDirectory(tempDir.toFile(), TestSuiteGenerator.Method.direct); + } + + @Test + public void runTestsAgainstTestSuite() { + for (TestCase testCase : suite.getTestCases()) { + System.out.println("Executing test " + testCase.getTestTitle()); + int exitCode = WKDCLI.execute(new String[] { + "fetch", "--armor", testCase.getLookupMailAddress() + }); + + if (testCase.isExpectSuccess()) { + assertEquals(0, exitCode); + } else { + assertNotEquals(0, exitCode); + } + } + } +} diff --git a/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestCase.java b/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestCase.java index 7306256..c76bc86 100644 --- a/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestCase.java +++ b/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestCase.java @@ -24,4 +24,28 @@ public class TestCase { this.certificatePath = certificatePath.toString(); this.lookupUri = lookupUri; } + + public boolean isExpectSuccess() { + return expectSuccess; + } + + public String getTestTitle() { + return testTitle; + } + + public String getTestDescription() { + return testDescription; + } + + public String getLookupMailAddress() { + return lookupMailAddress; + } + + public String getCertificatePath() { + return certificatePath; + } + + public URI getLookupUri() { + return lookupUri; + } } diff --git a/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestSuite.java b/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestSuite.java index e0abb44..15f8b38 100644 --- a/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestSuite.java +++ b/wkd-test-suite/src/main/java/pgp/wkd/test_suite/TestSuite.java @@ -4,6 +4,7 @@ package pgp.wkd.test_suite; +import java.util.ArrayList; import java.util.List; public class TestSuite { @@ -15,4 +16,12 @@ public class TestSuite { this.version = version; this.testCases = testCases; } + + public List getTestCases() { + return new ArrayList<>(testCases); + } + + public String getVersion() { + return version; + } }