mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-14 08:41:28 +00:00
make some better use of mocks during unit tests
This commit is contained in:
@@ -27,11 +27,6 @@
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>crypto-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>crypto-aes</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Jetty (Servlet Container) -->
|
||||
<dependency>
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.cryptomator.webdav.jackrabbit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.exceptions.DecryptFailedException;
|
||||
import org.cryptomator.crypto.exceptions.EncryptFailedException;
|
||||
import org.cryptomator.crypto.exceptions.MacAuthenticationFailedException;
|
||||
import org.cryptomator.crypto.exceptions.UnsupportedKeyLengthException;
|
||||
import org.cryptomator.crypto.exceptions.UnsupportedVaultException;
|
||||
import org.cryptomator.crypto.exceptions.WrongPasswordException;
|
||||
|
||||
class CryptorMock implements Cryptor {
|
||||
|
||||
private static final int BUFSIZE = 32768;
|
||||
|
||||
@Override
|
||||
public void randomizeMasterKey() {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encryptMasterKey(OutputStream out, CharSequence password) throws IOException {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decryptMasterKey(InputStream in, CharSequence password) throws DecryptFailedException, WrongPasswordException, UnsupportedKeyLengthException, IOException, UnsupportedVaultException {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encryptDirectoryPath(String cleartextDirectoryId, String nativePathSep) {
|
||||
return cleartextDirectoryId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encryptFilename(String cleartextName) {
|
||||
return cleartextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decryptFilename(String ciphertextName) throws DecryptFailedException {
|
||||
return ciphertextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decryptedContentLength(SeekableByteChannel encryptedFile) throws IOException, MacAuthenticationFailedException {
|
||||
return encryptedFile.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decryptFile(SeekableByteChannel encryptedFile, OutputStream plaintextFile, boolean authenticate) throws IOException, DecryptFailedException {
|
||||
ByteBuffer buf = ByteBuffer.allocate(BUFSIZE);
|
||||
long numReadTotal = 0;
|
||||
int numRead = 0;
|
||||
while ((numRead = encryptedFile.read(buf)) != -1) {
|
||||
numReadTotal += numRead;
|
||||
buf.flip();
|
||||
byte[] bytes = new byte[numRead];
|
||||
buf.get(bytes);
|
||||
plaintextFile.write(bytes);
|
||||
buf.rewind();
|
||||
}
|
||||
return numReadTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long decryptRange(SeekableByteChannel encryptedFile, OutputStream plaintextFile, long pos, long length, boolean authenticate) throws IOException, DecryptFailedException {
|
||||
encryptedFile.position(pos);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocate(BUFSIZE);
|
||||
long numReadTotal = 0;
|
||||
int numRead = 0;
|
||||
while ((numRead = encryptedFile.read(buf)) != -1 && numReadTotal < length) {
|
||||
int len = (int) Math.min(Math.min(numRead, BUFSIZE), length - numReadTotal); // known to fit into integer
|
||||
numReadTotal += len;
|
||||
buf.flip();
|
||||
byte[] bytes = new byte[len];
|
||||
buf.get(bytes);
|
||||
plaintextFile.write(bytes);
|
||||
buf.rewind();
|
||||
}
|
||||
return numReadTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long encryptFile(InputStream plaintextFile, SeekableByteChannel encryptedFile) throws IOException, EncryptFailedException {
|
||||
byte[] buf = new byte[BUFSIZE];
|
||||
long numWrittenTotal = 0;
|
||||
int numRead = 0;
|
||||
while ((numRead = plaintextFile.read(buf)) != -1) {
|
||||
numWrittenTotal += numRead;
|
||||
encryptedFile.write(ByteBuffer.wrap(buf, 0, numRead));
|
||||
}
|
||||
return numWrittenTotal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.commons.httpclient.methods.PutMethod;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.cryptomator.crypto.aes256.Aes256Cryptor;
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.webdav.WebDavServer;
|
||||
import org.cryptomator.webdav.WebDavServer.ServletLifeCycleAdapter;
|
||||
import org.junit.AfterClass;
|
||||
@@ -41,7 +41,7 @@ import com.google.common.io.Files;
|
||||
public class RangeRequestTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RangeRequestTest.class);
|
||||
private static final Aes256Cryptor CRYPTOR = new Aes256Cryptor();
|
||||
private static final Cryptor CRYPTOR = new CryptorMock();
|
||||
private static final WebDavServer SERVER = new WebDavServer();
|
||||
private static final File TMP_VAULT = Files.createTempDir();
|
||||
private static ServletLifeCycleAdapter SERVLET;
|
||||
|
||||
@@ -65,5 +65,16 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DI -->
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -103,14 +103,11 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
|
||||
/**
|
||||
* Creates a new Cryptor with a newly initialized PRNG.
|
||||
*/
|
||||
public Aes256Cryptor() {
|
||||
try {
|
||||
securePrng = SecureRandom.getInstanceStrong();
|
||||
// No setSeed needed. See SecureRandom.getInstance(String):
|
||||
// The first call to nextBytes will force the SecureRandom object to seed itself
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("PRNG algorithm should exist.", e);
|
||||
}
|
||||
|
||||
Aes256Cryptor(SecureRandom securePrng) {
|
||||
this.securePrng = securePrng;
|
||||
// No setSeed needed. See SecureRandom.getInstance(String):
|
||||
// The first call to nextBytes will force the SecureRandom object to seed itself
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.cryptomator.crypto.aes256;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = CryptoModule.class)
|
||||
interface CryptoComponent {
|
||||
|
||||
Cryptor cryptor();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.cryptomator.crypto.aes256;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class CryptoModule {
|
||||
|
||||
@Provides
|
||||
SecureRandom provideRandomNumberGenerator() {
|
||||
try {
|
||||
return SecureRandom.getInstanceStrong();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// quote "Every implementation of the Java platform is required to support at least one strong SecureRandom implementation."
|
||||
throw new AssertionError("No SecureRandom implementation available.");
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
public Cryptor provideCryptor(SecureRandom secureRandom) {
|
||||
return new Aes256Cryptor(secureRandom);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import java.util.Arrays;
|
||||
import javax.security.auth.DestroyFailedException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.exceptions.DecryptFailedException;
|
||||
import org.cryptomator.crypto.exceptions.EncryptFailedException;
|
||||
import org.cryptomator.crypto.exceptions.UnsupportedKeyLengthException;
|
||||
@@ -29,13 +30,18 @@ import org.junit.Test;
|
||||
|
||||
public class Aes256CryptorTest {
|
||||
|
||||
private final Aes256Cryptor cryptor;
|
||||
private final Cryptor cryptor;
|
||||
|
||||
public Aes256CryptorTest() {
|
||||
cryptor = new Aes256Cryptor();
|
||||
cryptor = DaggerCryptoTestComponent.create().cryptor();
|
||||
cryptor.randomizeMasterKey();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleCryptorInstances() {
|
||||
Assert.assertNotSame(DaggerCryptoTestComponent.create().cryptor(), DaggerCryptoTestComponent.create().cryptor());
|
||||
}
|
||||
|
||||
@Test(timeout = 10000)
|
||||
public void testCorrectPassword() throws IOException, WrongPasswordException, DecryptFailedException, UnsupportedKeyLengthException, DestroyFailedException, UnsupportedVaultException {
|
||||
final String pw = "asd";
|
||||
@@ -44,7 +50,7 @@ public class Aes256CryptorTest {
|
||||
cryptor.encryptMasterKey(out, pw);
|
||||
cryptor.destroy();
|
||||
|
||||
final Aes256Cryptor decryptor = new Aes256Cryptor();
|
||||
final Cryptor decryptor = DaggerCryptoTestComponent.create().cryptor();
|
||||
final InputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
decryptor.decryptMasterKey(in, pw);
|
||||
|
||||
@@ -63,7 +69,7 @@ public class Aes256CryptorTest {
|
||||
|
||||
// all these passwords are expected to fail.
|
||||
final String[] wrongPws = {"a", "as", "asdf", "sdf", "das", "dsa", "foo", "bar", "baz"};
|
||||
final Aes256Cryptor decryptor = new Aes256Cryptor();
|
||||
final Cryptor decryptor = DaggerCryptoTestComponent.create().cryptor();
|
||||
for (final String wrongPw : wrongPws) {
|
||||
final InputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.cryptomator.crypto.aes256;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = CryptoTestModule.class)
|
||||
public interface CryptoTestComponent {
|
||||
|
||||
Cryptor cryptor();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.cryptomator.crypto.aes256;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class CryptoTestModule {
|
||||
|
||||
@Provides
|
||||
@SuppressWarnings("deprecation")
|
||||
SecureRandom provideRandomNumberGenerator() {
|
||||
// we use this class for testing only, as unit tests on CI servers tend to stall, if they rely on true randomness.
|
||||
return new InsecureRandomMock();
|
||||
}
|
||||
|
||||
@Provides
|
||||
Cryptor provideCryptor(SecureRandom secureRandom) {
|
||||
return new Aes256Cryptor(secureRandom);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.cryptomator.crypto.aes256;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <b>DO NOT USE</b>
|
||||
*
|
||||
* This class is for testing only.
|
||||
*/
|
||||
@Deprecated // marked as deprecated and made package-private inside /src/test/java to avoid accidential use.
|
||||
class InsecureRandomMock extends SecureRandom {
|
||||
|
||||
private static final long serialVersionUID = 1505563778398085504L;
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
public void nextBytes(byte[] bytes) {
|
||||
// let the deterministic RNG do the work:
|
||||
this.random.nextBytes(bytes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -136,12 +136,12 @@
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
<version>2.0.1</version>
|
||||
<version>2.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.crypto.Cryptor;
|
||||
import org.cryptomator.crypto.SamplingCryptorDecorator;
|
||||
import org.cryptomator.crypto.aes256.Aes256Cryptor;
|
||||
import org.cryptomator.crypto.aes256.CryptoModule;
|
||||
import org.cryptomator.ui.model.VaultObjectMapperProvider;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.cryptomator.ui.settings.SettingsProvider;
|
||||
@@ -26,7 +26,7 @@ import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import javafx.application.Application;
|
||||
|
||||
@Module
|
||||
@Module(includes = CryptoModule.class)
|
||||
class CryptomatorModule {
|
||||
|
||||
private final Application application;
|
||||
@@ -90,8 +90,9 @@ class CryptomatorModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
Cryptor provideCryptor() {
|
||||
return SamplingCryptorDecorator.decorate(new Aes256Cryptor());
|
||||
@Named("SamplingCryptor")
|
||||
Cryptor provideCryptor(Cryptor cryptor) {
|
||||
return SamplingCryptorDecorator.decorate(cryptor);
|
||||
}
|
||||
|
||||
private <T> T closeLater(T object, Closer<T> closer) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package org.cryptomator.ui.controllers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -25,6 +26,7 @@ import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.cookie.CookiePolicy;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
@@ -140,8 +142,9 @@ public class WelcomeController extends AbstractFXMLViewController {
|
||||
client.getParams().setConnectionManagerTimeout(5000);
|
||||
try {
|
||||
client.executeMethod(method);
|
||||
if (method.getStatusCode() == HttpStatus.SC_OK) {
|
||||
final byte[] responseData = method.getResponseBody();
|
||||
final InputStream responseBodyStream = method.getResponseBodyAsStream();
|
||||
if (method.getStatusCode() == HttpStatus.SC_OK && responseBodyStream != null) {
|
||||
final byte[] responseData = IOUtils.toByteArray(responseBodyStream);
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
final Map<String, String> map = mapper.readValue(responseData, new TypeReference<HashMap<String, String>>() {
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.cryptomator.ui.model;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -20,7 +21,7 @@ public class VaultFactory {
|
||||
private final DeferredCloser closer;
|
||||
|
||||
@Inject
|
||||
public VaultFactory(WebDavServer server, Provider<Cryptor> cryptorProvider, WebDavMounter mounter, DeferredCloser closer) {
|
||||
public VaultFactory(WebDavServer server, @Named("SamplingCryptor") Provider<Cryptor> cryptorProvider, WebDavMounter mounter, DeferredCloser closer) {
|
||||
this.server = server;
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
this.mounter = mounter;
|
||||
|
||||
Reference in New Issue
Block a user