mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2025-09-10 10:49:48 +02:00
Initial commit
This commit is contained in:
commit
8e3ee6c284
90 changed files with 6086 additions and 0 deletions
|
@ -0,0 +1,49 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
public class DateParserTest {
|
||||
|
||||
@Test
|
||||
public void parseNotAfterDashReturnsEndOfTime() {
|
||||
assertEquals(DateParser.END_OF_TIME, DateParser.parseNotAfter("-"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNotBeforeDashReturnsBeginningOfTime() {
|
||||
assertEquals(DateParser.BEGINNING_OF_TIME, DateParser.parseNotBefore("-"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNotAfterNowReturnsNow() {
|
||||
assertEquals(new Date().getTime(), DateParser.parseNotAfter("now").getTime(), 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNotBeforeNowReturnsNow() {
|
||||
assertEquals(new Date().getTime(), DateParser.parseNotBefore("now").getTime(), 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNotAfterTimestamp() {
|
||||
String timestamp = "2019-10-24T23:48:29Z";
|
||||
Date date = DateParser.parseNotAfter(timestamp);
|
||||
assertEquals(timestamp, UTCUtil.formatUTCDate(date));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNotBeforeTimestamp() {
|
||||
String timestamp = "2019-10-29T18:36:45Z";
|
||||
Date date = DateParser.parseNotBefore(timestamp);
|
||||
assertEquals(timestamp, UTCUtil.formatUTCDate(date));
|
||||
}
|
||||
}
|
123
sop-java-picocli/src/test/java/sop/cli/picocli/FileUtilTest.java
Normal file
123
sop-java-picocli/src/test/java/sop/cli/picocli/FileUtilTest.java
Normal file
|
@ -0,0 +1,123 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.exception.SOPGPException;
|
||||
|
||||
public class FileUtilTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
FileUtil.setEnvironmentVariableResolver(new FileUtil.EnvironmentVariableResolver() {
|
||||
@Override
|
||||
public String resolveEnvironmentVariable(String name) {
|
||||
if (name.equals("test123")) {
|
||||
return "test321";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_ThrowsForNull() {
|
||||
assertThrows(NullPointerException.class, () -> FileUtil.getFile(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_prfxEnvAlreadyExists() throws IOException {
|
||||
File tempFile = new File("@ENV:test");
|
||||
tempFile.createNewFile();
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
assertThrows(SOPGPException.AmbiguousInput.class, () -> FileUtil.getFile("@ENV:test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_EnvironmentVariable() {
|
||||
File file = FileUtil.getFile("@ENV:test123");
|
||||
assertEquals("test321", file.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_nonExistentEnvVariable() {
|
||||
assertThrows(IllegalArgumentException.class, () -> FileUtil.getFile("@ENV:INVALID"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_prfxFdAlreadyExists() throws IOException {
|
||||
File tempFile = new File("@FD:1");
|
||||
tempFile.createNewFile();
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
assertThrows(SOPGPException.AmbiguousInput.class, () -> FileUtil.getFile("@FD:1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFile_prfxFdNotSupported() {
|
||||
assertThrows(IllegalArgumentException.class, () -> FileUtil.getFile("@FD:2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewFileOrThrow_throwsForNull() {
|
||||
assertThrows(NullPointerException.class, () -> FileUtil.createNewFileOrThrow(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewFileOrThrow_success() throws IOException {
|
||||
File dir = Files.createTempDirectory("test").toFile();
|
||||
dir.deleteOnExit();
|
||||
File file = new File(dir, "file");
|
||||
|
||||
assertFalse(file.exists());
|
||||
FileUtil.createNewFileOrThrow(file);
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewFileOrThrow_alreadyExists() throws IOException {
|
||||
File dir = Files.createTempDirectory("test").toFile();
|
||||
dir.deleteOnExit();
|
||||
File file = new File(dir, "file");
|
||||
|
||||
FileUtil.createNewFileOrThrow(file);
|
||||
assertTrue(file.exists());
|
||||
assertThrows(SOPGPException.OutputExists.class, () -> FileUtil.createNewFileOrThrow(file));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFileInputStream_success() throws IOException {
|
||||
File dir = Files.createTempDirectory("test").toFile();
|
||||
dir.deleteOnExit();
|
||||
File file = new File(dir, "file");
|
||||
|
||||
FileUtil.createNewFileOrThrow(file);
|
||||
FileInputStream inputStream = FileUtil.getFileInputStream(file.getAbsolutePath());
|
||||
assertNotNull(inputStream);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFileInputStream_fileNotFound() throws IOException {
|
||||
File dir = Files.createTempDirectory("test").toFile();
|
||||
dir.deleteOnExit();
|
||||
File file = new File(dir, "file");
|
||||
|
||||
assertThrows(SOPGPException.MissingInput.class,
|
||||
() -> FileUtil.getFileInputStream(file.getAbsolutePath()));
|
||||
}
|
||||
}
|
119
sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java
Normal file
119
sop-java-picocli/src/test/java/sop/cli/picocli/SOPTest.java
Normal file
|
@ -0,0 +1,119 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.SOP;
|
||||
import sop.operation.Armor;
|
||||
import sop.operation.Dearmor;
|
||||
import sop.operation.Decrypt;
|
||||
import sop.operation.DetachInbandSignatureAndMessage;
|
||||
import sop.operation.Encrypt;
|
||||
import sop.operation.ExtractCert;
|
||||
import sop.operation.GenerateKey;
|
||||
import sop.operation.Sign;
|
||||
import sop.operation.Verify;
|
||||
import sop.operation.Version;
|
||||
|
||||
public class SOPTest {
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(69)
|
||||
public void assertExitOnInvalidSubcommand() {
|
||||
SOP sop = mock(SOP.class);
|
||||
SopCLI.setSopInstance(sop);
|
||||
|
||||
SopCLI.main(new String[] {"invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void assertThrowsIfNoSOPBackendSet() {
|
||||
SopCLI.SOP_INSTANCE = null;
|
||||
// At this point, no SOP backend is set, so an InvalidStateException triggers exit(1)
|
||||
SopCLI.main(new String[] {"armor"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void UnsupportedSubcommandsTest() {
|
||||
SOP nullCommandSOP = new SOP() {
|
||||
@Override
|
||||
public Version version() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenerateKey generateKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtractCert extractCert() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sign sign() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Verify verify() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Encrypt encrypt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Decrypt decrypt() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Armor armor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dearmor dearmor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetachInbandSignatureAndMessage detachInbandSignatureAndMessage() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
SopCLI.setSopInstance(nullCommandSOP);
|
||||
|
||||
List<String[]> commands = new ArrayList<>();
|
||||
commands.add(new String[] {"armor"});
|
||||
commands.add(new String[] {"dearmor"});
|
||||
commands.add(new String[] {"decrypt"});
|
||||
commands.add(new String[] {"detach-inband-signature-and-message"});
|
||||
commands.add(new String[] {"encrypt"});
|
||||
commands.add(new String[] {"extract-cert"});
|
||||
commands.add(new String[] {"generate-key"});
|
||||
commands.add(new String[] {"sign"});
|
||||
commands.add(new String[] {"verify", "signature.asc", "cert.asc"});
|
||||
commands.add(new String[] {"version"});
|
||||
|
||||
for (String[] command : commands) {
|
||||
int exit = SopCLI.execute(command);
|
||||
assertEquals(69, exit, "Unexpected exit code for non-implemented command " + Arrays.toString(command) + ": " + exit);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import com.ginsberg.junit.exit.FailOnSystemExit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.Ready;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.enums.ArmorLabel;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Armor;
|
||||
|
||||
public class ArmorCmdTest {
|
||||
|
||||
private Armor armor;
|
||||
private SOP sop;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws SOPGPException.BadData {
|
||||
armor = mock(Armor.class);
|
||||
sop = mock(SOP.class);
|
||||
when(sop.armor()).thenReturn(armor);
|
||||
when(armor.data((InputStream) any())).thenReturn(nopReady());
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertLabelIsNotCalledByDefault() throws SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"armor"});
|
||||
verify(armor, never()).label(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertLabelIsCalledWhenFlaggedWithArgument() throws SOPGPException.UnsupportedOption {
|
||||
for (ArmorLabel label : ArmorLabel.values()) {
|
||||
SopCLI.main(new String[] {"armor", "--label", label.name()});
|
||||
verify(armor, times(1)).label(label);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertDataIsAlwaysCalled() throws SOPGPException.BadData {
|
||||
SopCLI.main(new String[] {"armor"});
|
||||
verify(armor, times(1)).data((InputStream) any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertThrowsForInvalidLabel() {
|
||||
SopCLI.main(new String[] {"armor", "--label", "Invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void ifLabelsUnsupportedExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(armor.label(any())).thenThrow(new SOPGPException.UnsupportedOption("Custom Armor labels are not supported."));
|
||||
|
||||
SopCLI.main(new String[] {"armor", "--label", "Sig"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void ifBadDataExit41() throws SOPGPException.BadData {
|
||||
when(armor.data((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
|
||||
SopCLI.main(new String[] {"armor"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@FailOnSystemExit
|
||||
public void ifNoErrorsNoExit() {
|
||||
when(sop.armor()).thenReturn(armor);
|
||||
|
||||
SopCLI.main(new String[] {"armor"});
|
||||
}
|
||||
|
||||
private static Ready nopReady() {
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.Ready;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Dearmor;
|
||||
|
||||
public class DearmorCmdTest {
|
||||
|
||||
private SOP sop;
|
||||
private Dearmor dearmor;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws IOException, SOPGPException.BadData {
|
||||
sop = mock(SOP.class);
|
||||
dearmor = mock(Dearmor.class);
|
||||
when(dearmor.data((InputStream) any())).thenReturn(nopReady());
|
||||
when(sop.dearmor()).thenReturn(dearmor);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
private static Ready nopReady() {
|
||||
return new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertDataIsCalled() throws IOException, SOPGPException.BadData {
|
||||
SopCLI.main(new String[] {"dearmor"});
|
||||
verify(dearmor, times(1)).data((InputStream) any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void assertBadDataCausesExit41() throws IOException, SOPGPException.BadData {
|
||||
when(dearmor.data((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException("invalid armor")));
|
||||
SopCLI.main(new String[] {"dearmor"});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,344 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import sop.DecryptionResult;
|
||||
import sop.ReadyWithResult;
|
||||
import sop.SOP;
|
||||
import sop.SessionKey;
|
||||
import sop.Verification;
|
||||
import sop.cli.picocli.DateParser;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Decrypt;
|
||||
import sop.util.HexUtil;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
public class DecryptCmdTest {
|
||||
|
||||
private Decrypt decrypt;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws SOPGPException.UnsupportedOption, SOPGPException.MissingArg, SOPGPException.BadData, SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.PasswordNotHumanReadable, SOPGPException.CannotDecrypt {
|
||||
SOP sop = mock(SOP.class);
|
||||
decrypt = mock(Decrypt.class);
|
||||
|
||||
when(decrypt.verifyNotAfter(any())).thenReturn(decrypt);
|
||||
when(decrypt.verifyNotBefore(any())).thenReturn(decrypt);
|
||||
when(decrypt.withPassword(any())).thenReturn(decrypt);
|
||||
when(decrypt.withSessionKey(any())).thenReturn(decrypt);
|
||||
when(decrypt.withKey((InputStream) any())).thenReturn(decrypt);
|
||||
when(decrypt.ciphertext((InputStream) any())).thenReturn(nopReadyWithResult());
|
||||
|
||||
when(sop.decrypt()).thenReturn(decrypt);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
private static ReadyWithResult<DecryptionResult> nopReadyWithResult() {
|
||||
return new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(OutputStream outputStream) {
|
||||
return new DecryptionResult(null, Collections.emptyList());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(19)
|
||||
public void missingArgumentsExceptionCausesExit19() throws SOPGPException.MissingArg, SOPGPException.BadData, SOPGPException.CannotDecrypt {
|
||||
when(decrypt.ciphertext((InputStream) any())).thenThrow(new SOPGPException.MissingArg("Missing arguments."));
|
||||
SopCLI.main(new String[] {"decrypt"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void badDataExceptionCausesExit41() throws SOPGPException.MissingArg, SOPGPException.BadData, SOPGPException.CannotDecrypt {
|
||||
when(decrypt.ciphertext((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"decrypt"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(31)
|
||||
public void assertNotHumanReadablePasswordCausesExit31() throws SOPGPException.PasswordNotHumanReadable,
|
||||
SOPGPException.UnsupportedOption {
|
||||
when(decrypt.withPassword(any())).thenThrow(new SOPGPException.PasswordNotHumanReadable());
|
||||
SopCLI.main(new String[] {"decrypt", "--with-password", "pretendThisIsNotReadable"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertWithPasswordPassesPasswordDown() throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"decrypt", "--with-password", "orange"});
|
||||
verify(decrypt, times(1)).withPassword("orange");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertUnsupportedWithPasswordCausesExit37() throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
when(decrypt.withPassword(any())).thenThrow(new SOPGPException.UnsupportedOption("Decrypting with password not supported."));
|
||||
SopCLI.main(new String[] {"decrypt", "--with-password", "swordfish"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertDefaultTimeRangesAreUsedIfNotOverwritten() throws SOPGPException.UnsupportedOption {
|
||||
Date now = new Date();
|
||||
SopCLI.main(new String[] {"decrypt"});
|
||||
verify(decrypt, times(1)).verifyNotBefore(DateParser.BEGINNING_OF_TIME);
|
||||
verify(decrypt, times(1)).verifyNotAfter(
|
||||
ArgumentMatchers.argThat(argument -> {
|
||||
// allow 1-second difference
|
||||
return Math.abs(now.getTime() - argument.getTime()) <= 1000;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertVerifyNotAfterAndBeforeDashResultsInMaxTimeRange() throws SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"decrypt", "--not-before", "-", "--not-after", "-"});
|
||||
verify(decrypt, times(1)).verifyNotBefore(DateParser.BEGINNING_OF_TIME);
|
||||
verify(decrypt, times(1)).verifyNotAfter(DateParser.END_OF_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertVerifyNotAfterAndBeforeNowResultsInMinTimeRange() throws SOPGPException.UnsupportedOption {
|
||||
Date now = new Date();
|
||||
ArgumentMatcher<Date> isMaxOneSecOff = argument -> {
|
||||
// Allow less than 1-second difference
|
||||
return Math.abs(now.getTime() - argument.getTime()) <= 1000;
|
||||
};
|
||||
|
||||
SopCLI.main(new String[] {"decrypt", "--not-before", "now", "--not-after", "now"});
|
||||
verify(decrypt, times(1)).verifyNotAfter(ArgumentMatchers.argThat(isMaxOneSecOff));
|
||||
verify(decrypt, times(1)).verifyNotBefore(ArgumentMatchers.argThat(isMaxOneSecOff));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void assertMalformedDateInNotBeforeCausesExit1() {
|
||||
// ParserException causes exit(1)
|
||||
SopCLI.main(new String[] {"decrypt", "--not-before", "invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void assertMalformedDateInNotAfterCausesExit1() {
|
||||
// ParserException causes exit(1)
|
||||
SopCLI.main(new String[] {"decrypt", "--not-after", "invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertUnsupportedNotAfterCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(decrypt.verifyNotAfter(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting upper signature date boundary not supported."));
|
||||
SopCLI.main(new String[] {"decrypt", "--not-after", "now"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertUnsupportedNotBeforeCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(decrypt.verifyNotBefore(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting lower signature date boundary not supported."));
|
||||
SopCLI.main(new String[] {"decrypt", "--not-before", "now"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(59)
|
||||
public void assertExistingSessionKeyOutFileCausesExit59() throws IOException {
|
||||
File tempFile = File.createTempFile("existing-session-key-", ".tmp");
|
||||
tempFile.deleteOnExit();
|
||||
SopCLI.main(new String[] {"decrypt", "--session-key-out", tempFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertWhenSessionKeyCannotBeExtractedExit37() throws IOException {
|
||||
Path tempDir = Files.createTempDirectory("session-key-out-dir");
|
||||
File tempFile = new File(tempDir.toFile(), "session-key");
|
||||
tempFile.deleteOnExit();
|
||||
SopCLI.main(new String[] {"decrypt", "--session-key-out", tempFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertSessionKeyIsProperlyWrittenToSessionKeyFile() throws SOPGPException.CannotDecrypt, SOPGPException.MissingArg, SOPGPException.BadData, IOException {
|
||||
byte[] key = "C7CBDAF42537776F12509B5168793C26B93294E5ABDFA73224FB0177123E9137".getBytes(StandardCharsets.UTF_8);
|
||||
when(decrypt.ciphertext((InputStream) any())).thenReturn(new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(OutputStream outputStream) {
|
||||
return new DecryptionResult(
|
||||
new SessionKey((byte) 9, key),
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
||||
});
|
||||
Path tempDir = Files.createTempDirectory("session-key-out-dir");
|
||||
File tempFile = new File(tempDir.toFile(), "session-key");
|
||||
tempFile.deleteOnExit();
|
||||
SopCLI.main(new String[] {"decrypt", "--session-key-out", tempFile.getAbsolutePath()});
|
||||
|
||||
ByteArrayOutputStream bytesInFile = new ByteArrayOutputStream();
|
||||
try (FileInputStream fileIn = new FileInputStream(tempFile)) {
|
||||
byte[] buf = new byte[32];
|
||||
int read = fileIn.read(buf);
|
||||
while (read != -1) {
|
||||
bytesInFile.write(buf, 0, read);
|
||||
read = fileIn.read(buf);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] algAndKey = new byte[key.length + 1];
|
||||
algAndKey[0] = (byte) 9;
|
||||
System.arraycopy(key, 0, algAndKey, 1, key.length);
|
||||
assertArrayEquals(algAndKey, bytesInFile.toByteArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(29)
|
||||
public void assertUnableToDecryptExceptionResultsInExit29() throws SOPGPException.CannotDecrypt, SOPGPException.MissingArg, SOPGPException.BadData {
|
||||
when(decrypt.ciphertext((InputStream) any())).thenThrow(new SOPGPException.CannotDecrypt());
|
||||
SopCLI.main(new String[] {"decrypt"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(3)
|
||||
public void assertNoSignatureExceptionCausesExit3() throws SOPGPException.CannotDecrypt, SOPGPException.MissingArg, SOPGPException.BadData {
|
||||
when(decrypt.ciphertext((InputStream) any())).thenReturn(new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(OutputStream outputStream) throws SOPGPException.NoSignature {
|
||||
throw new SOPGPException.NoSignature();
|
||||
}
|
||||
});
|
||||
SopCLI.main(new String[] {"decrypt"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void badDataInVerifyWithCausesExit41() throws IOException, SOPGPException.BadData {
|
||||
when(decrypt.verifyWithCert((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
File tempFile = File.createTempFile("verify-with-", ".tmp");
|
||||
SopCLI.main(new String[] {"decrypt", "--verify-with", tempFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(61)
|
||||
public void unexistentCertFileCausesExit61() {
|
||||
SopCLI.main(new String[] {"decrypt", "--verify-with", "invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(59)
|
||||
public void existingVerifyOutCausesExit59() throws IOException {
|
||||
File certFile = File.createTempFile("existing-verify-out-cert", ".asc");
|
||||
File existingVerifyOut = File.createTempFile("existing-verify-out", ".tmp");
|
||||
|
||||
SopCLI.main(new String[] {"decrypt", "--verify-out", existingVerifyOut.getAbsolutePath(), "--verify-with", certFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyOutIsProperlyWritten() throws IOException, SOPGPException.CannotDecrypt, SOPGPException.MissingArg, SOPGPException.BadData {
|
||||
File certFile = File.createTempFile("verify-out-cert", ".asc");
|
||||
File verifyOut = new File(certFile.getParent(), "verify-out.txt");
|
||||
if (verifyOut.exists()) {
|
||||
verifyOut.delete();
|
||||
}
|
||||
verifyOut.deleteOnExit();
|
||||
Date date = UTCUtil.parseUTCDate("2021-07-11T20:58:23Z");
|
||||
when(decrypt.ciphertext((InputStream) any())).thenReturn(new ReadyWithResult<DecryptionResult>() {
|
||||
@Override
|
||||
public DecryptionResult writeTo(OutputStream outputStream) {
|
||||
return new DecryptionResult(null, Collections.singletonList(
|
||||
new Verification(
|
||||
date,
|
||||
"1B66A707819A920925BC6777C3E0AFC0B2DFF862",
|
||||
"C8CD564EBF8D7BBA90611D8D071773658BF6BF86"))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
SopCLI.main(new String[] {"decrypt", "--verify-out", verifyOut.getAbsolutePath(), "--verify-with", certFile.getAbsolutePath()});
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(verifyOut))) {
|
||||
String line = reader.readLine();
|
||||
assertEquals("2021-07-11T20:58:23Z 1B66A707819A920925BC6777C3E0AFC0B2DFF862 C8CD564EBF8D7BBA90611D8D071773658BF6BF86", line);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertWithSessionKeyIsPassedDown() throws SOPGPException.UnsupportedOption {
|
||||
SessionKey key1 = new SessionKey((byte) 9, HexUtil.hexToBytes("C7CBDAF42537776F12509B5168793C26B93294E5ABDFA73224FB0177123E9137"));
|
||||
SessionKey key2 = new SessionKey((byte) 9, HexUtil.hexToBytes("FCA4BEAF687F48059CACC14FB019125CD57392BAB7037C707835925CBF9F7BCD"));
|
||||
SopCLI.main(new String[] {"decrypt",
|
||||
"--with-session-key", "9:C7CBDAF42537776F12509B5168793C26B93294E5ABDFA73224FB0177123E9137",
|
||||
"--with-session-key", "9:FCA4BEAF687F48059CACC14FB019125CD57392BAB7037C707835925CBF9F7BCD"});
|
||||
verify(decrypt).withSessionKey(key1);
|
||||
verify(decrypt).withSessionKey(key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void assertMalformedSessionKeysResultInExit1() {
|
||||
SopCLI.main(new String[] {"decrypt",
|
||||
"--with-session-key", "C7CBDAF42537776F12509B5168793C26B93294E5ABDFA73224FB0177123E9137"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void assertBadDataInKeysResultsInExit41() throws SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData, IOException {
|
||||
when(decrypt.withKey((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
File tempKeyFile = File.createTempFile("key-", ".tmp");
|
||||
SopCLI.main(new String[] {"decrypt", tempKeyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(61)
|
||||
public void assertKeyFileNotFoundCausesExit61() {
|
||||
SopCLI.main(new String[] {"decrypt", "nonexistent-key"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(67)
|
||||
public void assertProtectedKeyCausesExit67() throws IOException, SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData {
|
||||
when(decrypt.withKey((InputStream) any())).thenThrow(new SOPGPException.KeyIsProtected());
|
||||
File tempKeyFile = File.createTempFile("key-", ".tmp");
|
||||
SopCLI.main(new String[] {"decrypt", tempKeyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(13)
|
||||
public void assertUnsupportedAlgorithmExceptionCausesExit13() throws SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.BadData, IOException {
|
||||
when(decrypt.withKey((InputStream) any())).thenThrow(new SOPGPException.UnsupportedAsymmetricAlgo("Unsupported asymmetric algorithm.", new IOException()));
|
||||
File tempKeyFile = File.createTempFile("key-", ".tmp");
|
||||
SopCLI.main(new String[] {"decrypt", tempKeyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(23)
|
||||
public void verifyOutWithoutVerifyWithCausesExit23() {
|
||||
SopCLI.main(new String[] {"decrypt", "--verify-out", "out.file"});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.Ready;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.enums.EncryptAs;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Encrypt;
|
||||
|
||||
public class EncryptCmdTest {
|
||||
|
||||
Encrypt encrypt;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws IOException {
|
||||
encrypt = mock(Encrypt.class);
|
||||
when(encrypt.plaintext((InputStream) any())).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
SOP sop = mock(SOP.class);
|
||||
when(sop.encrypt()).thenReturn(encrypt);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(19)
|
||||
public void missingBothPasswordAndCertFileCauseExit19() {
|
||||
SopCLI.main(new String[] {"encrypt", "--no-armor"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void as_unsupportedEncryptAsCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(encrypt.mode(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting encryption mode not supported."));
|
||||
|
||||
SopCLI.main(new String[] {"encrypt", "--as", "Binary"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void as_invalidModeOptionCausesExit37() {
|
||||
SopCLI.main(new String[] {"encrypt", "--as", "invalid"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void as_modeIsPassedDown() throws SOPGPException.UnsupportedOption {
|
||||
for (EncryptAs mode : EncryptAs.values()) {
|
||||
SopCLI.main(new String[] {"encrypt", "--as", mode.name(), "--with-password", "0rbit"});
|
||||
verify(encrypt, times(1)).mode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(31)
|
||||
public void withPassword_notHumanReadablePasswordCausesExit31() throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
when(encrypt.withPassword("pretendThisIsNotReadable")).thenThrow(new SOPGPException.PasswordNotHumanReadable());
|
||||
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "pretendThisIsNotReadable"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void withPassword_unsupportedWithPasswordCausesExit37() throws SOPGPException.PasswordNotHumanReadable, SOPGPException.UnsupportedOption {
|
||||
when(encrypt.withPassword(any())).thenThrow(new SOPGPException.UnsupportedOption("Encrypting with password not supported."));
|
||||
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "orange"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void signWith_multipleTimesGetPassedDown() throws IOException, SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.KeyCannotSign, SOPGPException.BadData {
|
||||
File keyFile1 = File.createTempFile("sign-with-1-", ".asc");
|
||||
File keyFile2 = File.createTempFile("sign-with-2-", ".asc");
|
||||
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "password", "--sign-with", keyFile1.getAbsolutePath(), "--sign-with", keyFile2.getAbsolutePath()});
|
||||
verify(encrypt, times(2)).signWith((InputStream) any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(61)
|
||||
public void signWith_nonExistentKeyFileCausesExit61() {
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "admin", "--sign-with", "nonExistent.asc"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(67)
|
||||
public void signWith_keyIsProtectedCausesExit67() throws SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.KeyCannotSign, SOPGPException.BadData, IOException {
|
||||
when(encrypt.signWith((InputStream) any())).thenThrow(new SOPGPException.KeyIsProtected());
|
||||
File keyFile = File.createTempFile("sign-with", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", "--sign-with", keyFile.getAbsolutePath(), "--with-password", "starship"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(13)
|
||||
public void signWith_unsupportedAsymmetricAlgoCausesExit13() throws SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.KeyCannotSign, SOPGPException.BadData, IOException {
|
||||
when(encrypt.signWith((InputStream) any())).thenThrow(new SOPGPException.UnsupportedAsymmetricAlgo("Unsupported asymmetric algorithm.", new Exception()));
|
||||
File keyFile = File.createTempFile("sign-with", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "123456", "--sign-with", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(79)
|
||||
public void signWith_certCannotSignCausesExit1() throws IOException, SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.KeyCannotSign, SOPGPException.BadData {
|
||||
when(encrypt.signWith((InputStream) any())).thenThrow(new SOPGPException.KeyCannotSign());
|
||||
File keyFile = File.createTempFile("sign-with", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "dragon", "--sign-with", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void signWith_badDataCausesExit41() throws SOPGPException.KeyIsProtected, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.KeyCannotSign, SOPGPException.BadData, IOException {
|
||||
when(encrypt.signWith((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
File keyFile = File.createTempFile("sign-with", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "orange", "--sign-with", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(61)
|
||||
public void cert_nonExistentCertFileCausesExit61() {
|
||||
SopCLI.main(new String[] {"encrypt", "invalid.asc"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(13)
|
||||
public void cert_unsupportedAsymmetricAlgorithmCausesExit13() throws IOException, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.CertCannotEncrypt, SOPGPException.BadData {
|
||||
when(encrypt.withCert((InputStream) any())).thenThrow(new SOPGPException.UnsupportedAsymmetricAlgo("Unsupported asymmetric algorithm.", new Exception()));
|
||||
File certFile = File.createTempFile("cert", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", certFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(17)
|
||||
public void cert_certCannotEncryptCausesExit17() throws IOException, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.CertCannotEncrypt, SOPGPException.BadData {
|
||||
when(encrypt.withCert((InputStream) any())).thenThrow(new SOPGPException.CertCannotEncrypt("Certificate cannot encrypt.", new Exception()));
|
||||
File certFile = File.createTempFile("cert", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", certFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void cert_badDataCausesExit41() throws IOException, SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.CertCannotEncrypt, SOPGPException.BadData {
|
||||
when(encrypt.withCert((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
File certFile = File.createTempFile("cert", ".asc");
|
||||
SopCLI.main(new String[] {"encrypt", certFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_notCalledByDefault() {
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "clownfish"});
|
||||
verify(encrypt, never()).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_callGetsPassedDown() {
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "monkey", "--no-armor"});
|
||||
verify(encrypt, times(1)).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void writeTo_ioExceptionCausesExit1() throws IOException {
|
||||
when(encrypt.plaintext((InputStream) any())).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
});
|
||||
|
||||
SopCLI.main(new String[] {"encrypt", "--with-password", "wildcat"});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.Ready;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.ExtractCert;
|
||||
|
||||
public class ExtractCertCmdTest {
|
||||
|
||||
ExtractCert extractCert;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws IOException, SOPGPException.BadData {
|
||||
extractCert = mock(ExtractCert.class);
|
||||
when(extractCert.key((InputStream) any())).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
}
|
||||
});
|
||||
|
||||
SOP sop = mock(SOP.class);
|
||||
when(sop.extractCert()).thenReturn(extractCert);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_notCalledByDefault() {
|
||||
SopCLI.main(new String[] {"extract-cert"});
|
||||
verify(extractCert, never()).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_passedDown() {
|
||||
SopCLI.main(new String[] {"extract-cert", "--no-armor"});
|
||||
verify(extractCert, times(1)).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void key_ioExceptionCausesExit1() throws IOException, SOPGPException.BadData {
|
||||
when(extractCert.key((InputStream) any())).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
});
|
||||
SopCLI.main(new String[] {"extract-cert"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void key_badDataCausesExit41() throws IOException, SOPGPException.BadData {
|
||||
when(extractCert.key((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"extract-cert"});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
import sop.Ready;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.GenerateKey;
|
||||
|
||||
public class GenerateKeyCmdTest {
|
||||
|
||||
GenerateKey generateKey;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.MissingArg, IOException {
|
||||
generateKey = mock(GenerateKey.class);
|
||||
when(generateKey.generate()).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
SOP sop = mock(SOP.class);
|
||||
when(sop.generateKey()).thenReturn(generateKey);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_notCalledByDefault() {
|
||||
SopCLI.main(new String[] {"generate-key", "Alice"});
|
||||
verify(generateKey, never()).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_passedDown() {
|
||||
SopCLI.main(new String[] {"generate-key", "--no-armor", "Alice"});
|
||||
verify(generateKey, times(1)).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userId_multipleUserIdsPassedDownInProperOrder() {
|
||||
SopCLI.main(new String[] {"generate-key", "Alice <alice@pgpainless.org>", "Bob <bob@pgpainless.org>"});
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(generateKey);
|
||||
inOrder.verify(generateKey).userId("Alice <alice@pgpainless.org>");
|
||||
inOrder.verify(generateKey).userId("Bob <bob@pgpainless.org>");
|
||||
|
||||
verify(generateKey, times(2)).userId(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(19)
|
||||
public void missingArgumentCausesExit19() throws SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.MissingArg, IOException {
|
||||
// TODO: RFC4880-bis and the current Stateless OpenPGP CLI spec allow keys to have no user-ids,
|
||||
// so we might want to change this test in the future.
|
||||
when(generateKey.generate()).thenThrow(new SOPGPException.MissingArg("Missing user-id."));
|
||||
SopCLI.main(new String[] {"generate-key"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(13)
|
||||
public void unsupportedAsymmetricAlgorithmCausesExit13() throws SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.MissingArg, IOException {
|
||||
when(generateKey.generate()).thenThrow(new SOPGPException.UnsupportedAsymmetricAlgo("Unsupported asymmetric algorithm.", new Exception()));
|
||||
SopCLI.main(new String[] {"generate-key", "Alice"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void ioExceptionCausesExit1() throws SOPGPException.UnsupportedAsymmetricAlgo, SOPGPException.MissingArg, IOException {
|
||||
when(generateKey.generate()).thenReturn(new Ready() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
});
|
||||
SopCLI.main(new String[] {"generate-key", "Alice"});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.ReadyWithResult;
|
||||
import sop.SOP;
|
||||
import sop.SigningResult;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Sign;
|
||||
|
||||
public class SignCmdTest {
|
||||
|
||||
Sign sign;
|
||||
File keyFile;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() throws IOException, SOPGPException.ExpectedText {
|
||||
sign = mock(Sign.class);
|
||||
when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<SigningResult>() {
|
||||
@Override
|
||||
public SigningResult writeTo(OutputStream outputStream) {
|
||||
return SigningResult.builder().build();
|
||||
}
|
||||
});
|
||||
|
||||
SOP sop = mock(SOP.class);
|
||||
when(sop.sign()).thenReturn(sign);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
|
||||
keyFile = File.createTempFile("sign-", ".asc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void as_optionsAreCaseInsensitive() {
|
||||
SopCLI.main(new String[] {"sign", "--as", "Binary", keyFile.getAbsolutePath()});
|
||||
SopCLI.main(new String[] {"sign", "--as", "binary", keyFile.getAbsolutePath()});
|
||||
SopCLI.main(new String[] {"sign", "--as", "BINARY", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void as_invalidOptionCausesExit37() {
|
||||
SopCLI.main(new String[] {"sign", "--as", "Invalid", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void as_unsupportedOptionCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(sign.mode(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting signing mode not supported."));
|
||||
SopCLI.main(new String[] {"sign", "--as", "binary", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void key_nonExistentKeyFileCausesExit1() {
|
||||
SopCLI.main(new String[] {"sign", "invalid.asc"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void key_keyIsProtectedCausesExit1() throws SOPGPException.KeyIsProtected, IOException, SOPGPException.BadData {
|
||||
when(sign.key((InputStream) any())).thenThrow(new SOPGPException.KeyIsProtected());
|
||||
SopCLI.main(new String[] {"sign", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void key_badDataCausesExit41() throws SOPGPException.KeyIsProtected, IOException, SOPGPException.BadData {
|
||||
when(sign.key((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"sign", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(19)
|
||||
public void key_missingKeyFileCausesExit19() {
|
||||
SopCLI.main(new String[] {"sign"});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_notCalledByDefault() {
|
||||
SopCLI.main(new String[] {"sign", keyFile.getAbsolutePath()});
|
||||
verify(sign, never()).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noArmor_passedDown() {
|
||||
SopCLI.main(new String[] {"sign", "--no-armor", keyFile.getAbsolutePath()});
|
||||
verify(sign, times(1)).noArmor();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void data_ioExceptionCausesExit1() throws IOException, SOPGPException.ExpectedText {
|
||||
when(sign.data((InputStream) any())).thenReturn(new ReadyWithResult<SigningResult>() {
|
||||
@Override
|
||||
public SigningResult writeTo(OutputStream outputStream) throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
});
|
||||
SopCLI.main(new String[] {"sign", keyFile.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(53)
|
||||
public void data_expectedTextExceptionCausesExit53() throws IOException, SOPGPException.ExpectedText {
|
||||
when(sign.data((InputStream) any())).thenThrow(new SOPGPException.ExpectedText());
|
||||
SopCLI.main(new String[] {"sign", keyFile.getAbsolutePath()});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import sop.SOP;
|
||||
import sop.Verification;
|
||||
import sop.cli.picocli.DateParser;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.exception.SOPGPException;
|
||||
import sop.operation.Verify;
|
||||
import sop.util.UTCUtil;
|
||||
|
||||
public class VerifyCmdTest {
|
||||
|
||||
Verify verify;
|
||||
File signature;
|
||||
File cert;
|
||||
|
||||
PrintStream originalSout;
|
||||
|
||||
@BeforeEach
|
||||
public void prepare() throws SOPGPException.UnsupportedOption, SOPGPException.BadData, SOPGPException.NoSignature, IOException {
|
||||
originalSout = System.out;
|
||||
|
||||
verify = mock(Verify.class);
|
||||
when(verify.notBefore(any())).thenReturn(verify);
|
||||
when(verify.notAfter(any())).thenReturn(verify);
|
||||
when(verify.cert((InputStream) any())).thenReturn(verify);
|
||||
when(verify.signatures((InputStream) any())).thenReturn(verify);
|
||||
when(verify.data((InputStream) any())).thenReturn(
|
||||
Collections.singletonList(
|
||||
new Verification(
|
||||
UTCUtil.parseUTCDate("2019-10-29T18:36:45Z"),
|
||||
"EB85BB5FA33A75E15E944E63F231550C4F47E38E",
|
||||
"EB85BB5FA33A75E15E944E63F231550C4F47E38E")
|
||||
)
|
||||
);
|
||||
|
||||
SOP sop = mock(SOP.class);
|
||||
when(sop.verify()).thenReturn(verify);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
|
||||
signature = File.createTempFile("signature-", ".asc");
|
||||
cert = File.createTempFile("cert-", ".asc");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void restoreSout() {
|
||||
System.setOut(originalSout);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notAfter_passedDown() throws SOPGPException.UnsupportedOption {
|
||||
Date date = UTCUtil.parseUTCDate("2019-10-29T18:36:45Z");
|
||||
SopCLI.main(new String[] {"verify", "--not-after", "2019-10-29T18:36:45Z", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notAfter(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notAfter_now() throws SOPGPException.UnsupportedOption {
|
||||
Date now = new Date();
|
||||
SopCLI.main(new String[] {"verify", "--not-after", "now", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notAfter(dateMatcher(now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notAfter_dashCountsAsEndOfTime() throws SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"verify", "--not-after", "-", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notAfter(DateParser.END_OF_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void notAfter_unsupportedOptionCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(verify.notAfter(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting upper signature date boundary not supported."));
|
||||
SopCLI.main(new String[] {"verify", "--not-after", "2019-10-29T18:36:45Z", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notBefore_passedDown() throws SOPGPException.UnsupportedOption {
|
||||
Date date = UTCUtil.parseUTCDate("2019-10-29T18:36:45Z");
|
||||
SopCLI.main(new String[] {"verify", "--not-before", "2019-10-29T18:36:45Z", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notBefore(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notBefore_now() throws SOPGPException.UnsupportedOption {
|
||||
Date now = new Date();
|
||||
SopCLI.main(new String[] {"verify", "--not-before", "now", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notBefore(dateMatcher(now));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notBefore_dashCountsAsBeginningOfTime() throws SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"verify", "--not-before", "-", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notBefore(DateParser.BEGINNING_OF_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void notBefore_unsupportedOptionCausesExit37() throws SOPGPException.UnsupportedOption {
|
||||
when(verify.notBefore(any())).thenThrow(new SOPGPException.UnsupportedOption("Setting lower signature date boundary not supported."));
|
||||
SopCLI.main(new String[] {"verify", "--not-before", "2019-10-29T18:36:45Z", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notBeforeAndNotAfterAreCalledWithDefaultValues() throws SOPGPException.UnsupportedOption {
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
verify(verify, times(1)).notAfter(dateMatcher(new Date()));
|
||||
verify(verify, times(1)).notBefore(DateParser.BEGINNING_OF_TIME);
|
||||
}
|
||||
|
||||
private static Date dateMatcher(Date date) {
|
||||
return ArgumentMatchers.argThat(argument -> Math.abs(argument.getTime() - date.getTime()) < 1000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void cert_fileNotFoundCausesExit1() {
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), "invalid.asc"});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void cert_badDataCausesExit41() throws SOPGPException.BadData {
|
||||
when(verify.cert((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(1)
|
||||
public void signature_fileNotFoundCausesExit1() {
|
||||
SopCLI.main(new String[] {"verify", "invalid.sig", cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void signature_badDataCausesExit41() throws SOPGPException.BadData {
|
||||
when(verify.signatures((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(3)
|
||||
public void data_noSignaturesCausesExit3() throws SOPGPException.NoSignature, IOException, SOPGPException.BadData {
|
||||
when(verify.data((InputStream) any())).thenThrow(new SOPGPException.NoSignature());
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(41)
|
||||
public void data_badDataCausesExit41() throws SOPGPException.NoSignature, IOException, SOPGPException.BadData {
|
||||
when(verify.data((InputStream) any())).thenThrow(new SOPGPException.BadData(new IOException()));
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resultIsPrintedProperly() throws SOPGPException.NoSignature, IOException, SOPGPException.BadData {
|
||||
when(verify.data((InputStream) any())).thenReturn(Arrays.asList(
|
||||
new Verification(UTCUtil.parseUTCDate("2019-10-29T18:36:45Z"),
|
||||
"EB85BB5FA33A75E15E944E63F231550C4F47E38E",
|
||||
"EB85BB5FA33A75E15E944E63F231550C4F47E38E"),
|
||||
new Verification(UTCUtil.parseUTCDate("2019-10-24T23:48:29Z"),
|
||||
"C90E6D36200A1B922A1509E77618196529AE5FF8",
|
||||
"C4BC2DDB38CCE96485EBE9C2F20691179038E5C6")
|
||||
));
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
System.setOut(new PrintStream(out));
|
||||
|
||||
SopCLI.main(new String[] {"verify", signature.getAbsolutePath(), cert.getAbsolutePath()});
|
||||
|
||||
System.setOut(originalSout);
|
||||
|
||||
String expected = "2019-10-29T18:36:45Z EB85BB5FA33A75E15E944E63F231550C4F47E38E EB85BB5FA33A75E15E944E63F231550C4F47E38E\n" +
|
||||
"2019-10-24T23:48:29Z C90E6D36200A1B922A1509E77618196529AE5FF8 C4BC2DDB38CCE96485EBE9C2F20691179038E5C6\n";
|
||||
|
||||
assertEquals(expected, out.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package sop.cli.picocli.commands;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.ginsberg.junit.exit.ExpectSystemExitWithStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sop.SOP;
|
||||
import sop.cli.picocli.SopCLI;
|
||||
import sop.operation.Version;
|
||||
|
||||
public class VersionCmdTest {
|
||||
|
||||
private Version version;
|
||||
|
||||
@BeforeEach
|
||||
public void mockComponents() {
|
||||
SOP sop = mock(SOP.class);
|
||||
version = mock(Version.class);
|
||||
when(version.getName()).thenReturn("MockSop");
|
||||
when(version.getVersion()).thenReturn("1.0");
|
||||
when(sop.version()).thenReturn(version);
|
||||
|
||||
SopCLI.setSopInstance(sop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertVersionCommandWorks() {
|
||||
SopCLI.main(new String[] {"version"});
|
||||
verify(version, times(1)).getVersion();
|
||||
verify(version, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ExpectSystemExitWithStatus(37)
|
||||
public void assertInvalidOptionResultsInExit37() {
|
||||
SopCLI.main(new String[] {"version", "--invalid"});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue