Single maven module (#1676)

combined all sources into single maven module
This commit is contained in:
Sebastian Stenzel
2021-06-04 20:09:10 +02:00
committed by GitHub
parent 72bd9c1fdf
commit 7fac6da448
430 changed files with 709 additions and 962 deletions
@@ -0,0 +1,130 @@
package org.cryptomator.common;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@DisplayName("Environment Variables Test")
class EnvironmentTest {
private Environment env;
@BeforeEach
void init() {
env = Mockito.spy(new Environment());
Mockito.when(env.getHomeDir()).thenReturn(Path.of("/home/testuser"));
}
@Test
@DisplayName("cryptomator.settingsPath=~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json")
public void testSettingsPath() {
System.setProperty("cryptomator.settingsPath", "~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json");
List<Path> result = env.getSettingsPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(2));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/.config/Cryptomator/settings.json"), //
Paths.get("/home/testuser/.Cryptomator/settings.json")));
}
@Test
@DisplayName("cryptomator.ipcPortPath=~/.config/Cryptomator/ipcPort.bin:~/.Cryptomator/ipcPort.bin")
public void testIpcPortPath() {
System.setProperty("cryptomator.ipcPortPath", "~/.config/Cryptomator/ipcPort.bin:~/.Cryptomator/ipcPort.bin");
List<Path> result = env.getIpcPortPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(2));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/.config/Cryptomator/ipcPort.bin"), //
Paths.get("/home/testuser/.Cryptomator/ipcPort.bin")));
}
@Test
@DisplayName("cryptomator.keychainPath=~/AppData/Roaming/Cryptomator/keychain.json")
public void testKeychainPath() {
System.setProperty("cryptomator.keychainPath", "~/AppData/Roaming/Cryptomator/keychain.json");
List<Path> result = env.getKeychainPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/AppData/Roaming/Cryptomator/keychain.json")));
}
@Test
@DisplayName("cryptomator.logDir=/foo/bar")
public void testAbsoluteLogDir() {
System.setProperty("cryptomator.logDir", "/foo/bar");
Optional<Path> logDir = env.getLogDir();
Assertions.assertTrue(logDir.isPresent());
}
@Test
@DisplayName("cryptomator.logDir=~/foo/bar")
public void testRelativeLogDir() {
System.setProperty("cryptomator.logDir", "~/foo/bar");
Optional<Path> logDir = env.getLogDir();
Assertions.assertTrue(logDir.isPresent());
Assertions.assertEquals(Paths.get("/home/testuser/foo/bar"), logDir.get());
}
@Nested
@DisplayName("Path Lists")
class SettingsPath {
@Test
@DisplayName("test.path.property=")
public void testEmptyList() {
System.setProperty("test.path.property", "");
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(0));
}
@Test
@DisplayName("test.path.property=/foo/bar/test")
public void testSingleAbsolutePath() {
System.setProperty("test.path.property", "/foo/bar/test");
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.hasItem(Paths.get("/foo/bar/test")));
}
@Test
@DisplayName("test.path.property=~/test")
public void testSingleHomeRelativePath() {
System.setProperty("test.path.property", "~/test");
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.hasItem(Paths.get("/home/testuser/test")));
}
@Test
@DisplayName("test.path.property=~/test:~/test2:/foo/bar/test")
public void testMultiplePaths() {
System.setProperty("test.path.property", "~/test:~/test2:/foo/bar/test");
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(3));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/test"), //
Paths.get("/home/testuser/test2"), //
Paths.get("/foo/bar/test")));
}
}
}
@@ -0,0 +1,63 @@
package org.cryptomator.common;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Optional;
class LicenseCheckerTest {
private static final String PUBLIC_KEY = """
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\
Al8G7CqwoJOsW7Kddns=\
""";
private LicenseChecker licenseChecker;
@BeforeEach
public void setup() {
licenseChecker = new LicenseChecker(PUBLIC_KEY);
}
@Test
public void testCheckValidLicense() {
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
Optional<DecodedJWT> decoded = licenseChecker.check(license);
Assertions.assertTrue(decoded.isPresent());
Assertions.assertEquals("cryptobot@example.com", decoded.get().getSubject());
}
@Test
public void testCheckInvalidLicenseHeader() {
String license = "EyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
Optional<DecodedJWT> decoded = licenseChecker.check(license);
Assertions.assertFalse(decoded.isPresent());
}
@Test
public void testCheckInvalidLicensePayload() {
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.EyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.AQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
Optional<DecodedJWT> decoded = licenseChecker.check(license);
Assertions.assertFalse(decoded.isPresent());
}
@Test
public void testCheckInvalidLicenseSignature() {
String license = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCIsImtpZCI6InhaRGZacHJ5NFA5dlpQWnlHMmZOQlJqLTdMejVvbVZkbTd0SG9DZ1NOZlkifQ.eyJzdWIiOiJjcnlwdG9ib3RAZXhhbXBsZS5jb20iLCJpYXQiOjE1MTYyMzkwMjJ9.aQaBIKQdNCxmRJi2wLOcbagTgi39WhdWwgdpKTYSPicg-aPr_tst_RjmnqMemx3cBe0Blr4nEbj_lAtSKHz_i61fAUyI1xCIAZYbK9Q3ICHIHQl3AiuCpBwFl-k81OB4QDYiKpEc9gLN5dhW_VymJMsgOvyiC0UjC91f2AM7s46byDNj";
Optional<DecodedJWT> decoded = licenseChecker.check(license);
Assertions.assertFalse(decoded.isPresent());
}
}
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* All rights reserved.
* This program and the accompanying materials are made available under the terms of the accompanying LICENSE file.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.common;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Comparator;
public class SemVerComparatorTest {
private final Comparator<String> semVerComparator = new SemVerComparator();
// equal versions
@Test
public void compareEqualVersions() {
Assertions.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4")));
Assertions.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-alpha")));
Assertions.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4+20170101", "1.23.4+20171231")));
Assertions.assertEquals(0, Integer.signum(semVerComparator.compare("1.23.4-alpha+20170101", "1.23.4-alpha+20171231")));
}
// newer versions in first argument
@Test
public void compareHigherToLowerVersions() {
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.5", "1.23.4")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.24.4", "1.23.4")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4-SNAPSHOT")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.4-56.78")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-beta", "1.23.4-alpha")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-alpha.1", "1.23.4-alpha")));
Assertions.assertEquals(1, Integer.signum(semVerComparator.compare("1.23.4-56.79", "1.23.4-56.78")));
}
// newer versions in second argument
@Test
public void compareLowerToHigherVersions() {
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4", "1.23.5")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4", "1.24.4")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23", "1.23.4")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-SNAPSHOT", "1.23.4")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-56.78", "1.23.4")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-beta")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-alpha", "1.23.4-alpha.1")));
Assertions.assertEquals(-1, Integer.signum(semVerComparator.compare("1.23.4-56.78", "1.23.4-56.79")));
}
}
@@ -0,0 +1,58 @@
package org.cryptomator.common.keychain;
import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class KeychainManagerTest {
@Test
public void testStoreAndLoad() throws KeychainAccessException {
KeychainManager keychainManager = new KeychainManager(new SimpleObjectProperty<>(new MapKeychainAccess()));
keychainManager.storePassphrase("test", "asd");
Assertions.assertArrayEquals("asd".toCharArray(), keychainManager.loadPassphrase("test"));
}
@Nested
public static class WhenObservingProperties {
@BeforeAll
public static void startup() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
Platform.startup(latch::countDown);
latch.await(5, TimeUnit.SECONDS);
}
@Test
public void testPropertyChangesWhenStoringPassword() throws KeychainAccessException, InterruptedException {
KeychainManager keychainManager = new KeychainManager(new SimpleObjectProperty<>(new MapKeychainAccess()));
ReadOnlyBooleanProperty property = keychainManager.getPassphraseStoredProperty("test");
Assertions.assertEquals(false, property.get());
keychainManager.storePassphrase("test", "bar");
AtomicBoolean result = new AtomicBoolean(false);
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
result.set(property.get());
latch.countDown();
});
latch.await(1, TimeUnit.SECONDS);
Assertions.assertEquals(true, result.get());
}
}
}
@@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.common.keychain;
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
import java.util.HashMap;
import java.util.Map;
class MapKeychainAccess implements KeychainAccessProvider {
private final Map<String, char[]> map = new HashMap<>();
@Override
public void storePassphrase(String key, CharSequence passphrase) {
char[] pw = new char[passphrase.length()];
for (int i = 0; i < passphrase.length(); i++) {
pw[i] = passphrase.charAt(i);
}
map.put(key, pw);
}
@Override
public char[] loadPassphrase(String key) {
return map.get(key);
}
@Override
public void deletePassphrase(String key) {
map.remove(key);
}
@Override
public void changePassphrase(String key, CharSequence passphrase) {
map.get(key);
storePassphrase(key, passphrase);
}
@Override
public boolean isSupported() {
return true;
}
@Override
public boolean isLocked() {
return false;
}
}
@@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.common.settings;
import org.cryptomator.common.Environment;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mockito;
import java.io.IOException;
public class SettingsJsonAdapterTest {
private final Environment env = Mockito.mock(Environment.class);
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter(env);
@Test
public void testDeserialize() throws IOException {
String json = """
{
"directories": [
{"id": "1", "path": "/vault1", "mountName": "vault1", "winDriveLetter": "X"},
{"id": "2", "path": "/vault2", "mountName": "vault2", "winDriveLetter": "Y"}
],
"checkForUpdatesEnabled": true,
"port": 8080,
"numTrayNotifications": 42,
"preferredVolumeImpl": "FUSE"
}
""";
Settings settings = adapter.fromJson(json);
Assertions.assertTrue(settings.checkForUpdates().get());
Assertions.assertEquals(2, settings.getDirectories().size());
Assertions.assertEquals(8080, settings.port().get());
Assertions.assertEquals(42, settings.numTrayNotifications().get());
Assertions.assertEquals(WebDavUrlScheme.DAV, settings.preferredGvfsScheme().get());
Assertions.assertEquals(VolumeImpl.FUSE, settings.preferredVolumeImpl().get());
}
@ParameterizedTest(name = "fromJson() should throw IOException for input: {0}")
@ValueSource(strings = { //
"", //
"<html>", //
"{invalidjson}" //
})
public void testDeserializeMalformed(String input) {
Assertions.assertThrows(IOException.class, () -> {
adapter.fromJson(input);
});
}
}
@@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.common.settings;
import org.cryptomator.common.Environment;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.function.Consumer;
public class SettingsTest {
@Test
public void testAutoSave() {
Environment env = Mockito.mock(Environment.class);
@SuppressWarnings("unchecked") Consumer<Settings> changeListener = Mockito.mock(Consumer.class);
Settings settings = new Settings(env);
settings.setSaveCmd(changeListener);
VaultSettings vaultSettings = VaultSettings.withRandomId();
Mockito.verify(changeListener, Mockito.times(0)).accept(settings);
// first change (to property):
settings.preferredGvfsScheme().set(WebDavUrlScheme.WEBDAV);
Mockito.verify(changeListener, Mockito.times(1)).accept(settings);
// second change (to list):
settings.getDirectories().add(vaultSettings);
Mockito.verify(changeListener, Mockito.times(2)).accept(settings);
// third change (to property of list item):
vaultSettings.displayName().set("asd");
Mockito.verify(changeListener, Mockito.times(3)).accept(settings);
}
}
@@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.common.settings;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Paths;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class VaultSettingsJsonAdapterTest {
private final VaultSettingsJsonAdapter adapter = new VaultSettingsJsonAdapter();
@Test
public void testDeserialize() throws IOException {
String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"displayName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":\"--foo --bar\"}";
JsonReader jsonReader = new JsonReader(new StringReader(json));
VaultSettings vaultSettings = adapter.read(jsonReader);
assertAll(
() -> assertEquals("foo", vaultSettings.getId()),
() -> assertEquals(Paths.get("/foo/bar"), vaultSettings.path().get()),
() -> assertEquals("test", vaultSettings.displayName().get()),
() -> assertEquals("X", vaultSettings.winDriveLetter().get()),
() -> assertEquals("/home/test/crypto", vaultSettings.customMountPath().get()),
() -> assertEquals("--foo --bar", vaultSettings.mountFlags().get())
);
}
@Test
public void testSerialize() throws IOException {
VaultSettings vaultSettings = new VaultSettings("test");
vaultSettings.path().set(Paths.get("/foo/bar"));
vaultSettings.displayName().set("mountyMcMountFace");
vaultSettings.mountFlags().set("--foo --bar");
StringWriter buf = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(buf);
adapter.write(jsonWriter, vaultSettings);
String result = buf.toString();
assertAll(
() -> assertThat(result, containsString("\"id\":\"test\"")),
() -> {
if (System.getProperty("os.name").contains("Windows")) {
assertThat(result, containsString("\"path\":\"\\\\foo\\\\bar\""));
} else {
assertThat(result, containsString("\"path\":\"/foo/bar\""));
}
},
() -> assertThat(result, containsString("\"displayName\":\"mountyMcMountFace\"")),
() -> assertThat(result, containsString("\"mountFlags\":\"--foo --bar\""))
);
}
}
@@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
* All rights reserved.
* This program and the accompanying materials are made available under the terms of the accompanying LICENSE file.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.common.settings;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class VaultSettingsTest {
@ParameterizedTest
@CsvSource({"a\u000Fa,a_a", ": \\,_ _", "汉语,汉语", "..,_", "a\ta,a\u0020a", "\t\n\r,_"})
public void testNormalize(String test, String expected) {
VaultSettings settings = new VaultSettings("id");
settings.displayName().setValue(test);
assertEquals(expected, settings.normalizeDisplayName());
}
}
@@ -0,0 +1,72 @@
package org.cryptomator.common.vaults;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.settings.VolumeImpl;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mockito;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import java.nio.file.Path;
public class VaultModuleTest {
private final Settings settings = Mockito.mock(Settings.class);
private final VaultSettings vaultSettings = Mockito.mock(VaultSettings.class);
private final VaultModule module = new VaultModule();
@BeforeEach
public void setup(@TempDir Path tmpDir) {
Mockito.when(vaultSettings.mountName()).thenReturn(Bindings.createStringBinding(() -> "TEST"));
Mockito.when(vaultSettings.usesReadOnlyMode()).thenReturn(new SimpleBooleanProperty(true));
Mockito.when(vaultSettings.displayName()).thenReturn(new SimpleStringProperty("Vault"));
System.setProperty("user.home", tmpDir.toString());
}
@Test
@DisplayName("provideDefaultMountFlags on Mac/FUSE")
@EnabledOnOs(OS.MAC)
public void testMacFuseDefaultMountFlags() {
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.FUSE));
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-ovolname=\"TEST\""));
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-ordonly"));
}
@Test
@DisplayName("provideDefaultMountFlags on Linux/FUSE")
@EnabledOnOs(OS.LINUX)
public void testLinuxFuseDefaultMountFlags() {
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.FUSE));
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("-oro"));
}
@Test
@DisplayName("provideDefaultMountFlags on Windows/Dokany")
@EnabledOnOs(OS.WINDOWS)
public void testWinDokanyDefaultMountFlags() {
Mockito.when(settings.preferredVolumeImpl()).thenReturn(new SimpleObjectProperty<>(VolumeImpl.DOKANY));
StringBinding result = module.provideDefaultMountFlags(settings, vaultSettings);
MatcherAssert.assertThat(result.get(), CoreMatchers.containsString("--options CURRENT_SESSION,WRITE_PROTECTION"));
}
}
@@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.launcher;
import org.cryptomator.ui.launcher.AppLaunchEvent;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.nio.file.FileSystem;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class FileOpenRequestHandlerTest {
private FileOpenRequestHandler inTest;
private BlockingQueue<AppLaunchEvent> queue;
@BeforeEach
public void setup() {
queue = new ArrayBlockingQueue<>(1);
inTest = new FileOpenRequestHandler(queue);
}
@Test
@DisplayName("./cryptomator.exe foo bar")
public void testOpenArgsWithCorrectPaths() {
inTest.handleLaunchArgs(new String[]{"foo", "bar"});
AppLaunchEvent evt = queue.poll();
Assertions.assertNotNull(evt);
Collection<Path> paths = evt.getPathsToOpen();
MatcherAssert.assertThat(paths, CoreMatchers.hasItems(Paths.get("foo"), Paths.get("bar")));
}
@Test
@DisplayName("./cryptomator.exe foo (with 'foo' being an invalid path)")
public void testOpenArgsWithIncorrectPaths() {
FileSystem fs = Mockito.mock(FileSystem.class);
Mockito.when(fs.getPath("foo")).thenThrow(new InvalidPathException("foo", "foo is not a path"));
inTest.handleLaunchArgs(fs, new String[]{"foo"});
AppLaunchEvent evt = queue.poll();
Assertions.assertNull(evt);
}
@Test
@DisplayName("./cryptomator.exe foo (with full event queue)")
public void testOpenArgsWithFullQueue() {
queue.add(new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, Collections.emptyList()));
Assumptions.assumeTrue(queue.remainingCapacity() == 0);
inTest.handleLaunchArgs(new String[]{"foo"});
}
}
@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.launcher;
import org.cryptomator.common.Environment;
import org.cryptomator.launcher.IpcFactory.IpcEndpoint;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mockito;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class IpcFactoryTest {
private Environment environment = Mockito.mock(Environment.class);
private IpcProtocolImpl protocolHandler = Mockito.mock(IpcProtocolImpl.class);
@Test
@DisplayName("Wihout IPC port files")
public void testNoIpcWithoutPortFile() throws IOException {
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
Mockito.when(environment.getIpcPortPath()).thenReturn(Stream.empty());
try (IpcEndpoint endpoint1 = inTest.create()) {
Assertions.assertEquals(IpcFactory.SelfEndpoint.class, endpoint1.getClass());
Assertions.assertFalse(endpoint1.isConnectedToRemote());
Assertions.assertSame(protocolHandler, endpoint1.getRemote());
try (IpcEndpoint endpoint2 = inTest.create()) {
Assertions.assertEquals(IpcFactory.SelfEndpoint.class, endpoint2.getClass());
Assertions.assertNotSame(endpoint1, endpoint2);
Assertions.assertFalse(endpoint2.isConnectedToRemote());
Assertions.assertSame(protocolHandler, endpoint2.getRemote());
}
}
}
@Test
@DisplayName("Start server and client with port shared via file")
public void testInterProcessCommunication(@TempDir Path tmpDir) throws IOException {
Path portFile = tmpDir.resolve("testPortFile");
Mockito.when(environment.getIpcPortPath()).thenReturn(Stream.of(portFile));
IpcFactory inTest = new IpcFactory(environment, protocolHandler);
Assertions.assertFalse(Files.exists(portFile));
try (IpcEndpoint endpoint1 = inTest.create()) {
Assertions.assertEquals(IpcFactory.ServerEndpoint.class, endpoint1.getClass());
Assertions.assertFalse(endpoint1.isConnectedToRemote());
Assertions.assertTrue(Files.exists(portFile));
Assertions.assertSame(protocolHandler, endpoint1.getRemote());
Mockito.verifyZeroInteractions(protocolHandler);
try (IpcEndpoint endpoint2 = inTest.create()) {
Assertions.assertEquals(IpcFactory.ClientEndpoint.class, endpoint2.getClass());
Assertions.assertNotSame(endpoint1, endpoint2);
Assertions.assertTrue(endpoint2.isConnectedToRemote());
Assertions.assertNotSame(protocolHandler, endpoint2.getRemote());
Mockito.verifyZeroInteractions(protocolHandler);
endpoint2.getRemote().handleLaunchArgs(new String[]{"foo"});
Mockito.verify(protocolHandler).handleLaunchArgs(new String[]{"foo"});
}
}
}
}
@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.logging;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.io.File;
public class LaunchBasedTriggeringPolicyTest {
@Test
public void testTriggerOnceAndNeverAgain() {
LaunchBasedTriggeringPolicy<Object> policy = new LaunchBasedTriggeringPolicy<>();
File activeFile = Mockito.mock(File.class);
Object event = Mockito.mock(Object.class);
// 1st invocation
boolean triggered = policy.isTriggeringEvent(activeFile, event);
Assertions.assertTrue(triggered);
// 2nd invocation
triggered = policy.isTriggeringEvent(activeFile, event);
Assertions.assertFalse(triggered);
// 3rd invocation
triggered = policy.isTriggeringEvent(activeFile, event);
Assertions.assertFalse(triggered);
Mockito.verifyZeroInteractions(activeFile);
Mockito.verifyZeroInteractions(event);
}
}
@@ -0,0 +1,46 @@
package org.cryptomator.ui.addvaultwizard;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import java.util.List;
public class ReadMeGeneratorTest {
@ParameterizedTest
@CsvSource({ //
"test,test", //
"t\u00E4st,t\\u228st", //
"t\uD83D\uDE09st,t\\u55357\\u56841st", //
})
public void testEscapeNonAsciiChars(String input, String expectedResult) {
ReadmeGenerator readmeGenerator = new ReadmeGenerator(null);
String actualResult = readmeGenerator.escapeNonAsciiChars(input);
Assertions.assertEquals(expectedResult, actualResult);
}
@Test
public void testCreateDocument() {
ReadmeGenerator readmeGenerator = new ReadmeGenerator(null);
Iterable<String> paragraphs = List.of( //
"Dear User,", //
"\\b please don't touch the \"d\" directory.", //
"Thank you for your cooperation \uD83D\uDE09" //
);
String result = readmeGenerator.createDocument(paragraphs);
MatcherAssert.assertThat(result, CoreMatchers.startsWith("{\\rtf1\\fbidis\\ansi\\uc0\\fs32"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 Dear User,}\\par"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 \\b please don't touch the \"d\" directory.}\\par "));
MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 Thank you for your cooperation \\u55357\\u56841}\\par"));
MatcherAssert.assertThat(result, CoreMatchers.endsWith("}"));
}
}
@@ -0,0 +1,34 @@
package org.cryptomator.ui.common;
import com.google.common.base.Strings;
import org.cryptomator.common.Environment;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.time.Duration;
import java.util.ResourceBundle;
public class PasswordStrengthUtilTest {
@Test
public void testLongPasswords() {
PasswordStrengthUtil util = new PasswordStrengthUtil(Mockito.mock(ResourceBundle.class), Mockito.mock(Environment.class));
String longPw = Strings.repeat("x", 10_000);
Assertions.assertTimeout(Duration.ofSeconds(5), () -> {
util.computeRate(longPw);
});
}
@Test
@Disabled("waiting on upstream fix") // https://github.com/nulab/zxcvbn4j/issues/54
public void testIssue979() {
PasswordStrengthUtil util = new PasswordStrengthUtil(Mockito.mock(ResourceBundle.class), Mockito.mock(Environment.class));
int result1 = util.computeRate("backed derrick buckling mountains glove client procedures desire destination sword hidden ram");
int result2 = util.computeRate("backed derrick buckling mountains glove client procedures desire destination sword hidden ram escalation");
Assertions.assertEquals(4, result1);
Assertions.assertEquals(4, result2);
}
}
@@ -0,0 +1,174 @@
package org.cryptomator.ui.controls;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import javafx.application.Platform;
import java.awt.GraphicsEnvironment;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
class SecurePasswordFieldTest {
private SecurePasswordField pwField = new SecurePasswordField();
@BeforeAll
static void initJavaFx() throws InterruptedException {
Assumptions.assumeFalse(GraphicsEnvironment.isHeadless());
final CountDownLatch latch = new CountDownLatch(1);
Platform.startup(latch::countDown);
if (!latch.await(5L, TimeUnit.SECONDS)) {
throw new ExceptionInInitializerError();
}
}
@Nested
@DisplayName("Content Update Events")
class TextChange {
@Test
@DisplayName("\"ant\".append(\"eater\")")
public void append() {
pwField.setPassword("ant");
pwField.appendText("eater");
Assertions.assertEquals("anteater", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"eater\".insert(0, \"ant\")")
public void insert1() {
pwField.setPassword("eater");
pwField.insertText(0, "ant");
Assertions.assertEquals("anteater", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".insert(3, \"b\")")
public void insert2() {
pwField.setPassword("anteater");
pwField.insertText(3, "b");
Assertions.assertEquals("antbeater", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".delete(0, 3)")
public void delete1() {
pwField.setPassword("anteater");
pwField.deleteText(0, 3);
Assertions.assertEquals("eater", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".delete(3, 8)")
public void delete2() {
pwField.setPassword("anteater");
pwField.deleteText(3, 8);
Assertions.assertEquals("ant", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".replace(0, 3, \"hand\")")
public void replace1() {
pwField.setPassword("anteater");
pwField.replaceText(0, 3, "hand");
Assertions.assertEquals("handeater", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".replace(3, 6, \"keep\")")
public void replace2() {
pwField.setPassword("anteater");
pwField.replaceText(3, 6, "keep");
Assertions.assertEquals("antkeeper", pwField.getCharacters().toString());
}
@Test
@DisplayName("\"anteater\".replace(0, 3, \"bee\")")
public void replace3() {
pwField.setPassword("anteater");
pwField.replaceText(0, 3, "bee");
Assertions.assertEquals("beeeater", pwField.getCharacters().toString());
}
}
@Test
@DisplayName("entering NFC string leads to NFC char[]")
public void enterNfcString() {
pwField.appendText("str\u00F6m"); // ström
pwField.insertText(0, "\u212Bng"); // Ång
pwField.appendText("\uD83D\uDCA9"); // 💩
CharSequence result = pwField.getCharacters();
Assertions.assertEquals('\u00C5', result.charAt(0));
Assertions.assertEquals('n', result.charAt(1));
Assertions.assertEquals('g', result.charAt(2));
Assertions.assertEquals('s', result.charAt(3));
Assertions.assertEquals('t', result.charAt(4));
Assertions.assertEquals('r', result.charAt(5));
Assertions.assertEquals('ö', result.charAt(6));
Assertions.assertEquals('m', result.charAt(7));
Assertions.assertEquals('\uD83D', result.charAt(8));
Assertions.assertEquals('\uDCA9', result.charAt(9));
}
@Test
@DisplayName("entering NFD string leads to NFC char[]")
public void enterNfdString() {
pwField.appendText("str\u006F\u0308m"); // ström
pwField.insertText(0, "\u0041\u030Ang"); // Ång
pwField.appendText("\uD83D\uDCA9"); // 💩
CharSequence result = pwField.getCharacters();
Assertions.assertEquals('\u00C5', result.charAt(0));
Assertions.assertEquals('n', result.charAt(1));
Assertions.assertEquals('g', result.charAt(2));
Assertions.assertEquals('s', result.charAt(3));
Assertions.assertEquals('t', result.charAt(4));
Assertions.assertEquals('r', result.charAt(5));
Assertions.assertEquals('ö', result.charAt(6));
Assertions.assertEquals('m', result.charAt(7));
Assertions.assertEquals('\uD83D', result.charAt(8));
Assertions.assertEquals('\uDCA9', result.charAt(9));
}
@Test
@DisplayName("test swipe char[]")
public void testSwipe() {
pwField.appendText("topSecret");
CharSequence result1 = pwField.getCharacters();
Assertions.assertEquals("topSecret", result1.toString());
pwField.wipe();
CharSequence result2 = pwField.getCharacters();
Assertions.assertEquals(" ", result1.toString());
Assertions.assertEquals("", result2.toString());
}
@Test
@DisplayName("test control characters")
public void testControlCharacters() {
pwField.appendText("normal");
Assertions.assertFalse(pwField.containsNonPrintableCharacters());
pwField.appendText("\00\01\02");
Assertions.assertTrue(pwField.containsNonPrintableCharacters());
CharSequence result1 = pwField.getCharacters();
Assertions.assertEquals("normal\00\01\02", result1.toString());
}
}
@@ -0,0 +1,73 @@
package org.cryptomator.ui.recoverykey;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.Optional;
import java.util.Set;
class AutoCompleterTest {
@Test
@DisplayName("no match in []")
public void testNoMatchInEmptyDict() {
AutoCompleter autoCompleter = new AutoCompleter(Set.of());
Optional<String> result = autoCompleter.autocomplete("tea");
Assertions.assertFalse(result.isPresent());
}
@Test
@DisplayName("no match for \"\"")
public void testNoMatchForEmptyString() {
AutoCompleter autoCompleter = new AutoCompleter(Set.of("asd"));
Optional<String> result = autoCompleter.autocomplete("");
Assertions.assertFalse(result.isPresent());
}
@Nested
@DisplayName("search in dict: ['tame', 'teach', 'teacher']")
class NarrowedDownDict {
AutoCompleter autoCompleter = new AutoCompleter(Set.of("tame", "teach", "teacher"));
@ParameterizedTest
@DisplayName("find 'tame'")
@ValueSource(strings = {"t", "ta", "tam", "tame"})
public void testFindTame(String prefix) {
Optional<String> result = autoCompleter.autocomplete(prefix);
Assertions.assertTrue(result.isPresent());
Assertions.assertEquals("tame", result.get());
}
@ParameterizedTest
@DisplayName("find 'teach'")
@ValueSource(strings = {"te", "tea", "teac", "teach"})
public void testFindTeach(String prefix) {
Optional<String> result = autoCompleter.autocomplete(prefix);
Assertions.assertTrue(result.isPresent());
Assertions.assertEquals("teach", result.get());
}
@ParameterizedTest
@DisplayName("find 'teacher'")
@ValueSource(strings = {"teache", "teacher"})
public void testFindTeacher(String prefix) {
Optional<String> result = autoCompleter.autocomplete(prefix);
Assertions.assertTrue(result.isPresent());
Assertions.assertEquals("teacher", result.get());
}
@Test
@DisplayName("don't find 'teachers'")
public void testDontFindTeachers() {
Optional<String> result = autoCompleter.autocomplete("teachers");
Assertions.assertFalse(result.isPresent());
}
}
}
@@ -0,0 +1,79 @@
package org.cryptomator.ui.recoverykey;
import com.google.common.base.Splitter;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.io.IOException;
import java.nio.file.Path;
import java.security.SecureRandom;
class RecoveryKeyFactoryTest {
private WordEncoder wordEncoder = new WordEncoder();
private MasterkeyFileAccess masterkeyFileAccess = Mockito.mock(MasterkeyFileAccess.class);
private RecoveryKeyFactory inTest = new RecoveryKeyFactory(wordEncoder, masterkeyFileAccess);
@Test
@DisplayName("createRecoveryKey() creates 44 words")
public void testCreateRecoveryKey() throws IOException, CryptoException {
Path pathToVault = Path.of("path/to/vault");
Masterkey masterkey = Mockito.mock(Masterkey.class);
Mockito.when(masterkeyFileAccess.load(pathToVault.resolve("masterkey.cryptomator"), "asd")).thenReturn(masterkey);
Mockito.when(masterkey.getEncoded()).thenReturn(new byte[64]);
String recoveryKey = inTest.createRecoveryKey(pathToVault, "asd");
Assertions.assertNotNull(recoveryKey);
Assertions.assertEquals(44, Splitter.on(' ').splitToList(recoveryKey).size()); // 66 bytes encoded as 44 words
}
@Test
@DisplayName("validateRecoveryKey() with odd number of words")
public void testValidateValidateRecoveryKeyWithOddNumberOfWords() {
boolean result = inTest.validateRecoveryKey("pathway");
Assertions.assertFalse(result);
}
@Test
@DisplayName("validateRecoveryKey() with words not in dictionary")
public void testValidateValidateRecoveryKeyWithGarbageInput() {
boolean result = inTest.validateRecoveryKey("Backpfeifengesicht Schweinehund"); // according to le internet these are typical German words
Assertions.assertFalse(result);
}
@Test
@DisplayName("validateRecoveryKey() with too short input")
public void testValidateValidateRecoveryKeyWithTooShortInput() {
boolean result = inTest.validateRecoveryKey("pathway lift");
Assertions.assertFalse(result);
}
@Test
@DisplayName("validateRecoveryKey() with invalid checksum")
public void testValidateValidateRecoveryKeyWithInvalidCrc() {
boolean result = inTest.validateRecoveryKey("""
pathway lift abuse plenty export texture gentleman landscape beyond ceiling around leaf cafe charity \
border breakdown victory surely computer cat linger restrict infer crowd live computer true written amazed \
investor boot depth left theory snow whereby terminal weekly reject happiness circuit partial cup wrong \
""");
Assertions.assertFalse(result);
}
@Test
@DisplayName("validateRecoveryKey() with valid input")
public void testValidateValidateRecoveryKeyWithValidKey() {
boolean result = inTest.validateRecoveryKey("""
pathway lift abuse plenty export texture gentleman landscape beyond ceiling around leaf cafe charity \
border breakdown victory surely computer cat linger restrict infer crowd live computer true written amazed \
investor boot depth left theory snow whereby terminal weekly reject happiness circuit partial cup ad \
""");
Assertions.assertTrue(result);
}
}
@@ -0,0 +1,42 @@
package org.cryptomator.ui.recoverykey;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class WordEncoderTest {
private static final Random PRNG = new Random(42l);
private WordEncoder encoder;
@BeforeAll
public void setup() {
encoder = new WordEncoder();
}
@DisplayName("decode(encode(input)) == input")
@ParameterizedTest(name = "test {index}")
@MethodSource("createRandomByteSequences")
void encodeAndDecode(byte[] input) {
String encoded = encoder.encodePadded(input);
byte[] decoded = encoder.decode(encoded);
Assertions.assertArrayEquals(input, decoded);
}
static Stream<byte[]> createRandomByteSequences() {
return IntStream.range(0, 30).mapToObj(i -> {
byte[] randomBytes = new byte[i * 3];
PRNG.nextBytes(randomBytes);
return randomBytes;
});
}
}
@@ -0,0 +1 @@
mock-maker-inline