From 86b8be9f17168e6efe689f0c8537281d64a822db Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 7 Jun 2023 10:04:50 +0200 Subject: [PATCH] In-memory implementations of the store api using JaxB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new implementations are ment to be used in test classes replacing the older implementations like `InMemoryConfigurationStoreFactory`. The benefit of these new classes is that the serialization using JaxB is testet implicitly avoiding mistakes made with XML annotations on the data classes. Committed-by: Eduard Heimbuch Co-authored-by: René Pfeuffer --- .../jaxb_implementations_for_test_stores.yaml | 2 + .../scm/store/ConfigurationEntryStore.java | 7 +- .../store/JAXBConfigurationEntryStore.java | 5 - .../scm/store/InMemoryBlobStoreFactory.java | 10 +- .../InMemoryByteConfigurationEntryStore.java | 98 +++++++++++++++++++ ...oryByteConfigurationEntryStoreFactory.java | 56 +++++++++++ .../store/InMemoryByteConfigurationStore.java | 67 +++++++++++++ ...InMemoryByteConfigurationStoreFactory.java | 51 ++++++++++ .../scm/store/InMemoryByteDataStore.java | 10 ++ .../store/InMemoryByteDataStoreFactory.java | 13 ++- .../InMemoryConfigurationEntryStore.java | 4 + ...nMemoryConfigurationEntryStoreFactory.java | 4 + .../scm/store/InMemoryConfigurationStore.java | 7 +- .../InMemoryConfigurationStoreFactory.java | 9 +- .../InMemoryStoreParameterNameComputer.java | 38 +++++++ .../scm/security/PermissionAssignerTest.java | 4 +- .../sonia/scm/update/UpdateEngineTest.java | 4 +- .../group/XmlGroupV1UpdateStepTest.java | 8 +- .../XmlRepositoryV1UpdateStepTest.java | 7 +- .../security/XmlSecurityV1UpdateStepTest.java | 14 +-- .../update/user/XmlUserV1UpdateStepTest.java | 10 +- 21 files changed, 379 insertions(+), 49 deletions(-) create mode 100644 gradle/changelog/jaxb_implementations_for_test_stores.yaml create mode 100644 scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStore.java create mode 100644 scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStoreFactory.java create mode 100644 scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStore.java create mode 100644 scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStoreFactory.java create mode 100644 scm-test/src/main/java/sonia/scm/store/InMemoryStoreParameterNameComputer.java diff --git a/gradle/changelog/jaxb_implementations_for_test_stores.yaml b/gradle/changelog/jaxb_implementations_for_test_stores.yaml new file mode 100644 index 0000000000..eef2f6950a --- /dev/null +++ b/gradle/changelog/jaxb_implementations_for_test_stores.yaml @@ -0,0 +1,2 @@ +- type: added + description: New in-memory implementations of the store api for unit tests using JaxB diff --git a/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStore.java b/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStore.java index 92cd37c407..c750196c9c 100644 --- a/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStore.java +++ b/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStore.java @@ -24,6 +24,8 @@ package sonia.scm.store; +import com.google.common.collect.Collections2; + import java.util.Collection; import java.util.function.Predicate; @@ -42,10 +44,13 @@ public interface ConfigurationEntryStore extends DataStore { /** * Return all values matching the given {@link Predicate}. * + * Default implementation since 2.44.0 * * @param predicate predicate to match values * * @return filtered collection of values */ - Collection getMatchingValues(Predicate predicate); + default Collection getMatchingValues(Predicate predicate) { + return Collections2.filter(getAll().values(), predicate::test); + } } diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java index 016ca04cbf..6440eda94a 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java @@ -131,11 +131,6 @@ public class JAXBConfigurationEntryStore implements ConfigurationEntryStore getMatchingValues(Predicate predicate) { - return Collections2.filter(entries.values(), predicate::test); - } - private void load() { LOG.debug("load configuration from {}", file); execute(() -> diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryBlobStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryBlobStoreFactory.java index 58ecc31ec0..037d6c7552 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryBlobStoreFactory.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryBlobStoreFactory.java @@ -27,7 +27,7 @@ package sonia.scm.store; import java.util.HashMap; import java.util.Map; -public class InMemoryBlobStoreFactory implements BlobStoreFactory { +public class InMemoryBlobStoreFactory implements BlobStoreFactory, InMemoryStoreParameterNameComputer { private final Map stores = new HashMap<>(); @@ -49,12 +49,4 @@ public class InMemoryBlobStoreFactory implements BlobStoreFactory { return fixedStore; } } - - private String computeKey(StoreParameters storeParameters) { - if (storeParameters.getRepositoryId() == null) { - return storeParameters.getName(); - } else { - return storeParameters.getName() + "/" + storeParameters.getRepositoryId(); - } - } } diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStore.java new file mode 100644 index 0000000000..d5934fb19f --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStore.java @@ -0,0 +1,98 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.store; + +import sonia.scm.security.KeyGenerator; +import sonia.scm.security.UUIDKeyGenerator; + +import javax.xml.bind.JAXB; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class InMemoryByteConfigurationEntryStore implements ConfigurationEntryStore { + + private final Class type; + private final KeyGenerator generator = new UUIDKeyGenerator(); + private final Map store = new HashMap<>(); + + public InMemoryByteConfigurationEntryStore(Class type) { + this.type = type; + } + + @Override + public String put(V item) { + String id = generator.createKey(); + put(id, item); + return id; + } + + @Override + public void put(String id, V item) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JAXB.marshal(item, baos); + store.put(id, baos.toByteArray()); + } + + /** + * This method can be used to mock stores with old types to test update steps or otherwise the compatability of + * objects with old versions. + */ + public void putOldObject(String id, Object item) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JAXB.marshal(item, baos); + store.put(id, baos.toByteArray()); + } + + @Override + public Map getAll() { + Map all = new HashMap<>(); + for (String id : store.keySet()) { + all.put(id, get(id)); + } + return Collections.unmodifiableMap(all); + } + + @Override + public void clear() { + store.clear(); + } + + @Override + public void remove(String id) { + store.remove(id); + } + + @Override + public V get(String id) { + byte[] bytes = store.get(id); + if (bytes != null) { + return JAXB.unmarshal(new ByteArrayInputStream(bytes), type); + } + return null; + } +} diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStoreFactory.java new file mode 100644 index 0000000000..eeec98ec13 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationEntryStoreFactory.java @@ -0,0 +1,56 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.store; + +import java.util.HashMap; +import java.util.Map; + +/** + * Stores data in memory but in contrast to {@link InMemoryConfigurationEntryStoreFactory} + * it uses jaxb to marshal and unmarshall the objects. + * + * @since 2.44.0 + */ +public class InMemoryByteConfigurationEntryStoreFactory implements ConfigurationEntryStoreFactory, InMemoryStoreParameterNameComputer { + + @SuppressWarnings("rawtypes") + private final Map stores = new HashMap<>(); + + public static InMemoryByteConfigurationEntryStoreFactory create() { + return new InMemoryByteConfigurationEntryStoreFactory(); + } + + @Override + public ConfigurationEntryStore getStore(TypedStoreParameters storeParameters) { + String name = computeKey(storeParameters); + Class type = storeParameters.getType(); + return get(type, name); + } + + @SuppressWarnings("unchecked") + public ConfigurationEntryStore get(Class type, String name) { + return stores.computeIfAbsent(name, n -> new InMemoryByteConfigurationEntryStore<>(type)); + } +} diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStore.java new file mode 100644 index 0000000000..3025a3e810 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStore.java @@ -0,0 +1,67 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.store; + +import javax.xml.bind.JAXB; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * In memory store implementation of {@link ConfigurationStore} using a byte array to store the serialized object. + */ +public class InMemoryByteConfigurationStore implements ConfigurationStore { + + private final Class type; + byte[] store; + + public InMemoryByteConfigurationStore(Class type) { + this.type = type; + } + + @Override + public T get() { + if (store != null) { + return JAXB.unmarshal(new ByteArrayInputStream(store), type); + } + return null; + } + + @Override + public void set(T object) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JAXB.marshal(object, baos); + store = baos.toByteArray(); + } + + /** + * This method can be used to mock stores with old types to test update steps or otherwise the compatability of + * objects with old versions. + */ + public void setOldObject(Object object) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JAXB.marshal(object, baos); + store = baos.toByteArray(); + } +} diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStoreFactory.java new file mode 100644 index 0000000000..4c6ffb6934 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteConfigurationStoreFactory.java @@ -0,0 +1,51 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.store; + +import java.util.HashMap; +import java.util.Map; + +/** + * In memory configuration store factory for testing purposes that uses JaxB for serialization. + * + * @since 2.44.0 + */ +public class InMemoryByteConfigurationStoreFactory implements ConfigurationStoreFactory, InMemoryStoreParameterNameComputer { + + @SuppressWarnings("rawtypes") + private final Map stores = new HashMap<>(); + + @Override + public ConfigurationStore getStore(TypedStoreParameters storeParameters) { + String name = computeKey(storeParameters); + Class type = storeParameters.getType(); + return getStore(type, name); + } + + @SuppressWarnings("unchecked") + public ConfigurationStore getStore(Class type, String name) { + return stores.computeIfAbsent(name, n -> new InMemoryByteConfigurationStore<>(type)); + } +} diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStore.java index fa67ee0b2f..9e902054e5 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStore.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStore.java @@ -58,6 +58,16 @@ public class InMemoryByteDataStore implements DataStore { store.put(id, baos.toByteArray()); } + /** + * This method can be used to mock stores with old types to test update steps or otherwise the compatability of + * objects with old versions. + */ + public void putOldObject(String id, Object item) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JAXB.marshal(item, baos); + store.put(id, baos.toByteArray()); + } + @Override public Map getAll() { Map all = new HashMap<>(); diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStoreFactory.java index 2cbbbf78fc..348255b609 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStoreFactory.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryByteDataStoreFactory.java @@ -33,15 +33,20 @@ import java.util.Map; * * @since 2.18.0 */ -public class InMemoryByteDataStoreFactory implements DataStoreFactory { +public class InMemoryByteDataStoreFactory implements DataStoreFactory, InMemoryStoreParameterNameComputer { @SuppressWarnings("rawtypes") private final Map stores = new HashMap<>(); @Override - @SuppressWarnings("unchecked") public DataStore getStore(TypedStoreParameters storeParameters) { - String name = storeParameters.getName(); - return stores.computeIfAbsent(name, n -> new InMemoryByteDataStore(storeParameters.getType())); + String name = computeKey(storeParameters); + Class type = storeParameters.getType(); + return getStore(type, name); + } + + @SuppressWarnings("unchecked") + public DataStore getStore(Class type, String name) { + return stores.computeIfAbsent(name, n -> new InMemoryByteDataStore<>(type)); } } diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStore.java index f150b4bdf8..940c0893e5 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStore.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStore.java @@ -33,6 +33,10 @@ import java.util.UUID; import java.util.function.Predicate; import java.util.stream.Collectors; +/** + * @deprecated Replaced by {@link InMemoryByteConfigurationEntryStore} + */ +@Deprecated(since = "2.44.0") public class InMemoryConfigurationEntryStore implements ConfigurationEntryStore { private final Map values = new HashMap<>(); diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStoreFactory.java index 51b31aca67..4296f86a6e 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStoreFactory.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationEntryStoreFactory.java @@ -27,6 +27,10 @@ package sonia.scm.store; import java.util.HashMap; import java.util.Map; +/** + * @deprecated Use {@link InMemoryByteConfigurationEntryStoreFactory} instead to verify JaxB serialization, too. + */ +@Deprecated(since = "2.44.0") public class InMemoryConfigurationEntryStoreFactory implements ConfigurationEntryStoreFactory { private final Map stores = new HashMap<>(); diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStore.java b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStore.java index 560c0779f1..0d1cf1f306 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStore.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStore.java @@ -21,16 +21,19 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.store; /** * In memory store implementation of {@link ConfigurationStore}. - * + * * @author Sebastian Sdorra * * @param type of stored object + * + * @deprecated Replaced by the {@link InMemoryByteConfigurationStore} */ +@Deprecated(since = "2.44.0") public class InMemoryConfigurationStore implements ConfigurationStore { private T object; diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java index d497fc7bd9..504213fb69 100644 --- a/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryConfigurationStoreFactory.java @@ -21,10 +21,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - -package sonia.scm.store; -//~--- non-JDK imports -------------------------------------------------------- +package sonia.scm.store; import java.util.HashMap; import java.util.Map; @@ -32,10 +30,11 @@ import java.util.Map; /** * In memory configuration store factory for testing purposes. * - * Use {@link #create()} to get a store that creates the same store on each request. - * * @author Sebastian Sdorra + * + * @deprecated Use the {@link InMemoryByteConfigurationStoreFactory} to verify JaxB serialization, too. */ +@Deprecated(since = "2.44.0") public class InMemoryConfigurationStoreFactory implements ConfigurationStoreFactory { private final Map stores = new HashMap<>(); diff --git a/scm-test/src/main/java/sonia/scm/store/InMemoryStoreParameterNameComputer.java b/scm-test/src/main/java/sonia/scm/store/InMemoryStoreParameterNameComputer.java new file mode 100644 index 0000000000..6d545f99c7 --- /dev/null +++ b/scm-test/src/main/java/sonia/scm/store/InMemoryStoreParameterNameComputer.java @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.store; + +interface InMemoryStoreParameterNameComputer { + + default String computeKey(StoreParameters storeParameters) { + if (storeParameters.getNamespace() != null) { + return storeParameters.getName() + "/" + storeParameters.getNamespace(); + } else if (storeParameters.getRepositoryId() != null) { + return storeParameters.getName() + "/" + storeParameters.getRepositoryId(); + } else { + return storeParameters.getName(); + } + } +} diff --git a/scm-webapp/src/test/java/sonia/scm/security/PermissionAssignerTest.java b/scm-webapp/src/test/java/sonia/scm/security/PermissionAssignerTest.java index e8e629f5ad..e6bf5109df 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/PermissionAssignerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/PermissionAssignerTest.java @@ -34,7 +34,7 @@ import org.junit.rules.ExpectedException; import sonia.scm.NotFoundException; import sonia.scm.auditlog.Auditor; import sonia.scm.plugin.PluginLoader; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import sonia.scm.util.ClassLoaders; import java.util.Arrays; @@ -70,7 +70,7 @@ public class PermissionAssignerTest { PluginLoader pluginLoader = mock(PluginLoader.class); when(pluginLoader.getUberClassLoader()).thenReturn(ClassLoaders.getContextClassLoader(DefaultSecuritySystem.class)); - securitySystem = new DefaultSecuritySystem(new InMemoryConfigurationEntryStoreFactory(), pluginLoader, Set.of(auditor)) { + securitySystem = new DefaultSecuritySystem(new InMemoryByteConfigurationEntryStoreFactory(), pluginLoader, Set.of(auditor)) { @Override public Collection getAvailablePermissions() { return Arrays.stream(new String[]{"perm:read:1", "perm:read:2", "perm:read:3", "perm:read:4"}) diff --git a/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java b/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java index e57ad9737b..5a8f007ac0 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java @@ -30,7 +30,7 @@ import sonia.scm.migration.RepositoryUpdateContext; import sonia.scm.migration.RepositoryUpdateStep; import sonia.scm.migration.UpdateStep; import sonia.scm.store.ConfigurationEntryStoreFactory; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import sonia.scm.version.Version; import java.util.ArrayList; @@ -50,7 +50,7 @@ import static sonia.scm.version.Version.parse; class UpdateEngineTest { - ConfigurationEntryStoreFactory storeFactory = new InMemoryConfigurationEntryStoreFactory(); + ConfigurationEntryStoreFactory storeFactory = new InMemoryByteConfigurationEntryStoreFactory(); RepositoryUpdateIterator repositoryUpdateIterator = mock(RepositoryUpdateIterator.class, CALLS_REAL_METHODS); UpdateStepStore updateStepStore = new UpdateStepStore(storeFactory); diff --git a/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java index 434dc075d5..1577ad0dab 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java @@ -36,7 +36,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.group.Group; import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.store.ConfigurationEntryStore; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import sonia.scm.update.UpdateStepTestUtil; import sonia.scm.update.V1Properties; @@ -51,7 +51,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static sonia.scm.store.InMemoryConfigurationEntryStoreFactory.create; +import static sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory.create; @ExtendWith(MockitoExtension.class) class XmlGroupV1UpdateStepTest { @@ -62,7 +62,7 @@ class XmlGroupV1UpdateStepTest { @Captor ArgumentCaptor groupCaptor; - InMemoryConfigurationEntryStoreFactory storeFactory = create(); + InMemoryByteConfigurationEntryStoreFactory storeFactory = create(); XmlGroupV1UpdateStep updateStep; @@ -111,7 +111,7 @@ class XmlGroupV1UpdateStepTest { @Test void shouldExtractProperties() throws JAXBException { updateStep.doUpdate(); - ConfigurationEntryStore propertiesStore = storeFactory.get("group-properties-v1"); + ConfigurationEntryStore propertiesStore = storeFactory.get(V1Properties.class, "group-properties-v1"); V1Properties properties = propertiesStore.get("normals"); assertThat(properties).isNotNull(); assertThat(properties.get("mostly")).isEqualTo("humans"); diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java index 595bbb957a..9a6fd8561c 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java @@ -40,8 +40,9 @@ import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryPermission; import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.store.ConfigurationEntryStore; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import sonia.scm.update.UpdateStepTestUtil; +import sonia.scm.update.V1Properties; import javax.xml.bind.JAXBException; import java.io.IOException; @@ -72,7 +73,7 @@ class XmlRepositoryV1UpdateStepTest { @Mock DefaultMigrationStrategyDAO migrationStrategyDao; - InMemoryConfigurationEntryStoreFactory configurationEntryStoreFactory = new InMemoryConfigurationEntryStoreFactory(); + InMemoryByteConfigurationEntryStoreFactory configurationEntryStoreFactory = new InMemoryByteConfigurationEntryStoreFactory(); @Captor ArgumentCaptor storeCaptor; @@ -172,7 +173,7 @@ class XmlRepositoryV1UpdateStepTest { void shouldExtractPropertiesFromRepositories() throws JAXBException { updateStep.doUpdate(); - ConfigurationEntryStore store = configurationEntryStoreFactory.get("repository-properties-v1"); + ConfigurationEntryStore store = configurationEntryStoreFactory.get(V1Properties.class,"repository-properties-v1"); assertThat(store.getAll()) .hasSize(3); } diff --git a/scm-webapp/src/test/java/sonia/scm/update/security/XmlSecurityV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/security/XmlSecurityV1UpdateStepTest.java index f5d8c88ccc..28c3f687b1 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/security/XmlSecurityV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/security/XmlSecurityV1UpdateStepTest.java @@ -35,7 +35,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.SCMContextProvider; import sonia.scm.security.AssignedPermission; import sonia.scm.store.ConfigurationEntryStore; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import javax.xml.bind.JAXBException; import java.io.IOException; @@ -43,12 +43,11 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.Map; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import static sonia.scm.store.InMemoryConfigurationEntryStoreFactory.create; +import static sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory.create; @ExtendWith(MockitoExtension.class) class XmlSecurityV1UpdateStepTest { @@ -65,8 +64,8 @@ class XmlSecurityV1UpdateStepTest { @BeforeEach void mockScmHome() { when(contextProvider.getBaseDirectory()).thenReturn(tempDir.toFile()); - InMemoryConfigurationEntryStoreFactory inMemoryConfigurationEntryStoreFactory = create(); - assignedPermissionStore = inMemoryConfigurationEntryStoreFactory.get("security"); + InMemoryByteConfigurationEntryStoreFactory inMemoryConfigurationEntryStoreFactory = create(); + assignedPermissionStore = inMemoryConfigurationEntryStoreFactory.get(AssignedPermission.class, "security"); updateStep = new XmlSecurityV1UpdateStep(contextProvider, inMemoryConfigurationEntryStoreFactory); } @@ -129,8 +128,9 @@ class XmlSecurityV1UpdateStepTest { .filter(a -> a.getPermission().getValue().contains("repository:")) .map(AssignedPermission::getName) .collect(toList()); - assertThat(assignedPermission).contains("scmadmin"); - assertThat(assignedPermission).contains("test"); + assertThat(assignedPermission) + .contains("scmadmin") + .contains("test"); } @Test diff --git a/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java index da9e3ccb7d..c42e677675 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java @@ -35,7 +35,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import sonia.scm.security.AssignedPermission; import sonia.scm.store.ConfigurationEntryStore; -import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; +import sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory; import sonia.scm.update.UpdateStepTestUtil; import sonia.scm.update.V1Properties; import sonia.scm.user.User; @@ -51,7 +51,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static sonia.scm.store.InMemoryConfigurationEntryStoreFactory.create; +import static sonia.scm.store.InMemoryByteConfigurationEntryStoreFactory.create; @ExtendWith(MockitoExtension.class) class XmlUserV1UpdateStepTest { @@ -62,7 +62,7 @@ class XmlUserV1UpdateStepTest { @Captor ArgumentCaptor userCaptor; - InMemoryConfigurationEntryStoreFactory storeFactory = create(); + InMemoryByteConfigurationEntryStoreFactory storeFactory = create(); XmlUserV1UpdateStep updateStep; @@ -91,7 +91,7 @@ class XmlUserV1UpdateStepTest { void shouldCreateNewPermissionsForV1AdminUser() throws JAXBException { updateStep.doUpdate(); Optional assignedPermission = - storeFactory.get("security") + storeFactory.get(AssignedPermission.class, "security") .getAll() .values() .stream() @@ -126,7 +126,7 @@ class XmlUserV1UpdateStepTest { @Test void shouldExtractProperties() throws JAXBException { updateStep.doUpdate(); - ConfigurationEntryStore propertiesStore = storeFactory.get("user-properties-v1"); + ConfigurationEntryStore propertiesStore = storeFactory.get(V1Properties.class, "user-properties-v1"); V1Properties properties = propertiesStore.get("dent"); assertThat(properties).isNotNull(); assertThat(properties.get("born.on")).isEqualTo("earth");