diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java index 1d54212..87d2512 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/PGPCertificateDirectory.java @@ -15,6 +15,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; @@ -46,13 +48,17 @@ public class PGPCertificateDirectory if (!openPgpV4FingerprintPattern.matcher(fingerprint).matches()) { throw new BadNameException(); } - return backend.readByFingerprint(fingerprint); + Certificate certificate = backend.readByFingerprint(fingerprint); + if (certificate == null) { + throw new NoSuchElementException(); + } + return certificate; } @Override public Certificate getByFingerprintIfChanged(String fingerprint, long tag) throws IOException, BadNameException, BadDataException { - if (tag != backend.getTagForFingerprint(fingerprint)) { + if (!Objects.equals(tag, backend.getTagForFingerprint(fingerprint))) { return getByFingerprint(fingerprint); } return null; @@ -66,13 +72,13 @@ public class PGPCertificateDirectory if (keyMaterial != null) { return keyMaterial.asCertificate(); } - return null; + throw new NoSuchElementException(); } @Override public Certificate getBySpecialNameIfChanged(String specialName, long tag) throws IOException, BadNameException, BadDataException { - if (tag != backend.getTagForSpecialName(specialName)) { + if (!Objects.equals(tag, backend.getTagForSpecialName(specialName))) { return getBySpecialName(specialName); } return null; @@ -121,7 +127,11 @@ public class PGPCertificateDirectory @Override public KeyMaterial getTrustRoot() throws IOException, BadDataException { try { - return backend.readBySpecialName(SpecialNames.TRUST_ROOT); + KeyMaterial keyMaterial = backend.readBySpecialName(SpecialNames.TRUST_ROOT); + if (keyMaterial == null) { + throw new NoSuchElementException(); + } + return keyMaterial; } catch (BadNameException e) { throw new AssertionError("'" + SpecialNames.TRUST_ROOT + "' is implementation MUST"); } diff --git a/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java b/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java index 89e52ba..08ac356 100644 --- a/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java +++ b/pgp-cert-d-java/src/main/java/pgp/cert_d/backend/FileBasedCertificateDirectoryBackend.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; import java.util.regex.Pattern; /** @@ -348,7 +349,7 @@ public class FileBasedCertificateDirectoryBackend implements PGPCertificateDirec private Long getTag(File file) throws IOException { if (!file.exists()) { - throw new IllegalArgumentException("File MUST exist."); + throw new NoSuchElementException(); } Path path = file.toPath(); BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); diff --git a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java index 4ffb865..93ff6db 100644 --- a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java +++ b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateDirectoryTest.java @@ -31,6 +31,7 @@ import java.nio.file.Files; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; +import java.util.NoSuchElementException; import java.util.Set; import java.util.stream.Stream; @@ -68,6 +69,55 @@ public class PGPCertificateDirectoryTest { Arguments.of(Named.of("FileBasedCertificateDirectory", fileBased))); } + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentCertByFingerprintThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getByFingerprint("0000000000000000000000000000000000000000")); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentCertByFingerprintIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getByFingerprintIfChanged("0000000000000000000000000000000000000000", 12)); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentCertBySpecialNameThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getBySpecialName(SpecialNames.TRUST_ROOT)); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentCertBySpecialNameIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getBySpecialNameIfChanged(SpecialNames.TRUST_ROOT, 12)); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentTrustRootThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getTrustRoot()); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentTrustRootIfChangedThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getTrustRootCertificateIfChanged(12)); + } + + @ParameterizedTest + @MethodSource("provideTestSubjects") + public void getNonExistentTrustRootCertificateThrowsNoSuchElementException(PGPCertificateDirectory directory) { + assertThrows(NoSuchElementException.class, () -> + directory.getTrustRootCertificate()); + } + @ParameterizedTest @MethodSource("provideTestSubjects") public void lockDirectoryAndTryInsertWillFail(PGPCertificateDirectory directory) @@ -130,7 +180,7 @@ public class PGPCertificateDirectoryTest { @MethodSource("provideTestSubjects") public void testInsertAndGetSingleCert(PGPCertificateDirectory directory) throws BadDataException, IOException, InterruptedException, BadNameException { - assertNull(directory.getByFingerprint(CEDRIC_FP), "Empty directory MUST NOT contain certificate"); + assertThrows(NoSuchElementException.class, () -> directory.getByFingerprint(CEDRIC_FP), "Empty directory MUST NOT contain certificate"); Certificate certificate = directory.insert(TestKeys.getCedricCert(), merger); assertEquals(CEDRIC_FP, certificate.getFingerprint(), "Fingerprint of inserted cert MUST match"); @@ -148,7 +198,7 @@ public class PGPCertificateDirectoryTest { @MethodSource("provideTestSubjects") public void testInsertAndGetTrustRootAndCert(PGPCertificateDirectory directory) throws BadDataException, IOException, InterruptedException { - assertNull(directory.getTrustRoot()); + assertThrows(NoSuchElementException.class, () -> directory.getTrustRoot()); KeyMaterial trustRootMaterial = directory.insertTrustRoot( TestKeys.getHarryKey(), merger); @@ -188,6 +238,7 @@ public class PGPCertificateDirectoryTest { assertNotNull(directory.getTrustRootCertificateIfChanged(tag + 1)); Long oldTag = tag; + Thread.sleep(10); // "update" key trustRootMaterial = directory.insertTrustRoot( TestKeys.getHarryKey(), merger); @@ -241,10 +292,12 @@ public class PGPCertificateDirectoryTest { Long oldTag = tag; + Thread.sleep(10); // Change the file on disk directly, this invalidates the tag due to changed modification date File certFile = resolver.getCertFileByFingerprint(certificate.getFingerprint()); FileOutputStream fileOut = new FileOutputStream(certFile); Streams.pipeAll(certificate.getInputStream(), fileOut); + fileOut.write("\n".getBytes()); fileOut.close(); // Old invalidated tag indicates a change, so the modified certificate is returned diff --git a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java index 56fdac6..79b5fed 100644 --- a/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java +++ b/pgp-cert-d-java/src/test/java/pgp/cert_d/PGPCertificateStoreAdapterTest.java @@ -17,6 +17,7 @@ import pgp.certificate_store.exception.BadNameException; import java.io.IOException; import java.util.Iterator; import java.util.List; +import java.util.NoSuchElementException; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -52,7 +53,7 @@ public class PGPCertificateStoreAdapterTest { @Test public void testInsertGetCertificate() throws BadDataException, IOException, InterruptedException, BadNameException { - assertNull(adapter.getCertificate(TestKeys.CEDRIC_FP)); + assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(TestKeys.CEDRIC_FP)); assertFalse(adapter.getCertificates().hasNext()); Certificate certificate = adapter.insertCertificate(TestKeys.getCedricCert(), merger); @@ -70,7 +71,7 @@ public class PGPCertificateStoreAdapterTest { @Test public void testInsertGetTrustRoot() throws BadDataException, BadNameException, IOException, InterruptedException { - assertNull(adapter.getCertificate(SpecialNames.TRUST_ROOT)); + assertThrows(NoSuchElementException.class, () -> adapter.getCertificate(SpecialNames.TRUST_ROOT)); Certificate certificate = adapter.insertCertificateBySpecialName( SpecialNames.TRUST_ROOT, TestKeys.getHarryKey(), merger);