Add unit tests for micrometer / Wrap data stores with proxies

Squash commits of branch feature/store_metering:

- Wrap jaxb stores with proxies to get micrometer insights

- Handle exceptions from proxy

- User meter for queryable stores, too

- Log change

- Change name for metrics

- Fix imports

- Rename invocation handler

- Change change log

- Replace RuntimeException

- Merge branch 'develop' into feature/store_metering

- Add store type to description of timer

- Fix measuring methods for queryable store

- License

- Simplify usage of wrapper

- Rename class

- Remove unnecessary condition
This commit is contained in:
Rene Pfeuffer
2025-08-12 20:48:53 +02:00
committed by Till-André Diegeler
parent 57f15f3ac4
commit ce01cfc602
11 changed files with 749 additions and 111 deletions

View File

@@ -0,0 +1,2 @@
- type: added
description: Performance of stores can be measured with Micrometer metrics

View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 2020 - present Cloudogu GmbH
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
package sonia.scm.store;
import com.google.common.annotations.VisibleForTesting;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import sonia.scm.util.AssertUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public class StoreInvocationMicrometerWrapper implements InvocationHandler {
private final Object store;
private final MeterRegistry meterRegistry;
private final Consumer<Timer.Builder> timerCustomizer;
private final Supplier<Timer.Builder> timerBuilder;
/**
* Creates a wrapper for the given store which will record the time taken for each method call.
* If the {@link MeterRegistry} is {@code null}, the store will not be wrapped and returned as is.
*/
public static <T> T create(String storeType,
TypedStoreParameters<?> storeParameters,
Class<T> storeClass,
T store,
MeterRegistry meterRegistry) {
if (meterRegistry == null) {
return store;
}
return (T) Proxy.newProxyInstance(
storeParameters.getType().getClassLoader(),
new Class[]{storeClass},
new StoreInvocationMicrometerWrapper(
storeType,
storeParameters,
store,
meterRegistry,
() -> Timer.builder("scm.persistence")
)
);
}
/**
* Creates a wrapper for the given store which will record the time taken for each method call.
* If the {@link MeterRegistry} is {@code null}, the store will not be wrapped and returned as is.
*/
public static <T, Q> Q create(String storeType,
Class<T> clazz,
String[] parentIds,
Class<Q> storeClass,
Q store,
MeterRegistry meterRegistry) {
if (meterRegistry == null) {
return store;
}
return (Q) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{storeClass},
new StoreInvocationMicrometerWrapper(
storeType,
clazz,
parentIds,
store,
meterRegistry,
() -> Timer.builder("scm.persistence")
)
);
}
@VisibleForTesting
StoreInvocationMicrometerWrapper(String storeType,
TypedStoreParameters<?> storeParameters,
Object store,
MeterRegistry meterRegistry,
Supplier<Timer.Builder> timerBuilder) {
this(
meterRegistry,
store,
timer -> timer
.description("Time taken for store operation in " + storeType)
.tag("type", storeType)
.tag("storeName", storeParameters.getName())
.tag("repositoryId", storeParameters.getRepositoryId() == null ? "none" : storeParameters.getRepositoryId())
.tag("namespace", storeParameters.getNamespace() == null ? "none" : storeParameters.getNamespace()),
timerBuilder
);
}
@VisibleForTesting
<T, Q> StoreInvocationMicrometerWrapper(String storeType,
Class<T> clazz,
String[] parentIds,
Q store,
MeterRegistry meterRegistry,
Supplier<Timer.Builder> timerBuilder) {
this(
meterRegistry,
store,
timer -> timer
.description("Time taken for store operation in " + storeType)
.tag("type", storeType)
.tag("storeClass", clazz.getName())
.tag("parentIds", String.join(",", parentIds)),
timerBuilder
);
}
private StoreInvocationMicrometerWrapper(MeterRegistry meterRegistry,
Object store,
Consumer<Timer.Builder> timerCustomizer,
Supplier<Timer.Builder> timerBuilder) {
AssertUtil.assertIsNotNull(store);
this.meterRegistry = meterRegistry;
this.store = store;
this.timerCustomizer = timerCustomizer;
this.timerBuilder = timerBuilder;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (meterRegistry == null) {
return method.invoke(store, args);
}
if (QueryableStore.Query.class.isAssignableFrom(method.getReturnType())) {
Object delegate = method.invoke(store, args);
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),
new StoreInvocationMicrometerWrapper(meterRegistry, delegate, timerCustomizer, timerBuilder)
);
}
try {
if (method.getName().equals("close")) {
return method.invoke(store, args);
}
Timer.Builder timer = timerBuilder.get()
.tag("method", method.getName());
timerCustomizer.accept(timer);
return timer
.register(meterRegistry)
.record(() -> {
try {
return method.invoke(store, args);
} catch (Exception e) {
throw new StoreException("Failed to invoke store method", e);
}
});
} catch (InvocationTargetException | UndeclaredThrowableException e) {
throw e.getCause();
}
}
}

View File

@@ -16,17 +16,19 @@
package sonia.scm.store.file;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.micrometer.core.instrument.MeterRegistry;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.RepositoryReadOnlyChecker;
import sonia.scm.security.KeyGenerator;
import sonia.scm.store.ConfigurationEntryStore;
import sonia.scm.store.ConfigurationEntryStoreFactory;
import sonia.scm.store.StoreInvocationMicrometerWrapper;
import sonia.scm.store.TypedStoreParameters;
@Singleton
public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
implements ConfigurationEntryStoreFactory {
@@ -35,17 +37,39 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
private final StoreCache<ConfigurationEntryStore<?>> storeCache;
@Inject
private final MeterRegistry meterRegistry;
@VisibleForTesting
public JAXBConfigurationEntryStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
KeyGenerator keyGenerator,
RepositoryReadOnlyChecker readOnlyChecker,
StoreCacheFactory storeCacheFactory
) {
this(
contextProvider,
repositoryLocationResolver,
keyGenerator,
readOnlyChecker,
storeCacheFactory,
null
);
}
@Inject
public JAXBConfigurationEntryStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
KeyGenerator keyGenerator,
RepositoryReadOnlyChecker readOnlyChecker,
StoreCacheFactory storeCacheFactory,
MeterRegistry meterRegistry
) {
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
this.keyGenerator = keyGenerator;
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
this.meterRegistry = meterRegistry;
}
@Override
@@ -54,8 +78,8 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
return (ConfigurationEntryStore<T>) storeCache.getStore(storeParameters);
}
private <T> ConfigurationEntryStore<T> createStore(TypedStoreParameters<T> storeParameters) {
return new JAXBConfigurationEntryStore<>(
private <T> ConfigurationEntryStore<T> createStore(TypedStoreParameters<T> storeParameters) {
JAXBConfigurationEntryStore<T> store = new JAXBConfigurationEntryStore<>(
getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION),
storeParameters.getType(),
storeParameters.getRepositoryId(),
@@ -64,5 +88,13 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory
storeParameters.getType(),
TypedStoreContext.of(storeParameters)
);
return StoreInvocationMicrometerWrapper.create(
"configuration-entry-store",
storeParameters,
ConfigurationEntryStore.class,
store,
meterRegistry
);
}
}

View File

@@ -16,14 +16,17 @@
package sonia.scm.store.file;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.micrometer.core.instrument.MeterRegistry;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.RepositoryReadOnlyChecker;
import sonia.scm.store.ConfigurationStore;
import sonia.scm.store.ConfigurationStoreDecoratorFactory;
import sonia.scm.store.ConfigurationStoreFactory;
import sonia.scm.store.StoreInvocationMicrometerWrapper;
import sonia.scm.store.StoreDecoratorFactory;
import sonia.scm.store.TypedStoreParameters;
@@ -40,17 +43,39 @@ public class JAXBConfigurationStoreFactory extends FileBasedStoreFactory impleme
private final StoreCache<ConfigurationStore<?>> storeCache;
@Inject
private final MeterRegistry meterRegistry;
@VisibleForTesting
public JAXBConfigurationStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
RepositoryReadOnlyChecker readOnlyChecker,
Set<ConfigurationStoreDecoratorFactory> decoratorFactories,
StoreCacheFactory storeCacheFactory
) {
this(
contextProvider,
repositoryLocationResolver,
readOnlyChecker,
decoratorFactories,
storeCacheFactory,
null
);
}
@Inject
public JAXBConfigurationStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
RepositoryReadOnlyChecker readOnlyChecker,
Set<ConfigurationStoreDecoratorFactory> decoratorFactories,
StoreCacheFactory storeCacheFactory,
MeterRegistry meterRegistry
) {
super(contextProvider, repositoryLocationResolver, Store.CONFIG, readOnlyChecker);
this.decoratorFactories = decoratorFactories;
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
this.meterRegistry = meterRegistry;
}
@Override
@@ -76,6 +101,12 @@ public class JAXBConfigurationStoreFactory extends FileBasedStoreFactory impleme
store = factory.createDecorator(store, new StoreDecoratorFactory.Context(storeParameters));
}
return store;
return StoreInvocationMicrometerWrapper.create(
"configuration-store",
storeParameters,
ConfigurationStore.class,
store,
meterRegistry
);
}
}

View File

@@ -16,20 +16,22 @@
package sonia.scm.store.file;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.micrometer.core.instrument.MeterRegistry;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.RepositoryReadOnlyChecker;
import sonia.scm.security.KeyGenerator;
import sonia.scm.store.DataStore;
import sonia.scm.store.DataStoreFactory;
import sonia.scm.store.StoreInvocationMicrometerWrapper;
import sonia.scm.store.TypedStoreParameters;
import sonia.scm.util.IOUtil;
import java.io.File;
@Singleton
public class JAXBDataStoreFactory extends FileBasedStoreFactory
implements DataStoreFactory {
@@ -40,7 +42,9 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
private final DataFileCache dataFileCache;
@Inject
private final MeterRegistry meterRegistry;
@VisibleForTesting
public JAXBDataStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
@@ -48,11 +52,33 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
RepositoryReadOnlyChecker readOnlyChecker,
DataFileCache dataFileCache,
StoreCacheFactory storeCacheFactory
) {
this(
contextProvider,
repositoryLocationResolver,
keyGenerator,
readOnlyChecker,
dataFileCache,
storeCacheFactory,
null
);
}
@Inject
public JAXBDataStoreFactory(
SCMContextProvider contextProvider,
RepositoryLocationResolver repositoryLocationResolver,
KeyGenerator keyGenerator,
RepositoryReadOnlyChecker readOnlyChecker,
DataFileCache dataFileCache,
StoreCacheFactory storeCacheFactory,
MeterRegistry meterRegistry
) {
super(contextProvider, repositoryLocationResolver, Store.DATA, readOnlyChecker);
this.keyGenerator = keyGenerator;
this.dataFileCache = dataFileCache;
this.storeCache = storeCacheFactory.createStoreCache(this::createStore);
this.meterRegistry = meterRegistry;
}
@Override
@@ -61,15 +87,25 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
return (DataStore<T>) storeCache.getStore(storeParameters);
}
private <T> DataStore<T> createStore(TypedStoreParameters<T> storeParameters) {
private <T> DataStore<T> createStore(TypedStoreParameters<T> storeParameters) {
File storeLocation = getStoreLocation(storeParameters);
IOUtil.mkdirs(storeLocation);
return new JAXBDataStore<>(
// Create a proxy for the created store and use Micrometer to instrument it
JAXBDataStore<T> store = new JAXBDataStore<>(
keyGenerator,
TypedStoreContext.of(storeParameters),
storeLocation,
mustBeReadOnly(storeParameters),
dataFileCache.instanceFor(storeParameters.getType())
);
return StoreInvocationMicrometerWrapper.create(
"data-store",
storeParameters,
DataStore.class,
store,
meterRegistry
);
}
}

View File

@@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.micrometer.core.instrument.MeterRegistry;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
@@ -31,7 +32,10 @@ import sonia.scm.plugin.QueryableTypeDescriptor;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryReadOnlyChecker;
import sonia.scm.security.KeyGenerator;
import sonia.scm.store.StoreInvocationMicrometerWrapper;
import sonia.scm.store.QueryableMaintenanceStore;
import sonia.scm.store.QueryableMutableStore;
import sonia.scm.store.QueryableStore;
import sonia.scm.store.QueryableStoreFactory;
import sonia.scm.store.StoreException;
@@ -62,6 +66,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
private final KeyGenerator keyGenerator;
private final DataSource dataSource;
private final RepositoryReadOnlyChecker readOnlyChecker;
private final MeterRegistry meterRegistry;
private final Map<String, QueryableTypeDescriptor> queryableTypes = new HashMap<>();
@@ -73,6 +78,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
ObjectMapper objectMapper,
KeyGenerator keyGenerator,
RepositoryReadOnlyChecker readOnlyChecker,
MeterRegistry meterRegistry,
@ConfigValue(key = "queryableStore.maxPoolSize", defaultValue = DEFAULT_MAX_POOL_SIZE) int maxPoolSize,
@ConfigValue(key = "queryableStore.connectionTimeout", defaultValue = DEFAULT_CONNECTION_TIMEOUT_IN_SECONDS) int connectionTimeoutInSeconds,
@ConfigValue(key = "queryableStore.idleTimeout", defaultValue = DEFAULT_IDLE_TIMEOUT_IN_SECONDS) int idleTimeoutInSeconds,
@@ -85,6 +91,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
keyGenerator,
pluginLoader.getExtensionProcessor().getQueryableTypes(),
readOnlyChecker,
meterRegistry,
maxPoolSize,
connectionTimeoutInSeconds,
idleTimeoutInSeconds,
@@ -99,7 +106,19 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
KeyGenerator keyGenerator,
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
RepositoryReadOnlyChecker readOnlyChecker) {
this(connectionString, objectMapper, keyGenerator, queryableTypeIterable, readOnlyChecker, 10, 30, 600, 1800, 30);
this(
connectionString,
objectMapper,
keyGenerator,
queryableTypeIterable,
readOnlyChecker,
null,
10,
30,
600,
1800,
30
);
}
private SQLiteQueryableStoreFactory(String connectionString,
@@ -107,6 +126,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
KeyGenerator keyGenerator,
Iterable<QueryableTypeDescriptor> queryableTypeIterable,
RepositoryReadOnlyChecker readOnlyChecker,
MeterRegistry meterRegistry,
int maxPoolSize,
int connectionTimeoutInSeconds,
int idleTimeoutInSeconds,
@@ -120,6 +140,7 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
maxLifetimeInSeconds,
leakDetectionThresholdInSeconds);
this.readOnlyChecker = readOnlyChecker;
this.meterRegistry = meterRegistry;
this.dataSource = new HikariDataSource(config);
this.objectMapper = objectMapper
@@ -177,9 +198,9 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
}
@Override
public <T> SQLiteQueryableStore<T> getReadOnly(Class<T> clazz, String... parentIds) {
public <T> QueryableStore<T> getReadOnly(Class<T> clazz, String... parentIds) {
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
return new SQLiteQueryableStore<>(
SQLiteQueryableStore<T> store = new SQLiteQueryableStore<>(
objectMapper,
openDefaultConnection(),
clazz,
@@ -188,12 +209,21 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
lock,
mustBeReadOnly(queryableTypeDescriptor, parentIds)
);
return StoreInvocationMicrometerWrapper.create(
"QueryableStore",
clazz,
parentIds,
QueryableStore.class,
store,
meterRegistry
);
}
@Override
public <T> QueryableMaintenanceStore<T> getForMaintenance(Class<T> clazz, String... parentIds) {
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
return new SQLiteQueryableStore<>(
SQLiteQueryableStore<T> store = new SQLiteQueryableStore<>(
objectMapper,
openDefaultConnection(),
clazz,
@@ -202,12 +232,21 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
lock,
mustBeReadOnly(queryableTypeDescriptor, parentIds)
);
return StoreInvocationMicrometerWrapper.create(
"QueryableMaintenanceStore",
clazz,
parentIds,
QueryableMaintenanceStore.class,
store,
meterRegistry
);
}
@Override
public <T> SQLiteQueryableMutableStore<T> getMutable(Class<T> clazz, String... parentIds) {
public <T> QueryableMutableStore<T> getMutable(Class<T> clazz, String... parentIds) {
QueryableTypeDescriptor queryableTypeDescriptor = getQueryableTypeDescriptor(clazz);
return new SQLiteQueryableMutableStore<>(
SQLiteQueryableMutableStore<T> store = new SQLiteQueryableMutableStore<>(
objectMapper,
keyGenerator,
openDefaultConnection(),
@@ -217,6 +256,15 @@ public class SQLiteQueryableStoreFactory implements QueryableStoreFactory {
lock,
mustBeReadOnly(queryableTypeDescriptor, parentIds)
);
return StoreInvocationMicrometerWrapper.create(
"QueryableMutableStore",
clazz,
parentIds,
QueryableMutableStore.class,
store,
meterRegistry
);
}
private boolean mustBeReadOnly(QueryableTypeDescriptor queryableTypeDescriptor, String... parentIds) {

View File

@@ -0,0 +1,309 @@
/*
* Copyright (c) 2020 - present Cloudogu GmbH
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
package sonia.scm.store;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.user.User;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.function.Supplier;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Answers.RETURNS_SELF;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class StoreInvocationMicrometerWrapperTest {
@Mock
private MeterRegistry meterRegistry;
@Mock(answer = RETURNS_SELF)
private Timer.Builder timerBuilder;
@Mock
private Timer timer;
@BeforeEach
void setUpTimer() {
when(timerBuilder.register(any()))
.thenReturn(timer);
when(timer.record(any(Supplier.class)))
.thenAnswer(i -> i.getArgument(0, Supplier.class).get());
}
@Nested
class ForSimpleStore {
@Mock
private DataStore<User> dataStore;
@Mock
private TypedStoreParameters<User> storeParameters;
@BeforeEach
void setUpStore() {
when(storeParameters.getName())
.thenReturn("users");
when(dataStore.get("42")).thenReturn(new User("dent"));
}
@Test
void shouldMeasureDirectCallForGlobalStore() {
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"data",
storeParameters,
dataStore,
meterRegistry,
() -> timerBuilder
);
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
User result = store
.get("42");
assertThat(result)
.extracting(User::getName)
.isEqualTo("dent");
verify(timerBuilder).description("Time taken for store operation in data");
verify(timerBuilder).tag("method", "get");
verify(timerBuilder).tag("type", "data");
verify(timerBuilder).tag("storeName", "users");
verify(timerBuilder).tag("repositoryId", "none");
verify(timerBuilder).tag("namespace", "none");
verify(timer, only()).record(any(Supplier.class));
}
@Test
void shouldMeasureDirectCallForRepositoryStore() {
when(storeParameters.getRepositoryId())
.thenReturn("hog");
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"data",
storeParameters,
dataStore,
meterRegistry,
() -> timerBuilder
);
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
User result = store
.get("42");
assertThat(result)
.extracting(User::getName)
.isEqualTo("dent");
verify(timerBuilder).description("Time taken for store operation in data");
verify(timerBuilder).tag("method", "get");
verify(timerBuilder).tag("repositoryId", "hog");
verify(timerBuilder).tag("namespace", "none");
verify(timer, only()).record(any(Supplier.class));
}
@Test
void shouldMeasureDirectCallForNamespaceStore() {
when(storeParameters.getNamespace())
.thenReturn("intergalactic");
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"data",
storeParameters,
dataStore,
meterRegistry,
() -> timerBuilder
);
DataStore<User> store = (DataStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{DataStore.class}, handler);
User result = store
.get("42");
assertThat(result)
.extracting(User::getName)
.isEqualTo("dent");
verify(timerBuilder).description("Time taken for store operation in data");
verify(timerBuilder).tag("method", "get");
verify(timerBuilder).tag("namespace", "intergalactic");
verify(timerBuilder).tag("repositoryId", "none");
verify(timer, only()).record(any(Supplier.class));
}
}
@Nested
class ForQueryableStore {
@Mock
private QueryableStore<User> queryableStore;
@Mock
private QueryableStore.Query<User, User, ?> query;
@BeforeEach
void setUpStore() {
when(queryableStore.query())
.thenAnswer(i -> query);
when(query.findAll())
.thenReturn(List.of(new User("dent")));
}
@Test
void shouldMeasureDirectCall() {
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"queryable",
User.class,
new String[]{"intergalactic", "hog"},
queryableStore,
meterRegistry,
() -> timerBuilder
);
QueryableStore<User> store = (QueryableStore<User>) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
List<User> result = store
.query()
.findAll();
assertThat(result)
.extracting(User::getName)
.containsExactly("dent");
verify(timerBuilder).description("Time taken for store operation in queryable");
verify(timerBuilder).tag("method", "findAll");
verify(timerBuilder).tag("storeClass", "sonia.scm.user.User");
verify(timerBuilder).tag("parentIds", "intergalactic,hog");
verify(timer, only()).record(any(Supplier.class));
}
@Test
void shouldMeasureCallAfterOrder() {
when(query.orderBy(any(), any(QueryableStore.Order.class)))
.thenAnswer(i -> query);
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"queryable",
User.class,
new String[]{"intergalactic", "hog"},
queryableStore,
meterRegistry,
() -> timerBuilder
);
QueryableStore store = (QueryableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
List<User> result = store
.query()
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
.findAll();
assertThat(result)
.extracting(User::getName)
.containsExactly("dent");
verify(timerBuilder).description("Time taken for store operation in queryable");
verify(timerBuilder).tag("method", "findAll");
verify(timer, only()).record(any(Supplier.class));
}
@Test
void shouldMeasureCallAfterMultipleIndirection() {
when(query.orderBy(any(), any(QueryableStore.Order.class)))
.thenAnswer(i -> query);
when(query.distinct())
.thenAnswer(i -> query);
when(query.project(any()))
.thenAnswer(i -> query);
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"queryable",
User.class,
new String[]{"intergalactic", "hog"},
queryableStore,
meterRegistry,
() -> timerBuilder
);
QueryableStore store = (QueryableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableStore.class}, handler);
List<User> result = store
.query()
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
.distinct()
.project(new QueryableStore.IdQueryField())
.findAll();
assertThat(result)
.extracting(User::getName)
.containsExactly("dent");
verify(timerBuilder).description("Time taken for store operation in queryable");
verify(timerBuilder).tag("method", "findAll");
verify(timer, only()).record(any(Supplier.class));
}
}
@Nested
class ForQueryableMutableStore {
@Mock
private QueryableMutableStore<User> queryableMutableStore;
@Mock
private QueryableMutableStore.MutableQuery<User, ?> query;
@BeforeEach
void setUpStore() {
when(queryableMutableStore.query())
.thenAnswer(i -> query);
}
@Test
void shouldMeasureFinalCall() {
when(query.orderBy(any(), any(QueryableStore.Order.class)))
.thenAnswer(i -> query);
StoreInvocationMicrometerWrapper handler =
new StoreInvocationMicrometerWrapper(
"queryable",
User.class,
new String[]{"intergalactic", "hog"},
queryableMutableStore,
meterRegistry,
() -> timerBuilder
);
QueryableMutableStore<User> store = (QueryableMutableStore) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{QueryableMutableStore.class}, handler);
store
.query()
.orderBy(new QueryableStore.IdQueryField(), QueryableStore.Order.DESC)
.retain(100);
verify(timerBuilder).description("Time taken for store operation in queryable");
verify(timerBuilder).tag("method", "retain");
verify(timer, only()).record(any(Supplier.class));
}
}
}

View File

@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import sonia.scm.repository.Repository;
import sonia.scm.store.QueryableMaintenanceStore;
import sonia.scm.store.QueryableMutableStore;
import sonia.scm.user.User;
import java.nio.file.Path;
@@ -56,7 +57,7 @@ class SQLiteParallelizationTest {
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
List<Future<?>> futures = new ArrayList<>();
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
for (int i = 0; i < numThreads; i++) {
final String userId = "user-" + i;

View File

@@ -88,7 +88,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldPutObjectWithAutoIncrementId() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
store.put(new Spaceship("42"));
store.put(new Spaceship("23"));
@@ -101,7 +101,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldPutObjectWithGivenIdsThoughAutoIncrementActivated() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString, IdGenerator.AUTO_INCREMENT).forClassWithIds(Spaceship.class);
store.put("42", new Spaceship("42", SQLiteQueryableStoreTest.Range.INTER_GALACTIC));
store.put("23", new Spaceship("23", SQLiteQueryableStoreTest.Range.SOLAR_SYSTEM));
@@ -148,7 +148,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldRollback() throws SQLException {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.transactional(() -> {
store.put("tricia", new User("trillian"));
@@ -163,7 +163,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldDisableAutoCommit() throws SQLException {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.transactional(() -> {
store.put("tricia", new User("trillian"));
@@ -192,7 +192,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldGetObjectWithoutParent() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian"));
User tricia = store.get("tricia");
@@ -205,7 +205,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldReturnForNotExistingValue() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User earth = store.get("earth");
assertThat(earth)
@@ -215,7 +215,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldGetObjectWithSingleParent() {
new StoreTestBuilder(connectionString, "sonia.Group").withIds("1337").put("tricia", new User("McMillan"));
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("42");
store.put("tricia", new User("trillian"));
User tricia = store.get("tricia");
@@ -229,7 +229,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldGetObjectWithMultipleParents() {
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
store.put("tricia", new User("trillian"));
User tricia = store.get("tricia");
@@ -243,7 +243,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldGetAllForSingleEntry() {
new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337").put("tricia", new User("McMillan"));
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
store.put("tricia", new User("trillian"));
Map<String, User> users = store.getAll();
@@ -257,7 +257,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldGetAllForMultipleEntries() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
store.put("dent", new User("arthur"));
store.put("tricia", new User("trillian"));
@@ -280,7 +280,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldUseIdFromItemOnPut() {
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
String id = store.put(new SpaceshipWithId("Heart of Gold", 42));
SpaceshipWithId spaceship = store.get("Heart of Gold");
@@ -291,7 +291,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldSetNewIdInItemOnPut() {
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
String id = store.put(new SpaceshipWithId());
SpaceshipWithId spaceship = store.get(id);
@@ -302,7 +302,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldStoreWithNewIdAfterManualChange() {
SQLiteQueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
QueryableMutableStore<SpaceshipWithId> store = new StoreTestBuilder(connectionString).forClassWithIds(SpaceshipWithId.class);
store.put(new SpaceshipWithId("Heart of Gold", 42));
SpaceshipWithId spaceship = store.get("Heart of Gold");
@@ -321,9 +321,9 @@ class SQLiteQueryableMutableStoreTest {
class Clear {
@Test
void shouldClear() {
SQLiteQueryableMutableStore<User> uneffectedStore = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337");
QueryableMutableStore<User> uneffectedStore = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "1337");
uneffectedStore.put("tricia", new User("McMillan"));
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
store.put("tricia", new User("trillian"));
store.clear();
@@ -337,7 +337,7 @@ class SQLiteQueryableMutableStoreTest {
class Remove {
@Test
void shouldRemove() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Company", "sonia.Group").withIds("cloudogu", "42");
store.put("dent", new User("arthur"));
store.put("tricia", new User("trillian"));
@@ -351,7 +351,7 @@ class SQLiteQueryableMutableStoreTest {
class DeleteAll {
@Test
void shouldDeleteAllInStoreWithoutSubsequentQuery() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -365,7 +365,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldOnlyDeleteElementsMatchingTheQuery() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -383,9 +383,9 @@ class SQLiteQueryableMutableStoreTest {
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
try (
SQLiteQueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
QueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
QueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
QueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
) {
Spaceship spaceshipOne = new Spaceship("1");
Spaceship spaceshipTwo = new Spaceship("2");
@@ -408,7 +408,7 @@ class SQLiteQueryableMutableStoreTest {
class Retain {
@Test
void shouldRetainOneWithAscendingOrder() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -423,7 +423,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldThrowIllegalArgumentExceptionIfKeptElementsIsNegative() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -436,7 +436,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldRetainOneWithDescendingOrder() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -451,7 +451,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldDeleteUnselectedEntitiesAndRetainKeptElementsFromTheSelectedOnes() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
Spaceship spaceshipOne = new Spaceship("LazyShip");
Spaceship spaceshipTwo = new Spaceship("Biblical Ship");
@@ -477,7 +477,7 @@ class SQLiteQueryableMutableStoreTest {
@Test
void shouldRetainEverythingIfKeptElementsHigherThanContentQuantity() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put("1", new Spaceship("1"));
store.put("2", new Spaceship("2"));
store.put("3", new Spaceship("3"));
@@ -494,9 +494,9 @@ class SQLiteQueryableMutableStoreTest {
StoreTestBuilder spaceshipStoreBuilder = new StoreTestBuilder(connectionString);
StoreTestBuilder crewmateStoreBuilder = new StoreTestBuilder(connectionString, "Spaceship");
try (
SQLiteQueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
SQLiteQueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
QueryableMutableStore<Spaceship> spaceshipStore = spaceshipStoreBuilder.forClassWithIds(Spaceship.class);
QueryableMutableStore<Crewmate> crewmateStoreForShipOne = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "1");
QueryableMutableStore<Crewmate> crewmateStoreForShipTwo = crewmateStoreBuilder.forClassWithIds(Crewmate.class, "2")
) {
Spaceship spaceshipOne = new Spaceship("1");
Spaceship spaceshipTwo = new Spaceship("2");
@@ -567,7 +567,7 @@ class SQLiteQueryableMutableStoreTest {
Repository.class.getName() + ".class"
).readOnly("42");
SQLiteQueryableMutableStore<User> store = storeTestBuilder.withIds("23");
QueryableMutableStore<User> store = storeTestBuilder.withIds("23");
store.put("tricia", new User("trillian"));
assertThat(store.get("tricia")).isNotNull();
@@ -580,7 +580,7 @@ class SQLiteQueryableMutableStoreTest {
Group.class.getName() + ".class"
).readOnly("42");
SQLiteQueryableMutableStore<User> store = storeTestBuilder.withIds("42");
QueryableMutableStore<User> store = storeTestBuilder.withIds("42");
store.put("tricia", new User("trillian"));
assertThat(store.get("tricia")).isNotNull();

View File

@@ -30,6 +30,7 @@ import sonia.scm.store.Operator;
import sonia.scm.store.QueryableMaintenanceStore;
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceIterator;
import sonia.scm.store.QueryableMaintenanceStore.MaintenanceStoreEntry;
import sonia.scm.store.QueryableMutableStore;
import sonia.scm.store.QueryableStore;
import sonia.scm.user.User;
@@ -71,7 +72,7 @@ class SQLiteQueryableStoreTest {
@ParameterizedTest
@ValueSource(strings = {"*Of*", "Heart*Gold", "H*", "*d", "*Heart Of Gold*", "Heart Of Gold", "Heart Of *Gold"})
void shouldWorkWithLikes(String searchString) {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
@@ -87,7 +88,7 @@ class SQLiteQueryableStoreTest {
@ParameterizedTest
@ValueSource(strings = {"Of", "*of*", "heart of gold"})
void shouldNotFindNotMatchingValuesWithLike() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
@@ -100,7 +101,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldWorkWithEnums() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Space Shuttle", Range.SOLAR_SYSTEM));
store.put(new Spaceship("Heart Of Gold", Range.INTER_GALACTIC));
@@ -114,7 +115,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldWorkWithLongs() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
trillian.setCreationDate(10000000000L);
store.put(trillian);
@@ -134,7 +135,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldWorkWithIntegers() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
trillian.setCreationDate(42L);
store.put(trillian);
@@ -154,7 +155,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldWorkWithNumberCollection() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
trillian.setActive(true);
store.put(trillian);
@@ -174,7 +175,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldCountAndWorkWithNumberCollection() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User trillian = new User("trillian", "McMillan", "tricia@hog.org");
trillian.setActive(true);
store.put(trillian);
@@ -197,7 +198,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleCollections() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
@@ -210,7 +211,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldCountAndHandleCollections() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
@@ -223,7 +224,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldCountWithoutConditions() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
store.put(new Spaceship("Heart Of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
@@ -234,7 +235,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleEmptyCollectionWithMaxString() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
Integer result = store.query().max(
SPACESHIP_FLIGHT_COUNT
);
@@ -245,7 +246,7 @@ class SQLiteQueryableStoreTest {
@Nested
class ForAggregations {
SQLiteQueryableMutableStore<Spaceship> store;
QueryableMutableStore<Spaceship> store;
@BeforeEach
void createData() {
@@ -318,7 +319,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleCollectionSize() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", "Buzz", "Anndre"));
store.put(new Spaceship("Heart of Gold", "Trillian", "Arthur", "Ford", "Zaphod", "Marvin"));
store.put(new Spaceship("MillenniumFalcon"));
@@ -345,7 +346,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleMap() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
@@ -365,7 +366,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldCountAndHandleMap() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true)));
store.put(new Spaceship("MillenniumFalcon", Map.of("dagobah", false)));
@@ -386,7 +387,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleMapSize() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
store.put(new Spaceship("Spaceshuttle", Map.of("moon", true, "earth", true)));
store.put(new Spaceship("Heart of Gold", Map.of("vogon", true, "earth", true, "dagobah", true)));
store.put(new Spaceship("MillenniumFalcon", Map.of()));
@@ -413,7 +414,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldRetrieveTime() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
Spaceship spaceshuttle = new Spaceship("Spaceshuttle", Range.SOLAR_SYSTEM);
spaceshuttle.setInServiceSince(Instant.parse("1981-04-12T10:00:00Z"));
store.put(spaceshuttle);
@@ -445,7 +446,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldLimitQuery() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
store.put(new User("arthur", "Dent", "arthur@hog.org"));
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
@@ -461,7 +462,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldOrderResults() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
store.put(new User("arthur", "Dent", "arthur@hog.org"));
store.put(new User("zaphod", "Beeblebrox Head 1", "zaphod1@hog.org"));
@@ -480,7 +481,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldOrderResultsAsNumbers() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("1"));
store.put(new User("2"));
store.put(new User("10"));
@@ -498,7 +499,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldOrderResultsAsStrings() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("1"));
store.put(new User("2"));
store.put(new User("10"));
@@ -519,7 +520,7 @@ class SQLiteQueryableStoreTest {
class QueryLogicalHandling {
@Test
void shouldQueryForId() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -536,7 +537,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldQueryForIdAndOrderByDESC() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("3", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -551,7 +552,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldOrderIdsAndPayload() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("1", new User("trish", "Tricia", "tricia@hog.org"));
store.put("2", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("3", new User("trillian", "Arthur Dent", "arthur@hog.org"));
@@ -576,7 +577,7 @@ class SQLiteQueryableStoreTest {
.withIds("1337")
.put("tricia", new User("trillian", "Trillian McMillan", "tricia@hog.org"));
SQLiteQueryableStore<User> store = new StoreTestBuilder(connectionString, Group.class.getName()).withIds();
QueryableStore<User> store = new StoreTestBuilder(connectionString, Group.class.getName()).withIds();
List<User> all = store.query(
GROUP.eq("42")
@@ -590,7 +591,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleContainsCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -605,7 +606,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleIsNullCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -621,7 +622,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleNotNullCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian", null, "tricia@hog.org"));
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -637,7 +638,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleOr() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -658,7 +659,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleOrWithMultipleStores() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
@@ -666,7 +667,7 @@ class SQLiteQueryableStoreTest {
store.put("McMillan", mcmillan);
store.put("dent", dent);
SQLiteQueryableMutableStore<User> parallelStore = new StoreTestBuilder(connectionString, "sonia.Group").withIds("LameGroup");
QueryableMutableStore<User> parallelStore = new StoreTestBuilder(connectionString, "sonia.Group").withIds("LameGroup");
parallelStore.put("tricia", new User("trillian", "Trillian IAMINAPARALLELSTORE McMillan", "mcmillan@gmail.com"));
List<User> result = store.query(
@@ -680,7 +681,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleGroup() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
.withIds("42");
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
new StoreTestBuilder(connectionString, "sonia.Group")
@@ -696,7 +697,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleGroupWithCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
.withIds("42");
store
.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
@@ -713,7 +714,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldHandleInArrayCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("trillian", "McMillan", "tricia@hog.org"));
store.put(new User("arthur", "Dent", "arthur@hog.org"));
store.put(new User("zaphod", "Beeblebrox", "zaphod@hog.org"));
@@ -731,7 +732,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindAllObjectsWithoutParentWithoutConditions() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian"));
List<User> all = store.query().findAll();
@@ -741,7 +742,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindAllObjectsWithoutParentWithCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian"));
store.put("dent", new User("arthur"));
@@ -751,7 +752,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindAllObjectsWithOneParentAndMultipleConditions() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group").withIds("CoolGroup");
User tricia = new User("trillian", "Tricia", "tricia@hog.org");
User mcmillan = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
User dent = new User("arthur", "Arthur Dent", "arthur@hog.org");
@@ -770,7 +771,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindAllObjectsWithoutParentWithMultipleConditions() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
store.put("McMillan", new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put("dent", new User("arthur", "Arthur Dent", "arthur@hog.org"));
@@ -786,7 +787,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReturnIds() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, Spaceship.class.getName())
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, Spaceship.class.getName())
.withIds("hog");
store.put("tricia", new User("trillian", "Tricia", "tricia@hog.org"));
@@ -807,13 +808,13 @@ class SQLiteQueryableStoreTest {
class FindOne {
@Test
void shouldReturnEmptyOptionalIfNoResultFound() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
assertThat(store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne()).isEmpty();
}
@Test
void shouldReturnOneResultIfOneIsGiven() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
store.put(expectedShip);
Spaceship ship = store.query(SPACESHIP_NAME.eq("Heart Of Gold")).findOne().get();
@@ -823,7 +824,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldThrowErrorIfMoreThanOneResultIsSaved() {
SQLiteQueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
QueryableMutableStore<Spaceship> store = new StoreTestBuilder(connectionString).forClassWithIds(Spaceship.class);
Spaceship expectedShip = new Spaceship("Heart Of Gold", Range.INNER_GALACTIC);
Spaceship localShip = new Spaceship("Heart Of Gold", Range.SOLAR_SYSTEM);
store.put(expectedShip);
@@ -837,7 +838,7 @@ class SQLiteQueryableStoreTest {
class FindFirst {
@Test
void shouldFindFirst() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User expectedUser = new User("trillian", "Tricia", "tricia@hog.org");
store.put("1", expectedUser);
@@ -854,7 +855,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindFirstWithMatchingCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan-alternate@gmail.com");
store.put("1", new User("trillian", "Tricia", "tricia@hog.org"));
@@ -874,7 +875,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldFindFirstWithMatchingLogicalCondition() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User expectedUser = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
store.put("1", new User("trillian-old", "Tricia", "tricia@hog.org"));
@@ -900,7 +901,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReturnEmptyOptionalIfNoResultFound() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
Optional<User> user = store.query(
USER_NAME.eq("dave")
)
@@ -933,7 +934,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReturnDistinctValuesFromObject() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
.withIds();
List<Object[]> result = store.query().project(USER_NAME).distinct().findAll();
@@ -949,7 +950,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReturnDistinctParentIds() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
.withIds();
List<Object[]> result = store.query().project(GROUP).distinct().findAll();
@@ -963,7 +964,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReturnDistinctCount() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString, "sonia.Group")
.withIds();
long count = store.query().project(GROUP).distinct().count();
@@ -976,11 +977,12 @@ class SQLiteQueryableStoreTest {
class ForMaintenance {
@Test
void shouldUpdateRawJson() throws Exception {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
store.put("1", user);
try (MaintenanceIterator<User> iterator = store.iterateAll()) {
QueryableMaintenanceStore<User> maintenanceStore = new StoreTestBuilder(connectionString).forMaintenanceWithSubIds();
try (MaintenanceIterator<User> iterator = maintenanceStore.iterateAll()) {
assertThat(iterator.hasNext()).isTrue();
MaintenanceStoreEntry<User> entry = iterator.next();
assertThat(entry.getId()).isEqualTo("1");
@@ -997,7 +999,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldUpdateRawJsonForItemWithParent() throws Exception {
SQLiteQueryableMutableStore<User> subStore = new StoreTestBuilder(connectionString, Group.class.getName()).withIds("hitchhiker");
QueryableMutableStore<User> subStore = new StoreTestBuilder(connectionString, Group.class.getName()).withIds("hitchhiker");
User user = new User("trillian", "Trillian McMillan", "mcmillan@gmail.com");
subStore.put("1", user);
@@ -1019,11 +1021,12 @@ class SQLiteQueryableStoreTest {
@Test
void shouldRemoveFromIteratorWithoutParent() {
SQLiteQueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
QueryableMutableStore<User> store = new StoreTestBuilder(connectionString).withIds();
store.put(new User("trillian", "Trillian McMillan", "mcmillan@gmail.com"));
store.put(new User("dent", "Arthur Dent", "dent@gmail.com"));
for (MaintenanceIterator<User> iter = store.iterateAll(); iter.hasNext(); ) {
QueryableMaintenanceStore<User> maintenanceStore = new StoreTestBuilder(connectionString).forMaintenanceWithSubIds();
for (MaintenanceIterator<User> iter = maintenanceStore.iterateAll(); iter.hasNext(); ) {
MaintenanceStoreEntry<User> next = iter.next();
if (next.get().getName().equals("dent")) {
iter.remove();
@@ -1039,11 +1042,11 @@ class SQLiteQueryableStoreTest {
@Test
void shouldRemoveFromIteratorWithParents() {
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42", "hog");
QueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42", "hog");
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
SQLiteQueryableMutableStore<User> earthStore = testStoreBuilder.withIds("42", "earth");
QueryableMutableStore<User> earthStore = testStoreBuilder.withIds("42", "earth");
earthStore.put("dent", new User("dent", "Arthur Dent", "dent@gmail.com"));
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
@@ -1068,7 +1071,7 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReadAll() {
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName());
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
QueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
hogStore.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
hogStore.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
@@ -1091,9 +1094,9 @@ class SQLiteQueryableStoreTest {
@Test
void shouldReadAllWithMultipleIds() {
StoreTestBuilder testStoreBuilder = new StoreTestBuilder(connectionString, Repository.class.getName(), Group.class.getName());
SQLiteQueryableMutableStore<User> store1 = testStoreBuilder.withIds("42", "astronauts");
QueryableMutableStore<User> store1 = testStoreBuilder.withIds("42", "astronauts");
store1.put("trisha", new User("trillian", "Trillian McMillan", "mcmillan@hog.com"));
SQLiteQueryableMutableStore<User> store2 = testStoreBuilder.withIds("42", "earthlings");
QueryableMutableStore<User> store2 = testStoreBuilder.withIds("42", "earthlings");
store2.put("dent", new User("dent", "Arthur Dent", "dent@hog.com"));
QueryableMaintenanceStore<User> store = testStoreBuilder.forMaintenanceWithSubIds("42");
@@ -1128,7 +1131,7 @@ class SQLiteQueryableStoreTest {
)
);
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
QueryableMaintenanceStore<User> hogStore = testStoreBuilder.forMaintenanceWithSubIds("42");
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
assertThat(allValues)
.extracting("value")
@@ -1147,7 +1150,7 @@ class SQLiteQueryableStoreTest {
)
);
SQLiteQueryableMutableStore<User> hogStore = testStoreBuilder.withIds("42");
QueryableMaintenanceStore<User> hogStore = testStoreBuilder.forMaintenanceWithSubIds("42");
Collection<QueryableMaintenanceStore.Row<User>> allValues = hogStore.readAll();
assertThat(allValues)
.extracting("value")

View File

@@ -24,6 +24,7 @@ import sonia.scm.repository.RepositoryReadOnlyChecker;
import sonia.scm.security.UUIDKeyGenerator;
import sonia.scm.store.IdGenerator;
import sonia.scm.store.QueryableMaintenanceStore;
import sonia.scm.store.QueryableMutableStore;
import sonia.scm.store.QueryableStore;
import sonia.scm.user.User;
@@ -68,7 +69,7 @@ class StoreTestBuilder {
this.parentClasses = parentClasses;
}
SQLiteQueryableMutableStore<User> withIds(String... ids) {
QueryableMutableStore<User> withIds(String... ids) {
return forClassWithIds(User.class, ids);
}
@@ -86,7 +87,7 @@ class StoreTestBuilder {
return createStoreFactory(User.class).getForMaintenance(User.class, ids);
}
<T> SQLiteQueryableMutableStore<T> forClassWithIds(Class<T> clazz, String... ids) {
<T> QueryableMutableStore<T> forClassWithIds(Class<T> clazz, String... ids) {
return createStoreFactory(clazz).getMutable(clazz, ids);
}