From ca3791bd4adefeddd4038f94cb8b4d86195b9f90 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Tue, 22 May 2018 19:01:28 +0300 Subject: [PATCH 01/53] Add Error Prone compiler --- build.gradle | 23 +++++++++++++++++++++++ ext.gradle | 9 +++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 73a08e402c2..8a3006fcc12 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,12 @@ buildscript { maven { url = sonatypeSnapshots } jcenter() + maven { url = googleMavenCentralMirror } + // Repository for error-prone plugin. + maven { url = gradlePlugins } + mavenCentral() mavenLocal() @@ -50,6 +54,9 @@ buildscript { name: 'guava', version: guavaVersion, changing: true + classpath ("net.ltgt.gradle:gradle-errorprone-plugin:$errorPronePluginVersion") { + exclude group: 'com.google.guava' + } classpath("com.google.protobuf:protobuf-gradle-plugin:$protobufGradlePluginVersion") { // exclude an old Guava version exclude group: 'com.google.guava' @@ -65,6 +72,14 @@ buildscript { exclude group: 'com.google.guava' } } + + configurations.all({ + resolutionStrategy { + cacheChangingModulesFor(0, 'seconds') + force "com.google.guava:guava:$guavaVersion" + force "com.google.guava:guava-testlib:$guavaVersion" + } + }) } apply from: 'ext.gradle' @@ -143,6 +158,7 @@ subprojects { apply plugin: 'com.google.protobuf' apply plugin: 'java' + apply plugin: 'net.ltgt.errorprone' // Specific setup for a Travis build, // which prevents appearing of warning messages in build logs. @@ -290,6 +306,13 @@ subprojects { source = sourceSets.main.allJava } + tasks.withType(JavaCompile) { + // Exclude generated sources from being analyzed by Error Prone. + options.compilerArgs += [ + '-XepExcludedPaths:.*/generated/.*' + ] + } + task sourceJar(type: Jar) { from sourceSets.main.allJava classifier "sources" diff --git a/ext.gradle b/ext.gradle index fcb5b31cad3..c7024a2e49d 100644 --- a/ext.gradle +++ b/ext.gradle @@ -34,6 +34,7 @@ ext { spineRepository = 'http://maven.teamdev.com/repository/spine' spineSnapshotsRepository = 'http://maven.teamdev.com/repository/spine-snapshots' sonatypeSnapshots = 'https://oss.sonatype.org/content/repositories/snapshots' + gradlePlugins = 'https://plugins.gradle.org/m2/' // The version of the modules in this project. spineVersion = SPINE_VERSION @@ -52,11 +53,15 @@ ext { // `KnownTypes.addStandardProtobufTypes()` method is updated with new Message types that may be // introduced in the new version of Protobuf. protobufVersion = '3.5.1' - - gRpcVersion = '1.9.0' + + gRpcVersion = '1.10.0' slf4JVersion = '1.7.25' jUnitVersion = '5.1.1' + checkerFrameworkVersion = '2.5.1' + errorProneVersion = '2.3.1' + errorPronePluginVersion = '0.0.14' + // Note that this Mockito version is not the latest one. // When migrating to the further versions, side effects may happen, like mocks persisting // throughout a test suite. We leave this version as is ('2.7.22') for now. From a31f735d3ab6e65dbbf5e532513db3a5c5843f7b Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 23 May 2018 01:11:01 +0300 Subject: [PATCH 02/53] Change `Nullable`, address some ret. vals --- build.gradle | 14 ++++- ext.gradle | 2 +- .../java/io/spine/server/BoundedContext.java | 4 +- .../io/spine/server/ServerEnvironment.java | 3 +- .../io/spine/server/aggregate/Aggregate.java | 3 - .../server/aggregate/AggregatePartClass.java | 2 +- .../server/aggregate/AggregateRepository.java | 14 ++--- .../server/aggregate/AggregateStorage.java | 3 +- .../spine/server/aggregate/package-info.java | 3 + .../main/java/io/spine/server/bus/Bus.java | 2 +- .../spine/server/commandbus/CommandBus.java | 34 ++++++----- .../server/commandbus/CommandScheduler.java | 10 +--- .../spine/server/commandbus/package-info.java | 3 + .../io/spine/server/commandstore/CEntity.java | 37 +++++++----- .../server/commandstore/CRepository.java | 2 +- .../server/commandstore/CommandStore.java | 2 +- .../io/spine/server/commandstore/Records.java | 2 +- .../server/delivery/InProcessSharding.java | 2 +- .../spine/server/delivery/ShardedStream.java | 2 +- .../spine/server/entity/AbstractEntity.java | 14 ++--- .../entity/AbstractVersionableEntity.java | 2 - .../entity/DefaultEntityStorageConverter.java | 3 +- .../io/spine/server/entity/EntityClass.java | 2 +- .../server/entity/EntityStateEnvelope.java | 3 +- .../server/entity/EntityStorageConverter.java | 2 +- .../server/entity/EntityWithLifecycle.java | 3 +- .../server/entity/EventPlayingEntity.java | 6 +- .../io/spine/server/entity/FieldMasks.java | 2 +- .../server/entity/RecordBasedRepository.java | 56 ++++++++----------- .../io/spine/server/entity/Repository.java | 22 +++----- .../spine/server/entity/RepositoryView.java | 3 - .../io/spine/server/entity/Transaction.java | 5 +- .../spine/server/entity/VisibilityGuard.java | 2 +- .../io/spine/server/entity/package-info.java | 3 + .../storage/CompositeQueryParameter.java | 2 +- .../server/entity/storage/EntityColumn.java | 2 +- .../java/io/spine/server/event/EEntity.java | 2 +- .../io/spine/server/event/ERepository.java | 2 +- .../java/io/spine/server/event/EventBus.java | 2 +- .../io/spine/server/event/EventFactory.java | 3 +- .../io/spine/server/event/EventStore.java | 2 +- .../io/spine/server/event/MatchFilter.java | 2 +- .../server/event/MatchesStreamQuery.java | 2 +- .../server/integration/IntegrationBus.java | 2 +- .../server/model/DefaultStateRegistry.java | 3 - .../io/spine/server/model/HandlerMethod.java | 2 +- .../io/spine/server/model/HandlerMethods.java | 3 +- .../spine/server/model/MethodPredicate.java | 2 +- .../io/spine/server/model/package-info.java | 2 + .../outbus/enrich/EnrichmentFunction.java | 2 +- .../server/outbus/enrich/EnrichmentsMap.java | 2 +- .../outbus/enrich/MessageEnrichment.java | 2 +- .../server/outbus/enrich/SameTransition.java | 3 +- .../enrich/SupportsFieldConversion.java | 3 +- .../java/io/spine/server/package-info.java | 3 + .../procman/ProcessManagerRepository.java | 4 +- .../io/spine/server/procman/package-info.java | 3 + .../projection/ProjectionRepository.java | 2 +- .../server/projection/ProjectionStorage.java | 2 +- .../spine/server/rejection/RejectionBus.java | 2 +- .../server/stand/AggregateQueryProcessor.java | 2 +- .../spine/server/stand/AggregateStateId.java | 3 - .../server/stand/InMemoryTypeRegistry.java | 3 - .../MultitenantSubscriptionRegistry.java | 2 +- .../spine/server/stand/RequestValidator.java | 2 +- .../java/io/spine/server/stand/Stand.java | 14 ++--- .../server/stand/SubscriptionRecord.java | 12 ++-- .../server/stand/SubscriptionValidator.java | 3 +- .../io/spine/server/stand/package-info.java | 2 + .../storage/BulkStorageOperationsMixin.java | 3 - .../server/storage/OperatorEvaluator.java | 2 +- .../spine/server/storage/RecordStorage.java | 1 + .../server/storage/StorageFactorySwitch.java | 3 +- .../storage/memory/EntityQueryMatcher.java | 2 +- .../storage/memory/EntityRecordUnpacker.java | 3 +- .../memory/InMemoryProjectionStorage.java | 2 +- .../storage/memory/InMemoryStandStorage.java | 2 +- .../storage/memory/MultitenantStorage.java | 2 +- .../memory/TenantAggregateRecords.java | 2 +- .../server/storage/memory/TenantRecords.java | 2 +- .../io/spine/server/storage/package-info.java | 2 + .../server/tenant/TenantAwareFunction0.java | 8 +-- .../spine/server/tenant/TenantFunction.java | 3 +- .../spine/server/transport/GrpcContainer.java | 2 +- .../memory/InMemoryTransportFactory.java | 3 +- .../main/java/io/spine/server/tuple/Pair.java | 3 +- .../java/io/spine/server/tuple/Quartet.java | 3 +- .../java/io/spine/server/tuple/Quintet.java | 3 +- .../java/io/spine/server/tuple/Triplet.java | 3 +- .../java/io/spine/server/tuple/Tuple.java | 2 +- .../io/spine/server/entity/EntityBuilder.java | 4 +- .../io/spine/server/entity/given/Given.java | 2 +- .../entity/given/GivenLifecycleFlags.java | 6 +- 93 files changed, 209 insertions(+), 235 deletions(-) diff --git a/build.gradle b/build.gradle index 8a3006fcc12..3f8b5c3f15c 100644 --- a/build.gradle +++ b/build.gradle @@ -200,8 +200,14 @@ subprojects { name: 'guava', version: guavaVersion, changing: true + + //TODO:2018-05-11:alexander.yevsyukov: Replace the below with Checker Framework + // after Guava fully migrates from it too. compile "com.google.code.findbugs:jsr305:3.0.0" + compile "org.checkerframework:checker-qual:$checkerFrameworkVersion" + compile "com.google.errorprone:error_prone_annotations:$errorProneVersion" + //As a Library, we provide logging facade API, not specific logger bindings. //Target apps are free to use any binding they need. compile "org.slf4j:slf4j-api:$slf4JVersion" @@ -229,12 +235,16 @@ subprojects { sourceSets { main { proto.srcDirs = ["$sourcesRootDir/main/proto"] - java.srcDirs = [generatedJavaDir, "$sourcesRootDir/main/java", generatedSpineDir] + java.srcDirs = [generatedJavaDir, + "$sourcesRootDir/main/java", + generatedSpineDir] resources.srcDirs = ["$generatedRootDir/main/resources"] } test { proto.srcDirs = ["$sourcesRootDir/test/proto"] - java.srcDirs = [generatedTestJavaDir, "$sourcesRootDir/test/java", generatedTestSpineDir] + java.srcDirs = [generatedTestJavaDir, + "$sourcesRootDir/test/java", + generatedTestSpineDir] resources.srcDirs = ["$generatedRootDir/test/resources"] } } diff --git a/ext.gradle b/ext.gradle index c7024a2e49d..73df8cb0de4 100644 --- a/ext.gradle +++ b/ext.gradle @@ -40,7 +40,7 @@ ext { spineVersion = SPINE_VERSION // Depend on `base` for the general definitions and a model compiler. - spineBaseVersion = '0.10.37-SNAPSHOT' + spineBaseVersion = '0.10.38-SNAPSHOT' spineTimeVersion = '0.10.29-SNAPSHOT' diff --git a/server/src/main/java/io/spine/server/BoundedContext.java b/server/src/main/java/io/spine/server/BoundedContext.java index 18dae09d6bf..6e14f3eb375 100644 --- a/server/src/main/java/io/spine/server/BoundedContext.java +++ b/server/src/main/java/io/spine/server/BoundedContext.java @@ -50,11 +50,10 @@ import io.spine.server.transport.TransportFactory; import io.spine.server.transport.memory.InMemoryTransportFactory; import io.spine.type.TypeName; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; @@ -232,7 +231,6 @@ public StorageFactory getStorageFactory() { /** * @return {@code true} if the bounded context serves many organizations */ - @CheckReturnValue public boolean isMultitenant() { return multitenant; } diff --git a/server/src/main/java/io/spine/server/ServerEnvironment.java b/server/src/main/java/io/spine/server/ServerEnvironment.java index edcb0963593..f061e90abe1 100644 --- a/server/src/main/java/io/spine/server/ServerEnvironment.java +++ b/server/src/main/java/io/spine/server/ServerEnvironment.java @@ -26,8 +26,7 @@ import io.spine.server.delivery.InProcessSharding; import io.spine.server.delivery.Sharding; import io.spine.server.transport.memory.InMemoryTransportFactory; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/aggregate/Aggregate.java b/server/src/main/java/io/spine/server/aggregate/Aggregate.java index 9828786ad05..a9d9e46bf69 100644 --- a/server/src/main/java/io/spine/server/aggregate/Aggregate.java +++ b/server/src/main/java/io/spine/server/aggregate/Aggregate.java @@ -46,7 +46,6 @@ import io.spine.server.rejection.RejectionReactorMethod; import io.spine.validate.ValidatingBuilder; -import javax.annotation.CheckReturnValue; import java.util.Iterator; import java.util.List; @@ -392,7 +391,6 @@ void restore(Snapshot snapshot) { * * @return immutable view of all uncommitted events */ - @CheckReturnValue List getUncommittedEvents() { return ImmutableList.copyOf(uncommittedEvents); } @@ -432,7 +430,6 @@ protected String getMissingTxMessage() { * * @return new snapshot */ - @CheckReturnValue Snapshot toShapshot() { final Any state = AnyPacker.pack(getState()); final Snapshot.Builder builder = Snapshot.newBuilder() diff --git a/server/src/main/java/io/spine/server/aggregate/AggregatePartClass.java b/server/src/main/java/io/spine/server/aggregate/AggregatePartClass.java index 0ee30d94334..64857d1fc97 100644 --- a/server/src/main/java/io/spine/server/aggregate/AggregatePartClass.java +++ b/server/src/main/java/io/spine/server/aggregate/AggregatePartClass.java @@ -23,8 +23,8 @@ import io.spine.annotation.Internal; import io.spine.server.BoundedContext; import io.spine.server.model.ModelError; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; diff --git a/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java b/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java index ae04189e867..21a2be41589 100644 --- a/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java +++ b/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java @@ -59,7 +59,6 @@ import io.spine.server.storage.Storage; import io.spine.server.storage.StorageFactory; -import javax.annotation.CheckReturnValue; import java.util.List; import java.util.Set; @@ -271,18 +270,20 @@ public AggregateClass getShardedModelClass() { * * @param aggregate an instance to store */ + @SuppressWarnings("CheckReturnValue") + // ignore result of `commitEvents()` because we obtain them in the block before the call. @Override protected void store(A aggregate) { - final I id = aggregate.getId(); - final int snapshotTrigger = getSnapshotTrigger(); - final AggregateStorage storage = aggregateStorage(); + I id = aggregate.getId(); + int snapshotTrigger = getSnapshotTrigger(); + AggregateStorage storage = aggregateStorage(); int eventCount = storage.readEventCountAfterLastSnapshot(id); - final Iterable uncommittedEvents = aggregate.getUncommittedEvents(); + Iterable uncommittedEvents = aggregate.getUncommittedEvents(); for (Event event : uncommittedEvents) { storage.writeEvent(id, event); ++eventCount; if (eventCount >= snapshotTrigger) { - final Snapshot snapshot = aggregate.toShapshot(); + Snapshot snapshot = aggregate.toShapshot(); aggregate.clearRecentHistory(); storage.writeSnapshot(id, snapshot); eventCount = 0; @@ -438,7 +439,6 @@ private void updateStand(TenantId tenantId, A aggregate) { * @return a positive integer value * @see #DEFAULT_SNAPSHOT_TRIGGER */ - @CheckReturnValue protected int getSnapshotTrigger() { return this.snapshotTrigger; } diff --git a/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java b/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java index 81e22aa9a93..53feb93afd0 100644 --- a/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java +++ b/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java @@ -59,13 +59,14 @@ protected AggregateStorage(boolean multitenant) { /** * Forms and returns an {@link AggregateStateRecord} based on the - * {@linkplain #historyBackward(AggregateReadRequest) aggregate history}. + * {@linkplain #historyBackward(AggregateReadRequest) aggregate histor@Vhey}. * * @param request the aggregate read request based on which to form a record * @return the record instance or {@code Optional.absent()} if the * {@linkplain #historyBackward(AggregateReadRequest) aggregate history} is empty * @throws IllegalStateException if the storage was closed before */ + @SuppressWarnings("CheckReturnValue") // calling builder method @Override public Optional read(AggregateReadRequest request) { checkNotClosed(); diff --git a/server/src/main/java/io/spine/server/aggregate/package-info.java b/server/src/main/java/io/spine/server/aggregate/package-info.java index f7cc4da2e2a..40c9cb0e522 100644 --- a/server/src/main/java/io/spine/server/aggregate/package-info.java +++ b/server/src/main/java/io/spine/server/aggregate/package-info.java @@ -18,7 +18,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.aggregate; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/bus/Bus.java b/server/src/main/java/io/spine/server/bus/Bus.java index e76917b3edf..31e5bf52056 100644 --- a/server/src/main/java/io/spine/server/bus/Bus.java +++ b/server/src/main/java/io/spine/server/bus/Bus.java @@ -28,8 +28,8 @@ import io.spine.core.MessageEnvelope; import io.spine.core.Rejection; import io.spine.type.MessageClass; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Deque; import java.util.concurrent.ConcurrentLinkedDeque; diff --git a/server/src/main/java/io/spine/server/commandbus/CommandBus.java b/server/src/main/java/io/spine/server/commandbus/CommandBus.java index 8f23e96e469..236e81e1300 100644 --- a/server/src/main/java/io/spine/server/commandbus/CommandBus.java +++ b/server/src/main/java/io/spine/server/commandbus/CommandBus.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.spine.annotation.Internal; import io.spine.base.Error; import io.spine.base.Identifier; @@ -38,8 +39,8 @@ import io.spine.server.bus.EnvelopeValidator; import io.spine.server.commandstore.CommandStore; import io.spine.server.rejection.RejectionBus; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Deque; import java.util.Set; @@ -103,8 +104,7 @@ public class CommandBus extends Bus getValidator() { /** * Passes a previously scheduled command to the corresponding dispatcher. */ + @SuppressWarnings("CheckReturnValue") + // can ignore ack. since we checked the command when scheduled void postPreviouslyScheduled(Command command) { - final CommandEnvelope commandEnvelope = CommandEnvelope.of(command); + CommandEnvelope commandEnvelope = CommandEnvelope.of(command); doPost(commandEnvelope); } @@ -273,9 +275,8 @@ protected void store(Iterable commands) { } private CommandDispatcher getDispatcher(CommandEnvelope commandEnvelope) { - final Optional> dispatcher = getDispatcher( - commandEnvelope.getMessageClass() - ); + Optional> dispatcher = + getDispatcher(commandEnvelope.getMessageClass()); if (!dispatcher.isPresent()) { throw noDispatcherFound(commandEnvelope); } @@ -326,8 +327,7 @@ public static class Builder extends AbstractBuilderIf set directly, the value would be matched to the multi-tenancy flag of * {@code BoundedContext}. */ - @Nullable - private Boolean multitenant; + private @Nullable Boolean multitenant; private CommandStore commandStore; @@ -359,12 +359,12 @@ private static boolean detectThreadsAllowed() { } @Internal - @Nullable - public Boolean isMultitenant() { + public @Nullable Boolean isMultitenant() { return multitenant; } @Internal + @CanIgnoreReturnValue public Builder setMultitenant(@Nullable Boolean multitenant) { this.multitenant = multitenant; return this; @@ -386,18 +386,21 @@ public Optional getRejectionBus() { return Optional.fromNullable(rejectionBus); } + @CanIgnoreReturnValue public Builder setCommandStore(CommandStore commandStore) { checkNotNull(commandStore); this.commandStore = commandStore; return this; } + @CanIgnoreReturnValue public Builder setCommandScheduler(CommandScheduler commandScheduler) { checkNotNull(commandScheduler); this.commandScheduler = commandScheduler; return this; } + @CanIgnoreReturnValue public Builder setRejectionBus(RejectionBus rejectionBus) { checkNotNull(rejectionBus); this.rejectionBus = rejectionBus; @@ -417,6 +420,7 @@ public Builder setRejectionBus(RejectionBus rejectionBus) { *

If not set explicitly, the default value of this flag is set upon the best guess, * based on current {@link io.spine.server.ServerEnvironment server environment}. */ + @CanIgnoreReturnValue public Builder setThreadSpawnAllowed(boolean threadSpawnAllowed) { this.threadSpawnAllowed = threadSpawnAllowed; return this; @@ -490,12 +494,12 @@ protected Builder self() { return this; } + @SuppressWarnings("CheckReturnValue") + /* Calling registry() enforces creating the registry to make spying for CommandBus-es + in tests work. */ private CommandBus createCommandBus() { - final CommandBus commandBus = new CommandBus(this); - - // Enforce creating the registry to make spying for CommandBus-es in tests work. + CommandBus commandBus = new CommandBus(this); commandBus.registry(); - return commandBus; } } diff --git a/server/src/main/java/io/spine/server/commandbus/CommandScheduler.java b/server/src/main/java/io/spine/server/commandbus/CommandScheduler.java index 419c9466d37..93a4e95e825 100644 --- a/server/src/main/java/io/spine/server/commandbus/CommandScheduler.java +++ b/server/src/main/java/io/spine/server/commandbus/CommandScheduler.java @@ -29,9 +29,8 @@ import io.spine.core.CommandEnvelope; import io.spine.core.CommandId; import io.spine.server.bus.BusFilter; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; import java.util.Set; import static com.google.common.base.Optional.absent; @@ -57,11 +56,9 @@ public abstract class CommandScheduler implements BusFilter { private boolean isActive = true; - @Nullable - private CommandBus commandBus; + private @Nullable CommandBus commandBus; - @Nullable - private Rescheduler rescheduler; + private @Nullable Rescheduler rescheduler; protected CommandScheduler() { } @@ -126,7 +123,6 @@ public void schedule(Command command) { * @throws IllegalStateException if {@code CommandBus} was not * {@linkplain #setCommandBus(CommandBus) set} prior to calling this method */ - @CheckReturnValue protected CommandBus commandBus() { checkState(commandBus != null, "CommandBus is not set"); return commandBus; diff --git a/server/src/main/java/io/spine/server/commandbus/package-info.java b/server/src/main/java/io/spine/server/commandbus/package-info.java index 0510d06672d..d8607d9b492 100644 --- a/server/src/main/java/io/spine/server/commandbus/package-info.java +++ b/server/src/main/java/io/spine/server/commandbus/package-info.java @@ -22,7 +22,10 @@ * This package provides classes and interfaces related to * {@link io.spine.server.commandbus.CommandBus CommandBus} and its configuration. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.commandbus; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/commandstore/CEntity.java b/server/src/main/java/io/spine/server/commandstore/CEntity.java index 558c0c3d3ec..75b5a698801 100644 --- a/server/src/main/java/io/spine/server/commandstore/CEntity.java +++ b/server/src/main/java/io/spine/server/commandstore/CEntity.java @@ -55,8 +55,8 @@ static CEntity createForStatus(Command command, CommandStatus status) { checkNotNull(command); checkNotNull(status); - final CommandId commandId = command.getId(); - final CEntity entity = create(commandId); + CommandId commandId = command.getId(); + CEntity entity = create(commandId); entity.setCommandAndStatus(command, status); return entity; } @@ -65,51 +65,58 @@ static CEntity createForError(Command command, Error error) { checkNotNull(command); checkNotNull(error); - final CommandId id = Records.getOrGenerateCommandId(command); + CommandId id = Records.getOrGenerateCommandId(command); - final CEntity result = create(id); + CEntity result = create(id); result.setError(id, command, error); return result; } private void setCommandAndStatus(Command command, CommandStatus status) { - final CommandRecord record = Records.newRecordBuilder(command, - status, - null).build(); + CommandRecord record = Records.newRecordBuilder(command, status, null) + .build(); updateState(record); } + @SuppressWarnings("CheckReturnValue") // calling builder private void setError(CommandId id, Command command, Error error) { - final CommandRecord.Builder builder = Records.newRecordBuilder(command, ERROR, id); + CommandRecord.Builder builder = Records.newRecordBuilder(command, ERROR, id); builder.getStatusBuilder() .setError(error); - final CommandRecord record = builder.build(); + CommandRecord record = builder.build(); updateState(record); } + private CommandRecord.Builder stateBuilder() { + return getState().toBuilder(); + } + + @SuppressWarnings("CheckReturnValue") // calling builder void setOkStatus() { - final CommandRecord.Builder builder = getState().toBuilder(); + CommandRecord.Builder builder = stateBuilder(); builder.getStatusBuilder() .setCode(OK); - final CommandRecord record = builder.build(); + CommandRecord record = builder.build(); updateState(record); } + @SuppressWarnings("CheckReturnValue") // calling builder void setToError(Error error) { - final CommandRecord.Builder builder = getState().toBuilder(); + CommandRecord.Builder builder = stateBuilder(); builder.getStatusBuilder() .setCode(ERROR) .setError(error); - final CommandRecord record = builder.build(); + CommandRecord record = builder.build(); updateState(record); } + @SuppressWarnings("CheckReturnValue") // calling builder void setToRejected(Rejection rejection) { - final CommandRecord.Builder builder = getState().toBuilder(); + CommandRecord.Builder builder = stateBuilder(); builder.getStatusBuilder() .setCode(REJECTED) .setRejection(rejection); - final CommandRecord record = builder.build(); + CommandRecord record = builder.build(); updateState(record); } } diff --git a/server/src/main/java/io/spine/server/commandstore/CRepository.java b/server/src/main/java/io/spine/server/commandstore/CRepository.java index 6408519a619..38e0ff09da6 100644 --- a/server/src/main/java/io/spine/server/commandstore/CRepository.java +++ b/server/src/main/java/io/spine/server/commandstore/CRepository.java @@ -33,8 +33,8 @@ import io.spine.server.commandbus.CommandRecord; import io.spine.server.commandbus.ProcessingStatus; import io.spine.server.entity.DefaultRecordBasedRepository; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import static com.google.common.collect.Iterators.transform; diff --git a/server/src/main/java/io/spine/server/commandstore/CommandStore.java b/server/src/main/java/io/spine/server/commandstore/CommandStore.java index ec4edf8a7a9..fd018840163 100644 --- a/server/src/main/java/io/spine/server/commandstore/CommandStore.java +++ b/server/src/main/java/io/spine/server/commandstore/CommandStore.java @@ -40,8 +40,8 @@ import io.spine.server.tenant.TenantAwareFunction; import io.spine.server.tenant.TenantAwareOperation; import io.spine.server.tenant.TenantIndex; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/commandstore/Records.java b/server/src/main/java/io/spine/server/commandstore/Records.java index 8b98e6fb4a7..67cb45e10c3 100644 --- a/server/src/main/java/io/spine/server/commandstore/Records.java +++ b/server/src/main/java/io/spine/server/commandstore/Records.java @@ -29,8 +29,8 @@ import io.spine.core.CommandStatus; import io.spine.server.commandbus.CommandRecord; import io.spine.server.commandbus.ProcessingStatus; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import static io.spine.base.Identifier.EMPTY_ID; diff --git a/server/src/main/java/io/spine/server/delivery/InProcessSharding.java b/server/src/main/java/io/spine/server/delivery/InProcessSharding.java index 61b790d625f..12e085483d4 100644 --- a/server/src/main/java/io/spine/server/delivery/InProcessSharding.java +++ b/server/src/main/java/io/spine/server/delivery/InProcessSharding.java @@ -25,8 +25,8 @@ import io.spine.core.BoundedContextName; import io.spine.core.MessageEnvelope; import io.spine.server.transport.TransportFactory; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/delivery/ShardedStream.java b/server/src/main/java/io/spine/server/delivery/ShardedStream.java index 968deeac241..6f13bc0b9ae 100644 --- a/server/src/main/java/io/spine/server/delivery/ShardedStream.java +++ b/server/src/main/java/io/spine/server/delivery/ShardedStream.java @@ -36,8 +36,8 @@ import io.spine.server.transport.TransportFactory; import io.spine.string.Stringifiers; import io.spine.type.ClassName; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Objects; import static com.google.common.base.Joiner.on; diff --git a/server/src/main/java/io/spine/server/entity/AbstractEntity.java b/server/src/main/java/io/spine/server/entity/AbstractEntity.java index edc780d3ad3..a06e09ab84d 100644 --- a/server/src/main/java/io/spine/server/entity/AbstractEntity.java +++ b/server/src/main/java/io/spine/server/entity/AbstractEntity.java @@ -26,9 +26,8 @@ import io.spine.string.Stringifiers; import io.spine.validate.ConstraintViolation; import io.spine.validate.MessageValidator; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; import java.util.List; import java.util.Objects; @@ -50,19 +49,16 @@ public abstract class AbstractEntity implements Entity thisClass; + private volatile @MonotonicNonNull EntityClass thisClass; /** The ID of the entity. */ private final I id; /** Cached version of string ID. */ - @Nullable - private volatile String stringId; + private volatile @MonotonicNonNull String stringId; /** The state of the entity. */ - @Nullable - private volatile S state; + private volatile @MonotonicNonNull S state; /** * Creates new instance with the passed ID. @@ -83,7 +79,6 @@ public I getId() { * {@inheritDoc} */ @Override - @CheckReturnValue public S getState() { if (state == null) { state = getDefaultState(); @@ -131,7 +126,6 @@ void setState(S newState) { * {@inheritDoc} */ @Override - @CheckReturnValue public S getDefaultState() { final Class entityClass = getClass(); @SuppressWarnings("unchecked") diff --git a/server/src/main/java/io/spine/server/entity/AbstractVersionableEntity.java b/server/src/main/java/io/spine/server/entity/AbstractVersionableEntity.java index c20a597cb76..a72a86d5794 100644 --- a/server/src/main/java/io/spine/server/entity/AbstractVersionableEntity.java +++ b/server/src/main/java/io/spine/server/entity/AbstractVersionableEntity.java @@ -30,7 +30,6 @@ import io.spine.server.entity.rejection.CannotModifyArchivedEntity; import io.spine.server.entity.rejection.CannotModifyDeletedEntity; -import javax.annotation.CheckReturnValue; import java.util.Objects; import static com.google.common.base.Preconditions.checkNotNull; @@ -213,7 +212,6 @@ int incrementVersion() { /** * Obtains timestamp of the entity version. */ - @CheckReturnValue public Timestamp whenModified() { return version.getTimestamp(); } diff --git a/server/src/main/java/io/spine/server/entity/DefaultEntityStorageConverter.java b/server/src/main/java/io/spine/server/entity/DefaultEntityStorageConverter.java index 8c75d8cc29e..b21b9f9f64b 100644 --- a/server/src/main/java/io/spine/server/entity/DefaultEntityStorageConverter.java +++ b/server/src/main/java/io/spine/server/entity/DefaultEntityStorageConverter.java @@ -65,10 +65,11 @@ public EntityStorageConverter withFieldMask(FieldMask fieldMask) { * @param builder the entity builder to update * @param entity the entity which data is passed to the {@link EntityRecord} we are building */ + @SuppressWarnings("CheckReturnValue") // calling builder @Override protected void updateBuilder(EntityRecord.Builder builder, E entity) { if (entity instanceof AbstractVersionableEntity) { - final AbstractVersionableEntity versionable = (AbstractVersionableEntity) entity; + AbstractVersionableEntity versionable = (AbstractVersionableEntity) entity; builder.setVersion(versionable.getVersion()) .setLifecycleFlags(versionable.getLifecycleFlags()); } diff --git a/server/src/main/java/io/spine/server/entity/EntityClass.java b/server/src/main/java/io/spine/server/entity/EntityClass.java index 8c297e6e4f1..b5313fac461 100644 --- a/server/src/main/java/io/spine/server/entity/EntityClass.java +++ b/server/src/main/java/io/spine/server/entity/EntityClass.java @@ -26,8 +26,8 @@ import io.spine.server.model.ModelClass; import io.spine.server.model.ModelError; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Objects; diff --git a/server/src/main/java/io/spine/server/entity/EntityStateEnvelope.java b/server/src/main/java/io/spine/server/entity/EntityStateEnvelope.java index a1a1949e287..dbd6a5595e0 100644 --- a/server/src/main/java/io/spine/server/entity/EntityStateEnvelope.java +++ b/server/src/main/java/io/spine/server/entity/EntityStateEnvelope.java @@ -31,8 +31,7 @@ import io.spine.core.TenantId; import io.spine.core.Version; import io.spine.string.Stringifiers; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.util.Exceptions.unsupported; diff --git a/server/src/main/java/io/spine/server/entity/EntityStorageConverter.java b/server/src/main/java/io/spine/server/entity/EntityStorageConverter.java index 9b55aad3cb6..b562a456111 100644 --- a/server/src/main/java/io/spine/server/entity/EntityStorageConverter.java +++ b/server/src/main/java/io/spine/server/entity/EntityStorageConverter.java @@ -26,8 +26,8 @@ import com.google.protobuf.Message; import io.spine.base.Identifier; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.io.Serializable; import java.util.Objects; diff --git a/server/src/main/java/io/spine/server/entity/EntityWithLifecycle.java b/server/src/main/java/io/spine/server/entity/EntityWithLifecycle.java index 474ebfa3713..d6140e761f4 100644 --- a/server/src/main/java/io/spine/server/entity/EntityWithLifecycle.java +++ b/server/src/main/java/io/spine/server/entity/EntityWithLifecycle.java @@ -24,8 +24,7 @@ import com.google.protobuf.Message; import io.spine.server.entity.storage.Column; import io.spine.server.entity.storage.EntityRecordWithColumns; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * An entity which has {@linkplain LifecycleFlags lifecycle flags}. diff --git a/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java b/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java index 0d27165f61a..4ac8d2848a7 100644 --- a/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java +++ b/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java @@ -28,8 +28,7 @@ import io.spine.reflect.GenericTypeIndex; import io.spine.validate.ValidatingBuilder; import io.spine.validate.ValidatingBuilders; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -58,8 +57,7 @@ public abstract class EventPlayingEntity , S, B> transaction; + private volatile @Nullable Transaction, S, B> transaction; /** * Creates a new instance. diff --git a/server/src/main/java/io/spine/server/entity/FieldMasks.java b/server/src/main/java/io/spine/server/entity/FieldMasks.java index b50bcdc6d16..8266266a0ee 100644 --- a/server/src/main/java/io/spine/server/entity/FieldMasks.java +++ b/server/src/main/java/io/spine/server/entity/FieldMasks.java @@ -26,11 +26,11 @@ import com.google.protobuf.Message; import com.google.protobuf.ProtocolStringList; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Collection; diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index a5863f8d1d1..d00bae511f7 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -25,6 +25,7 @@ import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; import com.google.protobuf.Any; import com.google.protobuf.FieldMask; import com.google.protobuf.Message; @@ -40,10 +41,8 @@ import io.spine.server.storage.RecordStorage; import io.spine.server.storage.StorageFactory; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; -import javax.annotation.OverridingMethodsMustInvokeSuper; import java.util.Collection; import java.util.Iterator; import java.util.Map; @@ -68,20 +67,13 @@ * @author Alexander Yevsyukov */ public abstract class RecordBasedRepository, S extends Message> - extends Repository { + extends Repository { /** Creates a new instance. */ protected RecordBasedRepository() { super(); } - /** {@inheritDoc} */ - @Override - protected RecordStorage createStorage(StorageFactory factory) { - final RecordStorage result = factory.createRecordStorage(getEntityClass()); - return result; - } - /** * Obtains {@link EntityFactory} associated with this repository. */ @@ -132,6 +124,20 @@ public void store(E entity) { storage.write(entity.getId(), record); } + @Override + public Iterator iterator(Predicate filter) { + final Iterator allEntities = loadAll(); + final Iterator result = filter(allEntities, filter); + return result; + } + + /** {@inheritDoc} */ + @Override + protected RecordStorage createStorage(StorageFactory factory) { + final RecordStorage result = factory.createRecordStorage(getEntityClass()); + return result; + } + /** * Stores {@linkplain Entity Entities} in bulk. * @@ -163,10 +169,9 @@ public void storeRecord(EntityRecord record) { * * @param id the ID of the entity to find * @return the entity or {@link Optional#absent()} if there is no entity with such ID - * or this entity is not visible + * or this entity is not visible */ @Override - @CheckReturnValue public Optional find(I id) { Optional optional = findRecord(id); if (!optional.isPresent()) { @@ -196,15 +201,7 @@ private Optional findRecord(I id) { return Optional.of(record); } - @Override - public Iterator iterator(Predicate filter) { - final Iterator allEntities = loadAll(); - final Iterator result = filter(allEntities, filter); - return result; - } - @Internal - @CheckReturnValue public EntityRecord findOrCreateRecord(I id) { final E entity = findOrCreate(id); final EntityRecordWithColumns recordWithColumns = toRecord(entity); @@ -223,7 +220,6 @@ public EntityRecord findOrCreateRecord(I id) { * @param id the ID of the entity to load * @return the entity with the specified ID */ - @CheckReturnValue protected E findOrCreate(I id) { Optional optional = findRecord(id); if (!optional.isPresent()) { @@ -257,7 +253,6 @@ protected E findOrCreate(I id) { * @param ids entity IDs to search for * @return all the entities in this repository with the IDs matching the given {@code Iterable} */ - @CheckReturnValue public Iterator loadAll(Iterable ids) { return loadAll(ids, FieldMask.getDefaultInstance()); } @@ -278,7 +273,6 @@ public Iterator loadAll(Iterable ids) { * @return all the entities in this repository with the IDs contained in the given {@code ids} * @see #loadAll(Iterable) */ - @CheckReturnValue public Iterator loadAll(Iterable ids, FieldMask fieldMask) { final RecordStorage storage = recordStorage(); final Iterator entityStorageRecords = storage.readMultiple(ids, fieldMask); @@ -297,7 +291,6 @@ public Iterator loadAll(Iterable ids, FieldMask fieldMask) { * @return all the entities in this repository * @see #loadAll(Iterable) */ - @CheckReturnValue public Iterator loadAll() { final RecordStorage storage = recordStorage(); final Iterator records = storage.readAll(); @@ -324,7 +317,6 @@ public Iterator loadAll() { * @return all the entities in this repository passed through the filters * @see EntityQuery */ - @CheckReturnValue public Iterator find(EntityFilters filters, FieldMask fieldMask) { checkNotNull(filters); checkNotNull(fieldMask); @@ -357,9 +349,9 @@ public Iterator findRecords(EntityFilters filters, FieldMask field /** * Creates an {@link EntityQuery} instance which has: *

    - *
  • All the parameters from the {@code src} Query; - *
  • At least one parameter limiting - * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns}. + *
  • All the parameters from the {@code src} Query; + *
  • At least one parameter limiting + * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns}. *
* *

If the {@code src} instance @@ -381,8 +373,8 @@ public Iterator findRecords(EntityFilters filters, FieldMask field * * @param src the source {@link EntityQuery} to take the parameters from * @return an {@link EntityQuery} which includes - * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns} unless - * they are not supported + * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns} unless + * they are not supported */ private EntityQuery toCompleteQuery(EntityQuery src) { final EntityQuery completeQuery; @@ -465,7 +457,7 @@ public I apply(@Nullable EntityId input) { final Message idAsMessage = unpack(idAsAny); @SuppressWarnings("unchecked") - // As the message class is the same as expected, the conversion is safe. + // As the message class is the same as expected, the conversion is safe. final I id = (I) idAsMessage; return id; } diff --git a/server/src/main/java/io/spine/server/entity/Repository.java b/server/src/main/java/io/spine/server/entity/Repository.java index 13ca3d3b759..73c7f4b969b 100644 --- a/server/src/main/java/io/spine/server/entity/Repository.java +++ b/server/src/main/java/io/spine/server/entity/Repository.java @@ -24,6 +24,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.Iterators; +import com.google.errorprone.annotations.OverridingMethodsMustInvokeSuper; import io.spine.base.Identifier; import io.spine.core.MessageEnvelope; import io.spine.logging.Logging; @@ -36,11 +37,10 @@ import io.spine.string.Stringifiers; import io.spine.type.MessageClass; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; -import javax.annotation.OverridingMethodsMustInvokeSuper; import java.util.Iterator; import static com.google.common.base.Preconditions.checkState; @@ -68,16 +68,14 @@ public abstract class Repository> *

This field is null when a repository is not {@linkplain * BoundedContext#register(Repository) registered} yet. */ - @Nullable - private BoundedContext boundedContext; + private @MonotonicNonNull BoundedContext boundedContext; /** * Model class of entities managed by this repository. * *

This field is null if {@link #entityClass()} is never called. */ - @Nullable - private volatile EntityClass entityClass; + private volatile @MonotonicNonNull EntityClass entityClass; /** * The data storage for this repository. @@ -85,8 +83,7 @@ public abstract class Repository> *

This field is null if the storage was not {@linkplain #initStorage(StorageFactory) * initialized} or the repository was {@linkplain #close() closed}. */ - @Nullable - private Storage storage; + private @Nullable Storage storage; /** Lazily initialized logger. */ private final Supplier loggerSupplier = Logging.supplyFor(getClass()); @@ -104,7 +101,7 @@ protected final EntityClass entityClass() { if (entityClass == null) { @SuppressWarnings("unchecked") // The type is ensured by the declaration of this class. final Class cast = - (Class)ENTITY.getArgumentIn((Class>) getClass()); + (Class)ENTITY.getArgumentIn(getClass()); entityClass = getModelClass(cast); } return entityClass; @@ -121,14 +118,12 @@ protected EntityClass getModelClass(Class cls) { /** Returns the class of IDs used by this repository. */ @SuppressWarnings("unchecked") // The cast is ensured by generic parameters of the repository. - @CheckReturnValue public Class getIdClass() { return (Class) entityClass().getIdClass(); } /** Returns the class of entities managed by this repository. */ @SuppressWarnings("unchecked") // The cast is ensured by generic parameters of the repository. - @CheckReturnValue public Class getEntityClass() { return (Class) entityClass().value(); } @@ -137,7 +132,6 @@ public Class getEntityClass() { * Returns the {@link TypeUrl} for the state objects wrapped by entities * managed by this repository */ - @CheckReturnValue public TypeUrl getEntityStateType() { return entityClass().getStateType(); } @@ -225,7 +219,6 @@ private boolean managesVersionableEntities() { * @param id the id of the entity * @return new entity instance */ - @CheckReturnValue public abstract E create(I id); /** @@ -259,7 +252,6 @@ public Iterator iterator(Predicate filter) { * * @throws IllegalStateException if the storage is not assigned */ - @CheckReturnValue protected final Storage getStorage() { return checkStorage(this.storage); } diff --git a/server/src/main/java/io/spine/server/entity/RepositoryView.java b/server/src/main/java/io/spine/server/entity/RepositoryView.java index 97de2a2ad9f..1bc4063b007 100644 --- a/server/src/main/java/io/spine/server/entity/RepositoryView.java +++ b/server/src/main/java/io/spine/server/entity/RepositoryView.java @@ -23,7 +23,6 @@ import com.google.common.base.Optional; import com.google.common.base.Predicate; -import javax.annotation.CheckReturnValue; import java.util.Iterator; /** @@ -48,7 +47,6 @@ public interface RepositoryView> { * @param id the ID of the entity to load * @return the entity or {@link Optional#absent()} if there's no entity with such ID */ - @CheckReturnValue Optional find(I id); /** @@ -58,6 +56,5 @@ public interface RepositoryView> { * @param filter the {@linkplain Predicate#apply(Object) filtering} predicate * @return new iterator */ - @CheckReturnValue Iterator iterator(Predicate filter); } diff --git a/server/src/main/java/io/spine/server/entity/Transaction.java b/server/src/main/java/io/spine/server/entity/Transaction.java index a6a206305fe..ff2fb3aa74a 100644 --- a/server/src/main/java/io/spine/server/entity/Transaction.java +++ b/server/src/main/java/io/spine/server/entity/Transaction.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.annotation.Internal; import io.spine.core.EventContext; @@ -318,7 +319,8 @@ void rollback(Throwable cause) { * @return this instance of the transaction * @see Transaction#apply(EventEnvelope) */ - @SuppressWarnings("OverlyBroadCatchBlock") // to `rollback(..)` in case of any exception. + @CanIgnoreReturnValue + @SuppressWarnings("OverlyBroadCatchBlock") /* to `rollback(..)` in case of any exception. */ Transaction apply(EventEnvelope event) { final Phase phase = new Phase<>(this, event); @@ -360,6 +362,7 @@ private void commitAttributeChanges() { entity.updateStateChanged(); } + @SuppressWarnings("CheckReturnValue") // calling builder method void initAll(S state, Version version) { final B builder = getBuilder(); builder.clear(); diff --git a/server/src/main/java/io/spine/server/entity/VisibilityGuard.java b/server/src/main/java/io/spine/server/entity/VisibilityGuard.java index 466dd9f1288..8e38cc90d7a 100644 --- a/server/src/main/java/io/spine/server/entity/VisibilityGuard.java +++ b/server/src/main/java/io/spine/server/entity/VisibilityGuard.java @@ -29,8 +29,8 @@ import io.spine.option.EntityOption.Visibility; import io.spine.option.EntityOptions; import io.spine.type.TypeName; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/entity/package-info.java b/server/src/main/java/io/spine/server/entity/package-info.java index 22605d3e5d8..ce6a14be491 100644 --- a/server/src/main/java/io/spine/server/entity/package-info.java +++ b/server/src/main/java/io/spine/server/entity/package-info.java @@ -21,7 +21,10 @@ /** * This package contains classes and interfaces defining entity-oriented API and base functionality. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.entity; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/entity/storage/CompositeQueryParameter.java b/server/src/main/java/io/spine/server/entity/storage/CompositeQueryParameter.java index 6ca8da130ef..448ebab99ec 100644 --- a/server/src/main/java/io/spine/server/entity/storage/CompositeQueryParameter.java +++ b/server/src/main/java/io/spine/server/entity/storage/CompositeQueryParameter.java @@ -30,8 +30,8 @@ import com.google.common.collect.Multimap; import io.spine.client.ColumnFilter; import io.spine.client.CompositeColumnFilter.CompositeOperator; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.io.Serializable; import static com.google.common.base.Preconditions.checkArgument; diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java index 138ed84c5b7..1af243dd139 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java @@ -26,8 +26,8 @@ import com.google.gson.internal.Primitives; import io.spine.annotation.Internal; import io.spine.server.entity.Entity; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; diff --git a/server/src/main/java/io/spine/server/event/EEntity.java b/server/src/main/java/io/spine/server/event/EEntity.java index 60ce02d7bf2..bacd597c651 100644 --- a/server/src/main/java/io/spine/server/event/EEntity.java +++ b/server/src/main/java/io/spine/server/event/EEntity.java @@ -29,8 +29,8 @@ import io.spine.server.entity.AbstractEntity; import io.spine.server.entity.storage.Column; import io.spine.type.TypeName; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Comparator; import static io.spine.core.Events.clearEnrichments; diff --git a/server/src/main/java/io/spine/server/event/ERepository.java b/server/src/main/java/io/spine/server/event/ERepository.java index cca4a6a7cff..b7e48273d81 100644 --- a/server/src/main/java/io/spine/server/event/ERepository.java +++ b/server/src/main/java/io/spine/server/event/ERepository.java @@ -34,8 +34,8 @@ import io.spine.core.EventId; import io.spine.server.entity.DefaultRecordBasedRepository; import io.spine.server.storage.RecordStorage; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.List; diff --git a/server/src/main/java/io/spine/server/event/EventBus.java b/server/src/main/java/io/spine/server/event/EventBus.java index 5f3175492be..401d47671a9 100644 --- a/server/src/main/java/io/spine/server/event/EventBus.java +++ b/server/src/main/java/io/spine/server/event/EventBus.java @@ -39,8 +39,8 @@ import io.spine.server.outbus.OutputDispatcherRegistry; import io.spine.server.storage.StorageFactory; import io.spine.validate.MessageValidator; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Deque; import java.util.Set; import java.util.concurrent.Executor; diff --git a/server/src/main/java/io/spine/server/event/EventFactory.java b/server/src/main/java/io/spine/server/event/EventFactory.java index 9b7168a0b0c..363b626449d 100644 --- a/server/src/main/java/io/spine/server/event/EventFactory.java +++ b/server/src/main/java/io/spine/server/event/EventFactory.java @@ -33,8 +33,7 @@ import io.spine.server.integration.IntegrationEvent; import io.spine.server.integration.IntegrationEventContext; import io.spine.validate.ValidationException; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.base.Time.getCurrentTime; diff --git a/server/src/main/java/io/spine/server/event/EventStore.java b/server/src/main/java/io/spine/server/event/EventStore.java index 0d9c6a8f562..b307b477659 100644 --- a/server/src/main/java/io/spine/server/event/EventStore.java +++ b/server/src/main/java/io/spine/server/event/EventStore.java @@ -33,10 +33,10 @@ import io.spine.server.storage.StorageFactory; import io.spine.server.tenant.EventOperation; import io.spine.server.tenant.TenantAwareOperation; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; import java.io.IOException; import java.util.Iterator; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/event/MatchFilter.java b/server/src/main/java/io/spine/server/event/MatchFilter.java index 2a17bef3035..b7fd91acc4e 100644 --- a/server/src/main/java/io/spine/server/event/MatchFilter.java +++ b/server/src/main/java/io/spine/server/event/MatchFilter.java @@ -32,8 +32,8 @@ import io.spine.server.reflect.Field; import io.spine.type.TypeName; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.List; diff --git a/server/src/main/java/io/spine/server/event/MatchesStreamQuery.java b/server/src/main/java/io/spine/server/event/MatchesStreamQuery.java index 8050ab3aa34..e0d76e390f9 100644 --- a/server/src/main/java/io/spine/server/event/MatchesStreamQuery.java +++ b/server/src/main/java/io/spine/server/event/MatchesStreamQuery.java @@ -22,8 +22,8 @@ import com.google.common.base.Predicate; import io.spine.core.Event; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/integration/IntegrationBus.java b/server/src/main/java/io/spine/server/integration/IntegrationBus.java index 9c7f7bfda14..e55d1d8285e 100644 --- a/server/src/main/java/io/spine/server/integration/IntegrationBus.java +++ b/server/src/main/java/io/spine/server/integration/IntegrationBus.java @@ -42,8 +42,8 @@ import io.spine.server.transport.TransportFactory; import io.spine.server.transport.memory.InMemoryTransportFactory; import io.spine.validate.Validate; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Deque; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java b/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java index 0bea14bdf1c..ba1dd4447dd 100644 --- a/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java +++ b/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java @@ -25,7 +25,6 @@ import io.spine.server.entity.Entity; import io.spine.server.entity.EntityClass; -import javax.annotation.CheckReturnValue; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -61,7 +60,6 @@ class DefaultStateRegistry { * @param entityClass the class to check * @return {@code true} if there is a state for the passed class, {@code false} otherwise */ - @CheckReturnValue boolean contains(Class entityClass) { lock.readLock().lock(); try { @@ -97,7 +95,6 @@ Message putOrGet(Class entityClass) { * * @param entityClass an entity class */ - @CheckReturnValue Message get(Class entityClass) { lock.readLock().lock(); try { diff --git a/server/src/main/java/io/spine/server/model/HandlerMethod.java b/server/src/main/java/io/spine/server/model/HandlerMethod.java index 9c7968f9223..20f75524256 100644 --- a/server/src/main/java/io/spine/server/model/HandlerMethod.java +++ b/server/src/main/java/io/spine/server/model/HandlerMethod.java @@ -32,8 +32,8 @@ import io.spine.core.Version; import io.spine.server.event.EventFactory; import io.spine.type.MessageClass; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; diff --git a/server/src/main/java/io/spine/server/model/HandlerMethods.java b/server/src/main/java/io/spine/server/model/HandlerMethods.java index ffbe834ab9c..f1fe8aa3346 100644 --- a/server/src/main/java/io/spine/server/model/HandlerMethods.java +++ b/server/src/main/java/io/spine/server/model/HandlerMethods.java @@ -21,8 +21,7 @@ import com.google.common.base.Predicate; import io.spine.annotation.Internal; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/model/MethodPredicate.java b/server/src/main/java/io/spine/server/model/MethodPredicate.java index 9995a49625f..ffc6032b38e 100644 --- a/server/src/main/java/io/spine/server/model/MethodPredicate.java +++ b/server/src/main/java/io/spine/server/model/MethodPredicate.java @@ -21,8 +21,8 @@ package io.spine.server.model; import com.google.common.base.Predicate; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Method; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/model/package-info.java b/server/src/main/java/io/spine/server/model/package-info.java index 8f353662ebb..9b46ae671ed 100644 --- a/server/src/main/java/io/spine/server/model/package-info.java +++ b/server/src/main/java/io/spine/server/model/package-info.java @@ -23,9 +23,11 @@ * application. */ @Internal +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.model; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.Internal; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentFunction.java b/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentFunction.java index db475f013b3..1105b50e313 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentFunction.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentFunction.java @@ -27,8 +27,8 @@ import com.google.common.collect.FluentIterable; import com.google.protobuf.Message; import io.spine.server.event.EventBus; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Objects; import static com.google.common.base.Preconditions.checkArgument; diff --git a/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentsMap.java b/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentsMap.java index acefe5a6494..637c126ac1e 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentsMap.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/EnrichmentsMap.java @@ -32,8 +32,8 @@ import io.spine.type.KnownTypes; import io.spine.type.TypeName; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; diff --git a/server/src/main/java/io/spine/server/outbus/enrich/MessageEnrichment.java b/server/src/main/java/io/spine/server/outbus/enrich/MessageEnrichment.java index dfb9c42496f..fa384e56074 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/MessageEnrichment.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/MessageEnrichment.java @@ -26,8 +26,8 @@ import com.google.protobuf.Message; import io.spine.core.EventContext; import io.spine.server.reflect.Field; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.List; diff --git a/server/src/main/java/io/spine/server/outbus/enrich/SameTransition.java b/server/src/main/java/io/spine/server/outbus/enrich/SameTransition.java index 4dc5ebdd184..b67d7551658 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/SameTransition.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/SameTransition.java @@ -21,8 +21,7 @@ package io.spine.server.outbus.enrich; import com.google.common.base.Predicate; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/outbus/enrich/SupportsFieldConversion.java b/server/src/main/java/io/spine/server/outbus/enrich/SupportsFieldConversion.java index 9e372cae83e..792ef3c763b 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/SupportsFieldConversion.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/SupportsFieldConversion.java @@ -23,8 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import io.spine.annotation.Internal; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/package-info.java b/server/src/main/java/io/spine/server/package-info.java index d2e988e19af..36c62574d8b 100644 --- a/server/src/main/java/io/spine/server/package-info.java +++ b/server/src/main/java/io/spine/server/package-info.java @@ -25,7 +25,10 @@ * Those classes represent general data structures for working with backend data in * a multi-language system. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/procman/ProcessManagerRepository.java b/server/src/main/java/io/spine/server/procman/ProcessManagerRepository.java index b973e01fd02..b643bf803ca 100644 --- a/server/src/main/java/io/spine/server/procman/ProcessManagerRepository.java +++ b/server/src/main/java/io/spine/server/procman/ProcessManagerRepository.java @@ -59,7 +59,6 @@ import io.spine.server.route.RejectionProducers; import io.spine.server.route.RejectionRouting; -import javax.annotation.CheckReturnValue; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; @@ -339,7 +338,7 @@ public Set dispatch(EventEnvelope event) { * @return IDs of process managers who successfully consumed the rejection */ @Override - public Set dispatchRejection(final RejectionEnvelope rejection) { + public Set dispatchRejection(RejectionEnvelope rejection) { return PmRejectionEndpoint.handle(this, rejection); } @@ -379,7 +378,6 @@ void postEvents(Iterable events) { * @return loaded or created process manager instance */ @Override - @CheckReturnValue protected P findOrCreate(I id) { final P result = super.findOrCreate(id); final CommandBus commandBus = getBoundedContext().getCommandBus(); diff --git a/server/src/main/java/io/spine/server/procman/package-info.java b/server/src/main/java/io/spine/server/procman/package-info.java index c9ea4cf00c8..76293f78dc2 100644 --- a/server/src/main/java/io/spine/server/procman/package-info.java +++ b/server/src/main/java/io/spine/server/procman/package-info.java @@ -22,7 +22,10 @@ * This package provides classes related to Process Managers. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.procman; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java index 75e7e44e278..71411cd19f7 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java @@ -52,8 +52,8 @@ import io.spine.server.storage.RecordStorage; import io.spine.server.storage.StorageFactory; import io.spine.type.TypeName; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/projection/ProjectionStorage.java b/server/src/main/java/io/spine/server/projection/ProjectionStorage.java index 3ec277ee6dd..586b4ee763e 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionStorage.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionStorage.java @@ -30,8 +30,8 @@ import io.spine.server.entity.storage.EntityRecordWithColumns; import io.spine.server.storage.RecordReadRequest; import io.spine.server.storage.RecordStorage; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.Map; diff --git a/server/src/main/java/io/spine/server/rejection/RejectionBus.java b/server/src/main/java/io/spine/server/rejection/RejectionBus.java index 8407f1d748a..4226469a0f0 100644 --- a/server/src/main/java/io/spine/server/rejection/RejectionBus.java +++ b/server/src/main/java/io/spine/server/rejection/RejectionBus.java @@ -35,10 +35,10 @@ import io.spine.server.bus.EnvelopeValidator; import io.spine.server.outbus.CommandOutputBus; import io.spine.server.outbus.OutputDispatcherRegistry; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; import java.util.Deque; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/stand/AggregateQueryProcessor.java b/server/src/main/java/io/spine/server/stand/AggregateQueryProcessor.java index 24dbe4bdcdd..cdc328743f3 100644 --- a/server/src/main/java/io/spine/server/stand/AggregateQueryProcessor.java +++ b/server/src/main/java/io/spine/server/stand/AggregateQueryProcessor.java @@ -37,8 +37,8 @@ import io.spine.server.entity.EntityRecord; import io.spine.server.storage.RecordReadRequest; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Iterator; diff --git a/server/src/main/java/io/spine/server/stand/AggregateStateId.java b/server/src/main/java/io/spine/server/stand/AggregateStateId.java index 38351bd5555..e0e2fd15b44 100644 --- a/server/src/main/java/io/spine/server/stand/AggregateStateId.java +++ b/server/src/main/java/io/spine/server/stand/AggregateStateId.java @@ -24,8 +24,6 @@ import io.spine.string.StringifierRegistry; import io.spine.type.TypeUrl; -import javax.annotation.CheckReturnValue; - import static com.google.common.base.Preconditions.checkNotNull; /** @@ -55,7 +53,6 @@ private AggregateStateId(I aggregateId, TypeUrl stateType) { this.stateType = checkNotNull(stateType); } - @CheckReturnValue public static AggregateStateId of(I aggregateId, TypeUrl stateType) { return new AggregateStateId<>(aggregateId, stateType); } diff --git a/server/src/main/java/io/spine/server/stand/InMemoryTypeRegistry.java b/server/src/main/java/io/spine/server/stand/InMemoryTypeRegistry.java index cdb0f27d3ba..0619e157ce2 100644 --- a/server/src/main/java/io/spine/server/stand/InMemoryTypeRegistry.java +++ b/server/src/main/java/io/spine/server/stand/InMemoryTypeRegistry.java @@ -29,7 +29,6 @@ import io.spine.server.entity.VersionableEntity; import io.spine.type.TypeUrl; -import javax.annotation.CheckReturnValue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -87,7 +86,6 @@ static TypeRegistry newInstance() { return result; } - @CheckReturnValue @Override public ImmutableSet getTypes() { final ImmutableSet.Builder resultBuilder = ImmutableSet.builder(); @@ -98,7 +96,6 @@ public ImmutableSet getTypes() { return result; } - @CheckReturnValue @Override public ImmutableSet getAggregateTypes() { final ImmutableSet result = ImmutableSet.copyOf(knownAggregateTypes); diff --git a/server/src/main/java/io/spine/server/stand/MultitenantSubscriptionRegistry.java b/server/src/main/java/io/spine/server/stand/MultitenantSubscriptionRegistry.java index e5739f4c717..1c48cf3a3e8 100644 --- a/server/src/main/java/io/spine/server/stand/MultitenantSubscriptionRegistry.java +++ b/server/src/main/java/io/spine/server/stand/MultitenantSubscriptionRegistry.java @@ -27,8 +27,8 @@ import io.spine.core.TenantId; import io.spine.server.tenant.TenantFunction; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.HashSet; import java.util.Map; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/stand/RequestValidator.java b/server/src/main/java/io/spine/server/stand/RequestValidator.java index f58f694aa87..96dd6d7d5a9 100644 --- a/server/src/main/java/io/spine/server/stand/RequestValidator.java +++ b/server/src/main/java/io/spine/server/stand/RequestValidator.java @@ -29,8 +29,8 @@ import io.spine.validate.ConstraintViolation; import io.spine.validate.MessageValidator; import io.spine.validate.ValidationError; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.List; import static io.spine.server.transport.Statuses.invalidArgumentWithCause; diff --git a/server/src/main/java/io/spine/server/stand/Stand.java b/server/src/main/java/io/spine/server/stand/Stand.java index 105e8e04b83..daaaa82177b 100644 --- a/server/src/main/java/io/spine/server/stand/Stand.java +++ b/server/src/main/java/io/spine/server/stand/Stand.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.MoreExecutors; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.Message; import io.grpc.stub.StreamObserver; @@ -53,9 +54,9 @@ import io.spine.server.tenant.SubscriptionOperation; import io.spine.server.tenant.TenantAwareOperation; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nullable; import java.util.Set; import java.util.concurrent.Executor; @@ -315,7 +316,6 @@ public void run() { * * @return the set of types as {@link TypeUrl} instances */ - @CheckReturnValue public ImmutableSet getExposedTypes() { return typeRegistry.getTypes(); } @@ -328,7 +328,6 @@ public ImmutableSet getExposedTypes() { * * @return the set of types as {@link TypeUrl} instances */ - @CheckReturnValue public ImmutableSet getExposedAggregateTypes() { return typeRegistry.getAggregateTypes(); } @@ -511,8 +510,7 @@ public static class Builder { *

If set directly, the value would be matched to the multi-tenancy flag of aggregating * {@code BoundedContext}. */ - @Nullable - private Boolean multitenant; + private @MonotonicNonNull Boolean multitenant; private StandStorage storage; private Executor callbackExecutor; @@ -561,14 +559,14 @@ public StandStorage getStorage() { } @Internal + @CanIgnoreReturnValue public Builder setMultitenant(@Nullable Boolean multitenant) { this.multitenant = multitenant; return this; } @Internal - @Nullable - public Boolean isMultitenant() { + public @Nullable Boolean isMultitenant() { return multitenant; } diff --git a/server/src/main/java/io/spine/server/stand/SubscriptionRecord.java b/server/src/main/java/io/spine/server/stand/SubscriptionRecord.java index d62954125e7..2b7beb2c18e 100644 --- a/server/src/main/java/io/spine/server/stand/SubscriptionRecord.java +++ b/server/src/main/java/io/spine/server/stand/SubscriptionRecord.java @@ -28,9 +28,10 @@ import io.spine.client.Subscription; import io.spine.client.Target; import io.spine.client.Topic; +import io.spine.server.stand.Stand.EntityUpdateCallback; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.List; /** @@ -48,10 +49,9 @@ final class SubscriptionRecord { * The {@code callback} is null after the creation and until the subscription is activated. * * @see SubscriptionRegistry#add(Topic) - * @see SubscriptionRegistry#activate(Subscription, Stand.EntityUpdateCallback) + * @see SubscriptionRegistry#activate(Subscription, EntityUpdateCallback) */ - @Nullable - private Stand.EntityUpdateCallback callback = null; + private @Nullable EntityUpdateCallback callback = null; SubscriptionRecord(Subscription subscription, Target target, TypeUrl type) { this.subscription = subscription; @@ -64,7 +64,7 @@ final class SubscriptionRecord { * * @param callback the callback to attach */ - void activate(Stand.EntityUpdateCallback callback) { + void activate(EntityUpdateCallback callback) { this.callback = callback; } @@ -125,7 +125,7 @@ TypeUrl getType() { } @Nullable - Stand.EntityUpdateCallback getCallback() { + EntityUpdateCallback getCallback() { return callback; } diff --git a/server/src/main/java/io/spine/server/stand/SubscriptionValidator.java b/server/src/main/java/io/spine/server/stand/SubscriptionValidator.java index 05a060a2e22..8ea7353b5dd 100644 --- a/server/src/main/java/io/spine/server/stand/SubscriptionValidator.java +++ b/server/src/main/java/io/spine/server/stand/SubscriptionValidator.java @@ -25,8 +25,7 @@ import io.spine.client.SubscriptionValidationError; import io.spine.core.TenantId; import io.spine.server.tenant.TenantAwareFunction; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/stand/package-info.java b/server/src/main/java/io/spine/server/stand/package-info.java index 4e4c0b12107..829d4e1bd9f 100644 --- a/server/src/main/java/io/spine/server/stand/package-info.java +++ b/server/src/main/java/io/spine/server/stand/package-info.java @@ -23,9 +23,11 @@ */ @SPI +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.stand; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.SPI; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/storage/BulkStorageOperationsMixin.java b/server/src/main/java/io/spine/server/storage/BulkStorageOperationsMixin.java index 4739468b080..57245c813f1 100644 --- a/server/src/main/java/io/spine/server/storage/BulkStorageOperationsMixin.java +++ b/server/src/main/java/io/spine/server/storage/BulkStorageOperationsMixin.java @@ -21,7 +21,6 @@ import com.google.protobuf.Message; -import javax.annotation.CheckReturnValue; import java.util.Iterator; import java.util.Map; @@ -54,7 +53,6 @@ interface BulkStorageOperationsMixin { * @return the {@link Iterable} containing the records matching the given IDs * @throws IllegalStateException if the storage was closed before */ - @CheckReturnValue Iterator readMultiple(Iterable ids); /** @@ -66,6 +64,5 @@ interface BulkStorageOperationsMixin { * @return the {@code Map} containing the ID - record entries. * @throws IllegalStateException if the storage was closed before */ - @CheckReturnValue Iterator readAll(); } diff --git a/server/src/main/java/io/spine/server/storage/OperatorEvaluator.java b/server/src/main/java/io/spine/server/storage/OperatorEvaluator.java index 6cdc2e54f3e..1353f00f1e1 100644 --- a/server/src/main/java/io/spine/server/storage/OperatorEvaluator.java +++ b/server/src/main/java/io/spine/server/storage/OperatorEvaluator.java @@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableMap; import com.google.protobuf.Timestamp; import io.spine.annotation.Internal; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Objects; import static com.google.common.base.Preconditions.checkArgument; diff --git a/server/src/main/java/io/spine/server/storage/RecordStorage.java b/server/src/main/java/io/spine/server/storage/RecordStorage.java index e82a91dfa69..30bb504f9d3 100644 --- a/server/src/main/java/io/spine/server/storage/RecordStorage.java +++ b/server/src/main/java/io/spine/server/storage/RecordStorage.java @@ -114,6 +114,7 @@ public Optional read(RecordReadRequest request) { * or {@code Optional.absent()} if there is no record matching this request * @see #read(RecordReadRequest) */ + @SuppressWarnings("CheckReturnValue") // calling builder method public Optional read(RecordReadRequest request, FieldMask fieldMask) { final Optional rawResult = read(request); diff --git a/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java b/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java index 5f02499b8cb..755abd37ec4 100644 --- a/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java +++ b/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java @@ -26,8 +26,7 @@ import io.spine.base.Environment; import io.spine.core.BoundedContextName; import io.spine.server.storage.memory.InMemoryStorageFactory; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.util.Exceptions.newIllegalStateException; diff --git a/server/src/main/java/io/spine/server/storage/memory/EntityQueryMatcher.java b/server/src/main/java/io/spine/server/storage/memory/EntityQueryMatcher.java index 61d25e0092f..29c7eacfd26 100644 --- a/server/src/main/java/io/spine/server/storage/memory/EntityQueryMatcher.java +++ b/server/src/main/java/io/spine/server/storage/memory/EntityQueryMatcher.java @@ -33,8 +33,8 @@ import io.spine.server.entity.storage.EntityQuery; import io.spine.server.entity.storage.EntityRecordWithColumns; import io.spine.server.entity.storage.QueryParameters; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; diff --git a/server/src/main/java/io/spine/server/storage/memory/EntityRecordUnpacker.java b/server/src/main/java/io/spine/server/storage/memory/EntityRecordUnpacker.java index 5f329d60c1a..340fe9e0daa 100644 --- a/server/src/main/java/io/spine/server/storage/memory/EntityRecordUnpacker.java +++ b/server/src/main/java/io/spine/server/storage/memory/EntityRecordUnpacker.java @@ -23,8 +23,7 @@ import com.google.common.base.Function; import io.spine.server.entity.EntityRecord; import io.spine.server.entity.storage.EntityRecordWithColumns; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * The {@link Function} converting the {@link EntityRecordWithColumns} into {@link EntityRecord}. diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java index f284cc6c35a..c95f428f963 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java @@ -27,8 +27,8 @@ import io.spine.server.projection.ProjectionStorage; import io.spine.server.storage.RecordStorage; import io.spine.server.tenant.TenantFunction; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.Map; diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java index 6bd880bf317..0011217d6bb 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java @@ -32,8 +32,8 @@ import io.spine.server.storage.RecordReadRequest; import io.spine.server.storage.RecordStorage; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.Map; diff --git a/server/src/main/java/io/spine/server/storage/memory/MultitenantStorage.java b/server/src/main/java/io/spine/server/storage/memory/MultitenantStorage.java index 00b6f17c51a..ad0ec9576b3 100644 --- a/server/src/main/java/io/spine/server/storage/memory/MultitenantStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/MultitenantStorage.java @@ -22,8 +22,8 @@ import io.spine.core.TenantId; import io.spine.server.tenant.TenantFunction; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; diff --git a/server/src/main/java/io/spine/server/storage/memory/TenantAggregateRecords.java b/server/src/main/java/io/spine/server/storage/memory/TenantAggregateRecords.java index c490ca3badf..f495e3c181f 100644 --- a/server/src/main/java/io/spine/server/storage/memory/TenantAggregateRecords.java +++ b/server/src/main/java/io/spine/server/storage/memory/TenantAggregateRecords.java @@ -29,8 +29,8 @@ import io.spine.server.aggregate.AggregateReadRequest; import io.spine.server.entity.LifecycleFlags; import io.spine.time.Timestamps2; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.io.Serializable; import java.util.Comparator; import java.util.Iterator; diff --git a/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java b/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java index c9e2831ee5b..341c186eada 100644 --- a/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java +++ b/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java @@ -30,8 +30,8 @@ import io.spine.server.entity.storage.EntityQuery; import io.spine.server.entity.storage.EntityRecordWithColumns; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.util.Iterator; import java.util.Map; diff --git a/server/src/main/java/io/spine/server/storage/package-info.java b/server/src/main/java/io/spine/server/storage/package-info.java index db58d8d6524..f62035029ee 100644 --- a/server/src/main/java/io/spine/server/storage/package-info.java +++ b/server/src/main/java/io/spine/server/storage/package-info.java @@ -22,9 +22,11 @@ * This package provides interfaces and base classes for storages. */ @SPI +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.storage; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.SPI; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/tenant/TenantAwareFunction0.java b/server/src/main/java/io/spine/server/tenant/TenantAwareFunction0.java index f1df9444aaa..39a59205adb 100644 --- a/server/src/main/java/io/spine/server/tenant/TenantAwareFunction0.java +++ b/server/src/main/java/io/spine/server/tenant/TenantAwareFunction0.java @@ -23,8 +23,7 @@ import com.google.protobuf.Empty; import io.spine.annotation.SPI; import io.spine.core.TenantId; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A tenant-aware function that takes no parameters. @@ -45,13 +44,12 @@ protected TenantAwareFunction0(TenantId tenantId) { public abstract T apply(); - @Nullable @Override - public T apply(@Nullable Empty input) { + public @Nullable T apply(@Nullable Empty input) { return apply(); } public T execute() { - return super.execute(Empty.getDefaultInstance()); + return execute(Empty.getDefaultInstance()); } } diff --git a/server/src/main/java/io/spine/server/tenant/TenantFunction.java b/server/src/main/java/io/spine/server/tenant/TenantFunction.java index 553456314bb..06570d299ef 100644 --- a/server/src/main/java/io/spine/server/tenant/TenantFunction.java +++ b/server/src/main/java/io/spine/server/tenant/TenantFunction.java @@ -23,8 +23,7 @@ import com.google.common.base.Function; import io.spine.annotation.Internal; import io.spine.core.TenantId; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A function which can work in single-tenant and multi-tenant context and return a diff --git a/server/src/main/java/io/spine/server/transport/GrpcContainer.java b/server/src/main/java/io/spine/server/transport/GrpcContainer.java index 3f5f45f5e86..5a503e372ae 100644 --- a/server/src/main/java/io/spine/server/transport/GrpcContainer.java +++ b/server/src/main/java/io/spine/server/transport/GrpcContainer.java @@ -27,8 +27,8 @@ import io.grpc.ServerBuilder; import io.grpc.ServerServiceDefinition; import io.spine.client.ConnectionConstants; +import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nullable; import java.io.IOException; import java.util.Set; diff --git a/server/src/main/java/io/spine/server/transport/memory/InMemoryTransportFactory.java b/server/src/main/java/io/spine/server/transport/memory/InMemoryTransportFactory.java index 2e0371634c6..7699bcb5dd1 100644 --- a/server/src/main/java/io/spine/server/transport/memory/InMemoryTransportFactory.java +++ b/server/src/main/java/io/spine/server/transport/memory/InMemoryTransportFactory.java @@ -26,8 +26,7 @@ import io.spine.server.transport.Publisher; import io.spine.server.transport.Subscriber; import io.spine.server.transport.TransportFactory; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Multimaps.synchronizedMultimap; diff --git a/server/src/main/java/io/spine/server/tuple/Pair.java b/server/src/main/java/io/spine/server/tuple/Pair.java index ec28aa1e600..221dcc6c20e 100644 --- a/server/src/main/java/io/spine/server/tuple/Pair.java +++ b/server/src/main/java/io/spine/server/tuple/Pair.java @@ -24,8 +24,7 @@ import com.google.protobuf.Message; import io.spine.server.tuple.Element.AValue; import io.spine.server.tuple.Element.BValue; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Optional.fromNullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/main/java/io/spine/server/tuple/Quartet.java b/server/src/main/java/io/spine/server/tuple/Quartet.java index b8618ef5026..b5e9b9f3c36 100644 --- a/server/src/main/java/io/spine/server/tuple/Quartet.java +++ b/server/src/main/java/io/spine/server/tuple/Quartet.java @@ -26,8 +26,7 @@ import io.spine.server.tuple.Element.BValue; import io.spine.server.tuple.Element.CValue; import io.spine.server.tuple.Element.DValue; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Optional.fromNullable; import static io.spine.server.tuple.Element.value; diff --git a/server/src/main/java/io/spine/server/tuple/Quintet.java b/server/src/main/java/io/spine/server/tuple/Quintet.java index 01538b5ce85..fc68e77b54b 100644 --- a/server/src/main/java/io/spine/server/tuple/Quintet.java +++ b/server/src/main/java/io/spine/server/tuple/Quintet.java @@ -27,8 +27,7 @@ import io.spine.server.tuple.Element.CValue; import io.spine.server.tuple.Element.DValue; import io.spine.server.tuple.Element.EValue; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Optional.fromNullable; import static io.spine.server.tuple.Element.value; diff --git a/server/src/main/java/io/spine/server/tuple/Triplet.java b/server/src/main/java/io/spine/server/tuple/Triplet.java index e863582149c..94aeedf6e3e 100644 --- a/server/src/main/java/io/spine/server/tuple/Triplet.java +++ b/server/src/main/java/io/spine/server/tuple/Triplet.java @@ -25,8 +25,7 @@ import io.spine.server.tuple.Element.AValue; import io.spine.server.tuple.Element.BValue; import io.spine.server.tuple.Element.CValue; - -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Optional.fromNullable; import static io.spine.server.tuple.Element.value; diff --git a/server/src/main/java/io/spine/server/tuple/Tuple.java b/server/src/main/java/io/spine/server/tuple/Tuple.java index 2da7e8f22ec..d470543019c 100644 --- a/server/src/main/java/io/spine/server/tuple/Tuple.java +++ b/server/src/main/java/io/spine/server/tuple/Tuple.java @@ -26,9 +26,9 @@ import com.google.protobuf.Empty; import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.Message; +import org.checkerframework.checker.nullness.qual.Nullable; import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.io.Serializable; import java.util.Iterator; import java.util.List; diff --git a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java index 7d130f860de..be2c4d9f323 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java @@ -28,7 +28,6 @@ import io.spine.core.Versions; import io.spine.test.ReflectiveBuilder; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import java.lang.reflect.Constructor; @@ -78,7 +77,7 @@ public EntityBuilder() { // Have the constructor for finding usages easier. } - @SuppressWarnings("MethodDoesntCallSuperMethod") // fix IDEA bug + @SuppressWarnings("CheckReturnValue") // calling builder method @Override public EntityBuilder setResultClass(Class entityClass) { super.setResultClass(entityClass); @@ -117,7 +116,6 @@ protected EntityClass entityClass() { /** Returns the class of IDs used by entities. */ @SuppressWarnings("unchecked") // The cast is protected by generic parameters of the builder. - @CheckReturnValue protected Class getIdClass() { return (Class) entityClass().getIdClass(); } diff --git a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java index 630e0a89546..eeec0aa2fbf 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java +++ b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java @@ -43,8 +43,8 @@ */ public class Given { + /** Prevents instantiation of this utility class. */ private Given() { - // Prevent instantiation of this utility class. } /** diff --git a/testutil-server/src/main/java/io/spine/server/entity/given/GivenLifecycleFlags.java b/testutil-server/src/main/java/io/spine/server/entity/given/GivenLifecycleFlags.java index ecc5daa3a11..c8e1344af4d 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/given/GivenLifecycleFlags.java +++ b/testutil-server/src/main/java/io/spine/server/entity/given/GivenLifecycleFlags.java @@ -27,12 +27,12 @@ */ public class GivenLifecycleFlags { + /** Prevent instantiation of this utility class. */ private GivenLifecycleFlags() { - // Prevent instantiation of this utility class. } /** - * Creates {@code Visibility} with archived flag set to {@code true}. + * Creates an instance with archived flag set to {@code true}. */ public static LifecycleFlags archived() { return LifecycleFlags.newBuilder() @@ -41,7 +41,7 @@ public static LifecycleFlags archived() { } /** - * Creates {@code Visibility} with deleted flag set to {@code true}. + * Creates an instance with deleted flag set to {@code true}. */ public static LifecycleFlags deleted() { return LifecycleFlags.newBuilder() From cdd6f2855e96e789f944b009eb93d75a43320aa1 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 23 May 2018 02:50:09 +0300 Subject: [PATCH 03/53] Handle ignored return values --- .../io/spine/client/ActorRequestFactory.java | 21 ++++---- .../java/io/spine/client/CommandFactory.java | 22 ++++---- .../main/java/io/spine/client/Queries.java | 1 + .../java/io/spine/client/QueryFactory.java | 10 ++-- .../main/java/io/spine/client/Targets.java | 1 + .../io/spine/client/grpc/package-info.java | 2 + .../java/io/spine/client/package-info.java | 3 ++ .../main/java/io/spine/grpc/package-info.java | 3 ++ .../io/spine/client/ColumnFiltersShould.java | 22 +++++--- .../io/spine/client/CommandFactoryShould.java | 13 ++++- .../java/io/spine/client/QueriesShould.java | 9 +++- .../io/spine/client/QueryFactoryShould.java | 8 ++- .../java/io/spine/core/CommandsShould.java | 17 ++++-- .../java/io/spine/change/package-info.java | 3 ++ .../java/io/spine/core/CommandEnvelope.java | 1 + .../java/io/spine/core/EventEnvelope.java | 1 + core/src/main/java/io/spine/core/Events.java | 15 +++--- .../java/io/spine/core/RejectionEnvelope.java | 1 + .../main/java/io/spine/core/Rejections.java | 1 + .../main/java/io/spine/core/package-info.java | 3 ++ .../spine/change/BooleanMismatchShould.java | 14 +++-- .../io/spine/change/DoubleMismatchShould.java | 17 ++++-- .../io/spine/change/FloatMismatchShould.java | 17 ++++-- .../io/spine/change/IntMismatchShould.java | 17 ++++-- .../io/spine/change/LongMismatchShould.java | 17 ++++-- .../io/spine/change/StringMismatchShould.java | 17 ++++-- .../io/spine/model/assemble/package-info.java | 3 ++ .../java/io/spine/model/package-info.java | 3 ++ .../io/spine/model/verify/package-info.java | 3 ++ .../aggregate/storage/package-info.java | 3 ++ .../spine/server/bus/MessageDispatcher.java | 2 + .../io/spine/server/bus/package-info.java | 4 +- .../io/spine/server/command/package-info.java | 3 ++ .../server/commandstore/package-info.java | 3 ++ .../spine/server/delivery/package-info.java | 3 ++ .../server/entity/status/package-info.java | 2 + .../entity/storage/ColumnTypeRegistry.java | 8 +-- .../entity/storage/QueryParameters.java | 3 ++ .../server/entity/storage/package-info.java | 3 ++ .../io/spine/server/event/ERepository.java | 29 ++++++----- .../java/io/spine/server/event/EventBus.java | 21 ++++---- .../io/spine/server/event/EventStore.java | 52 ++++++++----------- .../server/event/EventSubscriberMethod.java | 2 + .../io/spine/server/event/package-info.java | 4 +- .../server/integration/IntegrationBus.java | 15 ++++-- .../server/integration/grpc/package-info.java | 2 + .../server/integration/package-info.java | 4 +- .../io/spine/server/model/HandlerMethod.java | 11 ++-- .../server/outbus/enrich/package-info.java | 4 +- .../io/spine/server/outbus/package-info.java | 4 +- .../spine/server/projection/package-info.java | 3 ++ .../io/spine/server/reflect/package-info.java | 2 + .../rejection/RejectionSubscriberMethod.java | 2 + .../spine/server/rejection/package-info.java | 3 ++ .../io/spine/server/route/package-info.java | 4 +- .../server/storage/memory/package-info.java | 3 ++ .../io/spine/server/tenant/package-info.java | 4 +- .../io/spine/server/transport/Publisher.java | 2 + .../server/transport/memory/package-info.java | 4 +- .../spine/server/transport/package-info.java | 3 ++ .../java/io/spine/server/tuple/Tuple.java | 11 ++-- .../io/spine/server/tuple/package-info.java | 4 +- 62 files changed, 343 insertions(+), 149 deletions(-) diff --git a/client/src/main/java/io/spine/client/ActorRequestFactory.java b/client/src/main/java/io/spine/client/ActorRequestFactory.java index 7c201f067c8..057a8879635 100644 --- a/client/src/main/java/io/spine/client/ActorRequestFactory.java +++ b/client/src/main/java/io/spine/client/ActorRequestFactory.java @@ -86,10 +86,11 @@ public TenantId getTenantId() { * @return new factory at new time zone */ public ActorRequestFactory switchTimezone(ZoneOffset zoneOffset) { - final ActorRequestFactory result = newBuilder().setActor(getActor()) - .setZoneOffset(zoneOffset) - .setTenantId(getTenantId()) - .build(); + ActorRequestFactory result = + newBuilder().setActor(getActor()) + .setZoneOffset(zoneOffset) + .setTenantId(getTenantId()) + .build(); return result; } @@ -137,11 +138,13 @@ protected CommandContext createCommandContext() { *

Sets the timestamp value to the * {@linkplain io.spine.base.Time#getCurrentTime() current time}. */ + @SuppressWarnings("CheckReturnValue") // calling builder ActorContext actorContext() { - final ActorContext.Builder builder = ActorContext.newBuilder() - .setActor(actor) - .setTimestamp(getCurrentTime()) - .setZoneOffset(zoneOffset); + ActorContext.Builder builder = + ActorContext.newBuilder() + .setActor(actor) + .setTimestamp(getCurrentTime()) + .setZoneOffset(zoneOffset); if (tenantId != null) { builder.setTenantId(tenantId); } @@ -211,7 +214,7 @@ public Builder setTenantId(@Nullable TenantId tenantId) { * * @return {@code null} */ - @SuppressWarnings("ReturnOfNull") // It's fine for an abstract Builder. + @SuppressWarnings("CheckReturnValue") // calling builder @CanIgnoreReturnValue public ActorRequestFactory build() { checkNotNull(actor, "`actor` must be defined"); diff --git a/client/src/main/java/io/spine/client/CommandFactory.java b/client/src/main/java/io/spine/client/CommandFactory.java index eff272c6bfd..720622363c5 100644 --- a/client/src/main/java/io/spine/client/CommandFactory.java +++ b/client/src/main/java/io/spine/client/CommandFactory.java @@ -222,13 +222,15 @@ static CommandContext createContext(@Nullable TenantId tenantId, return result; } + @SuppressWarnings("CheckReturnValue") // calling builder private static CommandContext.Builder newContextBuilder(@Nullable TenantId tenantId, UserId userId, ZoneOffset zoneOffset) { - final ActorContext.Builder actorContext = ActorContext.newBuilder() - .setActor(userId) - .setTimestamp(getCurrentTime()) - .setZoneOffset(zoneOffset); + ActorContext.Builder actorContext = + ActorContext.newBuilder() + .setActor(userId) + .setTimestamp(getCurrentTime()) + .setZoneOffset(zoneOffset); if (tenantId != null) { actorContext.setTenantId(tenantId); } @@ -248,11 +250,13 @@ private static CommandContext.Builder newContextBuilder(@Nullable TenantId tenan * @return new {@code CommandContext} */ private static CommandContext contextBasedOn(CommandContext value) { - final ActorContext.Builder withCurrentTime = value.getActorContext() - .toBuilder() - .setTimestamp(getCurrentTime()); - final CommandContext.Builder result = value.toBuilder() - .setActorContext(withCurrentTime); + ActorContext.Builder withCurrentTime = + value.getActorContext() + .toBuilder() + .setTimestamp(getCurrentTime()); + CommandContext.Builder result = + value.toBuilder() + .setActorContext(withCurrentTime); return result.build(); } } diff --git a/client/src/main/java/io/spine/client/Queries.java b/client/src/main/java/io/spine/client/Queries.java index 132e66cba75..1e118c1ad68 100644 --- a/client/src/main/java/io/spine/client/Queries.java +++ b/client/src/main/java/io/spine/client/Queries.java @@ -78,6 +78,7 @@ public static TypeUrl typeOf(Query query) { return typeUrl; } + @SuppressWarnings("CheckReturnValue") // calling builder static Query.Builder queryBuilderFor(Class entityClass, @Nullable Set ids, @Nullable Set columnFilters, diff --git a/client/src/main/java/io/spine/client/QueryFactory.java b/client/src/main/java/io/spine/client/QueryFactory.java index 187fb859228..45f12409ef7 100644 --- a/client/src/main/java/io/spine/client/QueryFactory.java +++ b/client/src/main/java/io/spine/client/QueryFactory.java @@ -181,12 +181,10 @@ Query composeQuery(Class entityClass, @Nullable FieldMask fieldMask) { checkNotNull(entityClass, "The class of Entity must be specified for a Query"); - final Query.Builder builder = queryBuilderFor(entityClass, - ids, - columnFilters, - fieldMask); - builder.setId(newQueryId()) - .setContext(actorContext); + Query.Builder builder = + queryBuilderFor(entityClass, ids, columnFilters, fieldMask) + .setId(newQueryId()) + .setContext(actorContext); return builder.build(); } } diff --git a/client/src/main/java/io/spine/client/Targets.java b/client/src/main/java/io/spine/client/Targets.java index 6ca0ec2eec2..68ee52eb18f 100644 --- a/client/src/main/java/io/spine/client/Targets.java +++ b/client/src/main/java/io/spine/client/Targets.java @@ -75,6 +75,7 @@ public static Target allOf(Class entityClass) { return result; } + @SuppressWarnings("CheckReturnValue") // calling builder static Target composeTarget(Class entityClass, @Nullable Set ids, @Nullable Set columnFilters) { diff --git a/client/src/main/java/io/spine/client/grpc/package-info.java b/client/src/main/java/io/spine/client/grpc/package-info.java index ba7a7bf2371..b47cdde9936 100644 --- a/client/src/main/java/io/spine/client/grpc/package-info.java +++ b/client/src/main/java/io/spine/client/grpc/package-info.java @@ -25,6 +25,8 @@ */ @Internal +@CheckReturnValue package io.spine.client.grpc; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.Internal; diff --git a/client/src/main/java/io/spine/client/package-info.java b/client/src/main/java/io/spine/client/package-info.java index a63ce0273b3..8cbcb73896b 100644 --- a/client/src/main/java/io/spine/client/package-info.java +++ b/client/src/main/java/io/spine/client/package-info.java @@ -22,7 +22,10 @@ * This package provides utility classes for client-side code. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.client; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/client/src/main/java/io/spine/grpc/package-info.java b/client/src/main/java/io/spine/grpc/package-info.java index daf53d0a6dd..00b184cb175 100644 --- a/client/src/main/java/io/spine/grpc/package-info.java +++ b/client/src/main/java/io/spine/grpc/package-info.java @@ -21,7 +21,10 @@ /** * This package contains classes and interfaces related to gRPC. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.grpc; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/client/src/test/java/io/spine/client/ColumnFiltersShould.java b/client/src/test/java/io/spine/client/ColumnFiltersShould.java index cb7b03c689b..115957bbefd 100644 --- a/client/src/test/java/io/spine/client/ColumnFiltersShould.java +++ b/client/src/test/java/io/spine/client/ColumnFiltersShould.java @@ -26,7 +26,9 @@ import com.google.protobuf.Timestamp; import io.spine.client.ColumnFilter.Operator; import io.spine.protobuf.AnyPacker; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Calendar; import java.util.concurrent.atomic.AtomicInteger; @@ -61,6 +63,9 @@ public class ColumnFiltersShould { private static final String COLUMN_NAME = "preciseColumn"; private static final Timestamp COLUMN_VALUE = getCurrentTime(); + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_util_ctor() { assertHasPrivateParameterlessCtor(ColumnFilters.class); @@ -129,28 +134,33 @@ public void create_ordering_filters_for_numbers() { @Test public void create_ordering_filters_for_strings() { - final String string = "abc"; - final ColumnFilter filter = gt("stringColumn", string); + final String str = "abc"; + final ColumnFilter filter = gt("stringColumn", str); assertNotNull(filter); assertEquals(GREATER_THAN, filter.getOperator()); final StringValue value = AnyPacker.unpack(filter.getValue()); - assertEquals(string, value.getValue()); + assertEquals(str, value.getValue()); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_create_ordering_filters_for_enums() { + thrown.expect(IllegalArgumentException.class); ge("enumColumn", EQUAL); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_create_ordering_filters_for_non_primitive_numbers() { final AtomicInteger number = new AtomicInteger(42); + + thrown.expect(IllegalArgumentException.class); ge("atomicColumn", number); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_create_ordering_filters_for_not_supported_types() { final Comparable value = Calendar.getInstance(); // Comparable but not supported + + thrown.expect(IllegalArgumentException.class); le("invalidColumn", value); } diff --git a/client/src/test/java/io/spine/client/CommandFactoryShould.java b/client/src/test/java/io/spine/client/CommandFactoryShould.java index aba7e7bd44c..653abcd86b0 100644 --- a/client/src/test/java/io/spine/client/CommandFactoryShould.java +++ b/client/src/test/java/io/spine/client/CommandFactoryShould.java @@ -35,13 +35,18 @@ import io.spine.time.ZoneOffset; import io.spine.time.ZoneOffsets; import io.spine.validate.ValidationException; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class CommandFactoryShould extends ActorRequestFactoryShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void create_command_context() { final TenantId tenantId = GivenTenantId.newUuid(); @@ -105,16 +110,20 @@ public void set_tenant_ID_in_commands_when_created_with_tenant_ID() { .getTenantId()); } - @Test(expected = ValidationException.class) + @Test public void throw_ValidationException_once_passed_invalid_Message() { final RequiredFieldCommand invalidCommand = RequiredFieldCommand.getDefaultInstance(); + + thrown.expect(ValidationException.class); factory().command() .create(invalidCommand); } - @Test(expected = ValidationException.class) + @Test public void throw_ValidationException_once_passed_invalid_Message_with_version() { final RequiredFieldCommand invalidCommand = RequiredFieldCommand.getDefaultInstance(); + + thrown.expect(ValidationException.class); factory().command() .create(invalidCommand, 42); } diff --git a/client/src/test/java/io/spine/client/QueriesShould.java b/client/src/test/java/io/spine/client/QueriesShould.java index b751337c55b..b23d012da95 100644 --- a/client/src/test/java/io/spine/client/QueriesShould.java +++ b/client/src/test/java/io/spine/client/QueriesShould.java @@ -22,7 +22,9 @@ import com.google.common.testing.NullPointerTester; import io.spine.test.client.TestEntity; import io.spine.type.TypeUrl; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.test.Tests.assertHasPrivateParameterlessCtor; import static org.junit.Assert.assertEquals; @@ -36,6 +38,9 @@ public class QueriesShould { private static final String TARGET_ENTITY_TYPE_URL = "type.spine.io/spine.test.queries.TestEntity"; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(Queries.class); @@ -58,7 +63,7 @@ public void return_proper_type_for_known_target() { assertEquals(TARGET_ENTITY_TYPE_URL, type.toString()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_ISE_for_unknown_type() { final Target target = Target.newBuilder() .setType("nonexistent/message.type") @@ -66,6 +71,8 @@ public void throw_ISE_for_unknown_type() { final Query query = Query.newBuilder() .setTarget(target) .build(); + + thrown.expect(IllegalStateException.class); Queries.typeOf(query); } } diff --git a/client/src/test/java/io/spine/client/QueryFactoryShould.java b/client/src/test/java/io/spine/client/QueryFactoryShould.java index ff96a552bad..a6bcafee2a8 100644 --- a/client/src/test/java/io/spine/client/QueryFactoryShould.java +++ b/client/src/test/java/io/spine/client/QueryFactoryShould.java @@ -26,7 +26,9 @@ import io.spine.test.client.TestEntity; import io.spine.test.client.TestEntityId; import io.spine.type.TypeUrl; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Collections; @@ -49,6 +51,9 @@ public class QueryFactoryShould extends ActorRequestFactoryShould { // See {@code client_requests} for declaration. private static final Class TARGET_ENTITY_CLASS = TestEntity.class; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void compose_proper_read_all_query() { final Query readAllQuery = factory().query() @@ -133,8 +138,9 @@ public void compose_proper_read_by_ids_query_with_multiple_random_paths() { verifyMultiplePathsInQuery(paths, readByIdsWithSinglePathQuery); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_create_query_with_empty_IDs_with_mask() { + thrown.expect(IllegalArgumentException.class); factory().query() .byIdsWithMask(TestEntity.class, Collections.emptySet(), diff --git a/client/src/test/java/io/spine/core/CommandsShould.java b/client/src/test/java/io/spine/core/CommandsShould.java index c80c37e1576..29b436815da 100644 --- a/client/src/test/java/io/spine/core/CommandsShould.java +++ b/client/src/test/java/io/spine/core/CommandsShould.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.testing.NullPointerTester; +import com.google.common.testing.NullPointerTester.Visibility; import com.google.protobuf.Any; import com.google.protobuf.BoolValue; import com.google.protobuf.Duration; @@ -41,7 +42,9 @@ import io.spine.time.ZoneOffsets; import io.spine.type.TypeName; import io.spine.type.TypeUrl; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.List; @@ -57,6 +60,7 @@ import static io.spine.time.Durations2.seconds; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -76,6 +80,9 @@ public class CommandsShould { private final TestActorRequestFactory requestFactory = TestActorRequestFactory.newInstance(CommandsShould.class); + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_ctor() { assertHasPrivateParameterlessCtor(Commands.class); @@ -91,7 +98,7 @@ public void sort_commands_by_timestamp() { secondsAgo(5)); final List sortedCommands = newArrayList(cmd1, cmd2, cmd3); final List commandsToSort = newArrayList(cmd3, cmd1, cmd2); - assertFalse(sortedCommands.equals(commandsToSort)); + assertNotEquals(sortedCommands, commandsToSort); Commands.sort(commandsToSort); @@ -128,7 +135,7 @@ public void pass_null_tolerance_test() { .setDefault(CommandContext.class, requestFactory.createCommandContext()) .setDefault(ZoneOffset.class, ZoneOffsets.UTC) .setDefault(UserId.class, GivenUserId.newUuid()) - .testStaticMethods(Commands.class, NullPointerTester.Visibility.PACKAGE); + .testStaticMethods(Commands.class, Visibility.PACKAGE); } @Test @@ -195,12 +202,13 @@ public void when_no_scheduling_options_then_consider_command_not_scheduled() { assertFalse(Commands.isScheduled(cmd)); } - @Test(expected = IllegalArgumentException.class) + @Test public void when_set_negative_delay_then_throw_exception() { final CommandContext context = GivenCommandContext.withScheduledDelayOf(seconds(-10)); final Command cmd = requestFactory.command() .createBasedOnContext(StringValue.getDefaultInstance(), context); + thrown.expect(IllegalArgumentException.class); Commands.isScheduled(cmd); } @@ -213,8 +221,9 @@ public void provide_stringifier_for_CommandId() { assertEquals(id, convertedBack); } - @Test(expected = IllegalArgumentException.class) + @Test public void throw_exception_if_checked_command_id_is_empty() { + thrown.expect(IllegalArgumentException.class); Commands.checkValid(CommandId.getDefaultInstance()); } diff --git a/core/src/main/java/io/spine/change/package-info.java b/core/src/main/java/io/spine/change/package-info.java index b16e5e9c33e..ea5fbea4c6d 100644 --- a/core/src/main/java/io/spine/change/package-info.java +++ b/core/src/main/java/io/spine/change/package-info.java @@ -22,7 +22,10 @@ * This package contains classes and interfaces for working with field value changes. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.change; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/core/src/main/java/io/spine/core/CommandEnvelope.java b/core/src/main/java/io/spine/core/CommandEnvelope.java index ea0be0bd3e4..93ca59a8e79 100644 --- a/core/src/main/java/io/spine/core/CommandEnvelope.java +++ b/core/src/main/java/io/spine/core/CommandEnvelope.java @@ -124,6 +124,7 @@ public ActorContext getActorContext() { * * @param builder event context builder into which the origin related fields are set */ + @SuppressWarnings("CheckReturnValue") // calling builder @Override public void setOriginFields(EventContext.Builder builder) { builder.setCommandContext(getCommandContext()); diff --git a/core/src/main/java/io/spine/core/EventEnvelope.java b/core/src/main/java/io/spine/core/EventEnvelope.java index 2c1e9b3159e..c866ff13935 100644 --- a/core/src/main/java/io/spine/core/EventEnvelope.java +++ b/core/src/main/java/io/spine/core/EventEnvelope.java @@ -109,6 +109,7 @@ public ActorContext getActorContext() { * * @param builder event context builder into which the origin related fields are set */ + @SuppressWarnings("CheckReturnValue") // calling builder @Override public void setOriginFields(EventContext.Builder builder) { final EventContext context = getEventContext(); diff --git a/core/src/main/java/io/spine/core/Events.java b/core/src/main/java/io/spine/core/Events.java index c7dfb6cfbd0..349e868cc94 100644 --- a/core/src/main/java/io/spine/core/Events.java +++ b/core/src/main/java/io/spine/core/Events.java @@ -30,7 +30,6 @@ import io.spine.string.StringifierRegistry; import io.spine.time.Timestamps2; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.UUID; @@ -49,13 +48,10 @@ public final class Events { /** Compares two events by their timestamps. */ - private static final Comparator eventComparator = new Comparator() { - @Override - public int compare(Event o1, Event o2) { - final Timestamp timestamp1 = getTimestamp(o1); - final Timestamp timestamp2 = getTimestamp(o2); - return Timestamps2.compare(timestamp1, timestamp2); - } + private static final Comparator eventComparator = (o1, o2) -> { + final Timestamp timestamp1 = getTimestamp(o1); + final Timestamp timestamp2 = getTimestamp(o2); + return Timestamps2.compare(timestamp1, timestamp2); }; /** The stringifier for event IDs. */ @@ -89,7 +85,7 @@ public static EventId generateId() { */ public static void sort(List events) { checkNotNull(events); - Collections.sort(events, eventComparator()); + events.sort(eventComparator()); } /** @@ -306,6 +302,7 @@ public static boolean isExternal(EventContext context) { * @param event the event to clear enrichments * @return the event without enrichments */ + @SuppressWarnings("CheckReturnValue") // calling builder @Internal public static Event clearEnrichments(Event event) { final EventContext context = event.getContext(); diff --git a/core/src/main/java/io/spine/core/RejectionEnvelope.java b/core/src/main/java/io/spine/core/RejectionEnvelope.java index 42add758ebb..994d72ccb7f 100644 --- a/core/src/main/java/io/spine/core/RejectionEnvelope.java +++ b/core/src/main/java/io/spine/core/RejectionEnvelope.java @@ -112,6 +112,7 @@ public RejectionContext getMessageContext() { * * @param builder event context builder into which the origin related fields are set */ + @SuppressWarnings("CheckReturnValue") // calling builder @Override public void setOriginFields(EventContext.Builder builder) { final RejectionContext context = getOuterObject().getContext(); diff --git a/core/src/main/java/io/spine/core/Rejections.java b/core/src/main/java/io/spine/core/Rejections.java index 31ab6a5c691..b4081100155 100644 --- a/core/src/main/java/io/spine/core/Rejections.java +++ b/core/src/main/java/io/spine/core/Rejections.java @@ -98,6 +98,7 @@ public static Rejection toRejection(ThrowableMessage throwable, Command command) return builder.build(); } + @SuppressWarnings("CheckReturnValue") // calling builder private static RejectionContext createContext(ThrowableMessage message, Command command) { final String stacktrace = Throwables.getStackTraceAsString(message); final RejectionContext.Builder builder = diff --git a/core/src/main/java/io/spine/core/package-info.java b/core/src/main/java/io/spine/core/package-info.java index c1e510c6d56..3bb17eca683 100644 --- a/core/src/main/java/io/spine/core/package-info.java +++ b/core/src/main/java/io/spine/core/package-info.java @@ -23,7 +23,10 @@ * event-sourcing applications. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.core; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/core/src/test/java/io/spine/change/BooleanMismatchShould.java b/core/src/test/java/io/spine/change/BooleanMismatchShould.java index a9bd6143983..fe2f360ca1d 100644 --- a/core/src/test/java/io/spine/change/BooleanMismatchShould.java +++ b/core/src/test/java/io/spine/change/BooleanMismatchShould.java @@ -21,7 +21,9 @@ package io.spine.change; import com.google.common.testing.NullPointerTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedFalse; import static io.spine.change.BooleanMismatch.expectedTrue; @@ -35,6 +37,9 @@ public class BooleanMismatchShould { private static final int VERSION = 2; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(BooleanMismatch.class); @@ -66,21 +71,24 @@ public void create_ValueMismatch_instance_for_expectedTrue_case() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_BooleanMismatch() { final ValueMismatch mismatch = IntMismatch.of(1, 2, 3, VERSION); + thrown.expect(RuntimeException.class); BooleanMismatch.unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_BooleanMismatch() { final ValueMismatch mismatch = IntMismatch.of(1, 2, 3, VERSION); + thrown.expect(RuntimeException.class); BooleanMismatch.unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_BooleanMismatch() { final ValueMismatch mismatch = IntMismatch.of(1, 2, 3, VERSION); + thrown.expect(RuntimeException.class); BooleanMismatch.unpackNewValue(mismatch); } diff --git a/core/src/test/java/io/spine/change/DoubleMismatchShould.java b/core/src/test/java/io/spine/change/DoubleMismatchShould.java index c1e54cbde3b..0269aecc69c 100644 --- a/core/src/test/java/io/spine/change/DoubleMismatchShould.java +++ b/core/src/test/java/io/spine/change/DoubleMismatchShould.java @@ -21,7 +21,9 @@ package io.spine.change; import com.google.common.testing.NullPointerTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedTrue; import static io.spine.change.DoubleMismatch.expectedNonZero; @@ -41,6 +43,9 @@ public class DoubleMismatchShould { private static final double NEW_VALUE = 14.52; private static final double DELTA = 0.01; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(DoubleMismatch.class); @@ -88,27 +93,31 @@ public void create_instance_for_unexpected_int_value() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackNewValue(mismatch); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_accept_same_expected_and_actual() { final double value = 19.19; + thrown.expect(IllegalArgumentException.class); unexpectedValue(value, value, NEW_VALUE, VERSION); } diff --git a/core/src/test/java/io/spine/change/FloatMismatchShould.java b/core/src/test/java/io/spine/change/FloatMismatchShould.java index d2083a9842d..1f975cb51be 100644 --- a/core/src/test/java/io/spine/change/FloatMismatchShould.java +++ b/core/src/test/java/io/spine/change/FloatMismatchShould.java @@ -21,7 +21,9 @@ package io.spine.change; import com.google.common.testing.NullPointerTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedTrue; import static io.spine.change.FloatMismatch.expectedNonZero; @@ -41,6 +43,9 @@ public class FloatMismatchShould { private static final float NEW_VALUE = 14.52f; private static final float DELTA = 0.01f; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(FloatMismatch.class); @@ -88,27 +93,31 @@ public void create_instance_for_unexpected_int_value() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackNewValue(mismatch); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_accept_same_expected_and_actual() { final float value = 19.19f; + thrown.expect(IllegalArgumentException.class); unexpectedValue(value, value, NEW_VALUE, VERSION); } diff --git a/core/src/test/java/io/spine/change/IntMismatchShould.java b/core/src/test/java/io/spine/change/IntMismatchShould.java index a35abe314f0..64061461b59 100644 --- a/core/src/test/java/io/spine/change/IntMismatchShould.java +++ b/core/src/test/java/io/spine/change/IntMismatchShould.java @@ -22,7 +22,9 @@ import com.google.common.testing.NullPointerTester; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedTrue; import static io.spine.test.Tests.assertHasPrivateParameterlessCtor; @@ -35,6 +37,9 @@ public class IntMismatchShould { private static final int NEW_VALUE = 1452; private static final int VERSION = 5; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(IntMismatch.class); @@ -83,27 +88,31 @@ public void create_instance_for_unexpected_int_value() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); IntMismatch.unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); IntMismatch.unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); IntMismatch.unpackNewValue(mismatch); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_accept_same_expected_and_actual() { final int value = 5; + thrown.expect(IllegalArgumentException.class); IntMismatch.unexpectedValue(value, value, NEW_VALUE, VERSION); } diff --git a/core/src/test/java/io/spine/change/LongMismatchShould.java b/core/src/test/java/io/spine/change/LongMismatchShould.java index 5d8e5389b9b..82de33850f6 100644 --- a/core/src/test/java/io/spine/change/LongMismatchShould.java +++ b/core/src/test/java/io/spine/change/LongMismatchShould.java @@ -21,7 +21,9 @@ package io.spine.change; import com.google.common.testing.NullPointerTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedTrue; import static io.spine.change.LongMismatch.expectedNonZero; @@ -40,6 +42,9 @@ public class LongMismatchShould { private static final long NEW_VALUE = 1452L; private static final int VERSION = 7; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(LongMismatch.class); @@ -87,27 +92,31 @@ public void create_instance_for_unexpected_int_value() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackNewValue(mismatch); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_accept_same_expected_and_actual() { final long value = 1919L; + thrown.expect(IllegalArgumentException.class); unexpectedValue(value, value, NEW_VALUE, VERSION); } diff --git a/core/src/test/java/io/spine/change/StringMismatchShould.java b/core/src/test/java/io/spine/change/StringMismatchShould.java index 02421e34a77..a3972c8f191 100644 --- a/core/src/test/java/io/spine/change/StringMismatchShould.java +++ b/core/src/test/java/io/spine/change/StringMismatchShould.java @@ -21,7 +21,9 @@ package io.spine.change; import com.google.common.testing.NullPointerTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.change.BooleanMismatch.expectedTrue; import static io.spine.change.StringMismatch.expectedEmpty; @@ -41,6 +43,9 @@ public class StringMismatchShould { private static final int VERSION = 1; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(StringMismatch.class); @@ -82,27 +87,31 @@ public void create_instance_for_unexpected_value() { assertEquals(VERSION, mismatch.getVersion()); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_accept_same_expected_and_actual() { final String value = "same-same"; + thrown.expect(IllegalArgumentException.class); unexpectedValue(value, value, NEW_VALUE, VERSION); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackExpected_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackExpected(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackActual_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackActual(mismatch); } - @Test(expected = RuntimeException.class) + @Test public void not_unpackNewValue_if_its_not_a_IntMismatch() { final ValueMismatch mismatch = expectedTrue(VERSION); + thrown.expect(RuntimeException.class); unpackNewValue(mismatch); } diff --git a/model/model-assembler/src/main/java/io/spine/model/assemble/package-info.java b/model/model-assembler/src/main/java/io/spine/model/assemble/package-info.java index 194860095e1..f0c024f6f04 100644 --- a/model/model-assembler/src/main/java/io/spine/model/assemble/package-info.java +++ b/model/model-assembler/src/main/java/io/spine/model/assemble/package-info.java @@ -21,7 +21,10 @@ /** * This package provides tools for assembling the Spine model at compile time. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.model.assemble; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/model/model-assembler/src/main/java/io/spine/model/package-info.java b/model/model-assembler/src/main/java/io/spine/model/package-info.java index 3bd5d7b2943..a645bda371d 100644 --- a/model/model-assembler/src/main/java/io/spine/model/package-info.java +++ b/model/model-assembler/src/main/java/io/spine/model/package-info.java @@ -21,7 +21,10 @@ /** * This package provides common types for analyzing Spine model at compile time. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.model; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/model/model-verifier/src/main/java/io/spine/model/verify/package-info.java b/model/model-verifier/src/main/java/io/spine/model/verify/package-info.java index db5d51fab23..50176933e77 100644 --- a/model/model-verifier/src/main/java/io/spine/model/verify/package-info.java +++ b/model/model-verifier/src/main/java/io/spine/model/verify/package-info.java @@ -21,7 +21,10 @@ /** * Utilities for verification of Spine project model. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.model.verify; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/aggregate/storage/package-info.java b/server/src/main/java/io/spine/server/aggregate/storage/package-info.java index 2b673160ec5..bd02b752467 100644 --- a/server/src/main/java/io/spine/server/aggregate/storage/package-info.java +++ b/server/src/main/java/io/spine/server/aggregate/storage/package-info.java @@ -22,7 +22,10 @@ * This package provides types related to storage of aggregates. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.aggregate.storage; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/bus/MessageDispatcher.java b/server/src/main/java/io/spine/server/bus/MessageDispatcher.java index 3e35e193d07..041bd75a02b 100644 --- a/server/src/main/java/io/spine/server/bus/MessageDispatcher.java +++ b/server/src/main/java/io/spine/server/bus/MessageDispatcher.java @@ -20,6 +20,7 @@ package io.spine.server.bus; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.spine.core.MessageEnvelope; import io.spine.type.MessageClass; @@ -53,6 +54,7 @@ public interface MessageDispatcher Builder newBuilder() { return new Builder<>(); } - @SuppressWarnings("unchecked") - // Unchecked copying from the src instance - // Never leads to a failure, since checked while writing into the instance itself + @SuppressWarnings({ + "unchecked" /* Unchecked copying from the src instance never leads to a failure, + since checked while writing into the instance itself. */, + "CheckReturnValue" // calling builder + }) public static Builder newBuilder(ColumnTypeRegistry src) { final Builder builder = newBuilder(); for (Map.Entry typeMapping : src.columnTypeMap.entrySet()) { diff --git a/server/src/main/java/io/spine/server/entity/storage/QueryParameters.java b/server/src/main/java/io/spine/server/entity/storage/QueryParameters.java index ba327a64e3c..f1aa9739d76 100644 --- a/server/src/main/java/io/spine/server/entity/storage/QueryParameters.java +++ b/server/src/main/java/io/spine/server/entity/storage/QueryParameters.java @@ -23,6 +23,7 @@ import com.google.common.base.Objects; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.spine.annotation.SPI; import io.spine.client.ColumnFilter; @@ -116,12 +117,14 @@ private Builder() { parameters = ImmutableList.builder(); } + @CanIgnoreReturnValue public Builder add(CompositeQueryParameter parameter) { parameters.add(parameter); hasLifecycle |= parameter.hasLifecycle(); return this; } + @CanIgnoreReturnValue public Builder addAll(Iterable parameters) { for (CompositeQueryParameter parameter : parameters) { add(parameter); diff --git a/server/src/main/java/io/spine/server/entity/storage/package-info.java b/server/src/main/java/io/spine/server/entity/storage/package-info.java index 5ebcb6a6702..3d668601ffc 100644 --- a/server/src/main/java/io/spine/server/entity/storage/package-info.java +++ b/server/src/main/java/io/spine/server/entity/storage/package-info.java @@ -22,7 +22,10 @@ * This package contains classes and interfaces for working with * {@link io.spine.server.entity.Entity entity} storage representation. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.entity.storage; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/event/ERepository.java b/server/src/main/java/io/spine/server/event/ERepository.java index b7e48273d81..e51f042482f 100644 --- a/server/src/main/java/io/spine/server/event/ERepository.java +++ b/server/src/main/java/io/spine/server/event/ERepository.java @@ -24,7 +24,6 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import com.google.protobuf.FieldMask; import com.google.protobuf.Timestamp; import io.spine.client.ColumnFilter; @@ -38,6 +37,8 @@ import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterators.filter; @@ -51,7 +52,6 @@ import static io.spine.server.event.EEntity.CREATED_TIME_COLUMN; import static io.spine.server.event.EEntity.TYPE_COLUMN; import static io.spine.server.event.EEntity.comparator; -import static java.util.Collections.sort; /** * A storage used by {@link EventStore} for keeping event data. @@ -67,9 +67,8 @@ class ERepository extends DefaultRecordBasedRepository private static final Function GET_EVENT = new Function() { - @Nullable @Override - public Event apply(@Nullable EEntity input) { + public @Nullable Event apply(@Nullable EEntity input) { if (input == null) { return null; } @@ -96,7 +95,7 @@ Iterator iterator(EventStreamQuery query) { final Predicate detailedLookupFilter = createEntityFilter(query); final Iterator filtered = filter(entities, detailedLookupFilter); final List entityList = newArrayList(filtered); - sort(entityList, comparator()); + entityList.sort(comparator()); final Iterator result = transform(entityList.iterator(), getEvent()); return result; } @@ -107,7 +106,9 @@ void store(Event event) { } void store(Iterable events) { - final Iterable entities = Iterables.transform(events, EventToEEntity.instance()); + final Iterable entities = StreamSupport.stream(events.spliterator(), false) + .map(EventToEEntity.instance()) + .collect(Collectors.toList()); store(newArrayList(entities)); } @@ -129,6 +130,7 @@ private static Predicate createEntityFilter(EventStreamQuery query) { * @param query the source {@link EventStreamQuery} to get the info from * @return new instance of {@link EntityFilters} filtering the events */ + @SuppressWarnings("CheckReturnValue") // calling builder @VisibleForTesting static EntityFilters toEntityFilters(EventStreamQuery query) { final EntityFilters.Builder builder = EntityFilters.newBuilder(); @@ -146,6 +148,7 @@ static EntityFilters toEntityFilters(EventStreamQuery query) { return builder.build(); } + @SuppressWarnings("CheckReturnValue") // calling builder private static Optional timeFilter(EventStreamQuery query) { final CompositeColumnFilter.Builder timeFilter = CompositeColumnFilter.newBuilder() .setOperator(ALL); @@ -163,14 +166,16 @@ private static Optional timeFilter(EventStreamQuery query return buildFilter(timeFilter); } + @SuppressWarnings("CheckReturnValue") // calling builder private static Optional typeFilter(EventStreamQuery query) { - final CompositeColumnFilter.Builder typeFilter = CompositeColumnFilter.newBuilder() - .setOperator(EITHER); + CompositeColumnFilter.Builder typeFilter = + CompositeColumnFilter.newBuilder() + .setOperator(EITHER); for (EventFilter eventFilter : query.getFilterList()) { - final String type = eventFilter.getEventType(); - if (!type.trim() - .isEmpty()) { - final ColumnFilter filter = eq(TYPE_COLUMN, type); + String type = eventFilter.getEventType() + .trim(); + if (!type.isEmpty()) { + ColumnFilter filter = eq(TYPE_COLUMN, type); typeFilter.addFilter(filter); } } diff --git a/server/src/main/java/io/spine/server/event/EventBus.java b/server/src/main/java/io/spine/server/event/EventBus.java index 401d47671a9..a2e316d4257 100644 --- a/server/src/main/java/io/spine/server/event/EventBus.java +++ b/server/src/main/java/io/spine/server/event/EventBus.java @@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.util.concurrent.MoreExecutors; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.grpc.stub.StreamObserver; import io.spine.annotation.Internal; @@ -262,8 +263,7 @@ public static class Builder extends AbstractBuilderEither a {@code StorageFactory} or an {@code EventStore} are mandatory * to create an instance of {@code EventBus}. */ - @Nullable - private StorageFactory storageFactory; + private @Nullable StorageFactory storageFactory; /** * A {@code EventStore} for storing all the events passed through the {@code EventBus}. @@ -274,8 +274,7 @@ public static class Builder extends AbstractBuilderEither a {@code StorageFactory} or an {@code EventStore} are mandatory * to create an instance of {@code EventBus}. */ - @Nullable - private EventStore eventStore; + private @Nullable EventStore eventStore; /** * Optional {@code Executor} for returning event stream from the {@code EventStore}. @@ -284,16 +283,14 @@ public static class Builder extends AbstractBuilderIf not set, a default value will be set by the builder. */ - @Nullable - private Executor eventStoreStreamExecutor; + private @Nullable Executor eventStoreStreamExecutor; /** * Optional validator for events. * *

If not set, a default value will be set by the builder. */ - @Nullable - private MessageValidator eventValidator; + private @Nullable MessageValidator eventValidator; /** * Optional enricher for events. @@ -301,8 +298,7 @@ public static class Builder extends AbstractBuilderIf not set, the enrichments will NOT be supported * in the {@code EventBus} instance built. */ - @Nullable - private EventEnricher enricher; + private @Nullable EventEnricher enricher; /** Logging level for posted events. */ private LoggingObserver.Level logLevelForPost = Level.TRACE; @@ -324,6 +320,7 @@ private Builder() { * * @see #setEventStore(EventStore) */ + @CanIgnoreReturnValue public Builder setStorageFactory(StorageFactory storageFactory) { checkState(eventStore == null, MSG_EVENT_STORE_CONFIGURED); this.storageFactory = checkNotNull(storageFactory); @@ -346,6 +343,7 @@ public Optional getStorageFactory() { * @see #setEventStoreStreamExecutor(Executor) * @see #setStorageFactory(StorageFactory) */ + @CanIgnoreReturnValue public Builder setEventStore(EventStore eventStore) { checkState(storageFactory == null, "storageFactory already set."); checkState(eventStoreStreamExecutor == null, "eventStoreStreamExecutor already set."); @@ -369,7 +367,7 @@ public Optional getEventStore() { * * @see #setEventStore(EventStore) */ - + @CanIgnoreReturnValue public Builder setEventStoreStreamExecutor(Executor eventStoreStreamExecutor) { checkState(eventStore == null, MSG_EVENT_STORE_CONFIGURED); this.eventStoreStreamExecutor = eventStoreStreamExecutor; @@ -380,6 +378,7 @@ public Optional getEventStoreStreamExecutor() { return Optional.fromNullable(eventStoreStreamExecutor); } + @CanIgnoreReturnValue public Builder setEventValidator(MessageValidator eventValidator) { this.eventValidator = checkNotNull(eventValidator); return this; diff --git a/server/src/main/java/io/spine/server/event/EventStore.java b/server/src/main/java/io/spine/server/event/EventStore.java index b307b477659..f238da35100 100644 --- a/server/src/main/java/io/spine/server/event/EventStore.java +++ b/server/src/main/java/io/spine/server/event/EventStore.java @@ -20,14 +20,14 @@ package io.spine.server.event; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicates; -import com.google.common.collect.FluentIterable; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.TextFormat; import io.grpc.ServerServiceDefinition; import io.grpc.stub.StreamObserver; import io.spine.core.Event; +import io.spine.core.Events; import io.spine.core.TenantId; import io.spine.server.event.grpc.EventStoreGrpc; import io.spine.server.storage.StorageFactory; @@ -41,11 +41,12 @@ import java.util.Iterator; import java.util.Set; import java.util.concurrent.Executor; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.tryFind; -import static io.spine.core.Events.getTenantId; /** * A store of all events in a bounded context. @@ -62,8 +63,7 @@ public class EventStore implements AutoCloseable { private final ERepository storage; private final Executor streamExecutor; - @Nullable - private final Logger logger; + private final @Nullable Logger logger; /** * Creates a builder for locally running {@code EventStore}. @@ -84,18 +84,10 @@ public static ServiceBuilder newServiceBuilder() { private static void ensureSameTenant(Iterable events) { checkNotNull(events); - - final Set tenants = - FluentIterable.from(events) - .transform(new Function() { - @Override - public TenantId apply( - @Nullable Event event) { - checkNotNull(event); - return getTenantId(event); - } - }) - .toSet(); + Set tenants = + StreamSupport.stream(events.spliterator(), false) + .map(Events::getTenantId) + .collect(Collectors.toSet()); checkArgument(tenants.size() == 1, TENANT_MISMATCH_ERROR_MSG, tenants); @@ -153,12 +145,12 @@ public void run() { */ public void appendAll(final Iterable events) { checkNotNull(events); - final Optional tenantDefiningEvent = tryFind(events, Predicates.notNull()); + Optional tenantDefiningEvent = tryFind(events, Predicates.notNull()); if (!tenantDefiningEvent.isPresent()) { return; } - final Event event = tenantDefiningEvent.get(); - final TenantAwareOperation op = new EventOperation(event) { + Event event = tenantDefiningEvent.get(); + TenantAwareOperation op = new EventOperation(event) { @Override public void run() { if (isTenantSet()) { // If multitenant context @@ -258,8 +250,7 @@ private abstract static class AbstractBuilder private Executor streamExecutor; private StorageFactory storageFactory; - @Nullable - private Logger logger; + private @Nullable Logger logger; public abstract T build(); @@ -276,6 +267,7 @@ public Executor getStreamExecutor() { return streamExecutor; } + @CanIgnoreReturnValue public B setStreamExecutor(Executor executor) { this.streamExecutor = checkNotNull(executor); return castThis(); @@ -285,16 +277,17 @@ public StorageFactory getStorageFactory() { return storageFactory; } + @CanIgnoreReturnValue public B setStorageFactory(StorageFactory storageFactory) { this.storageFactory = checkNotNull(storageFactory); return castThis(); } - @Nullable - public Logger getLogger() { + public @Nullable Logger getLogger() { return logger; } + @CanIgnoreReturnValue public B setLogger(@Nullable Logger logger) { this.logger = logger; return castThis(); @@ -305,6 +298,7 @@ public B setLogger(@Nullable Logger logger) { * * @see EventStore#log() */ + @CanIgnoreReturnValue public B withDefaultLogger() { setLogger(log()); return castThis(); @@ -325,7 +319,7 @@ public static class Builder extends AbstractBuilder { @Override public EventStore build() { checkState(); - final EventStore result = + EventStore result = new EventStore(getStreamExecutor(), getStorageFactory(), getLogger()); return result; } @@ -334,7 +328,7 @@ public EventStore build() { /** * The builder of {@code EventStore} instance exposed as gRPC service. * - * @see io.spine.server.event.grpc.EventStoreGrpc.EventStoreImplBase + * @see EventStoreGrpc.EventStoreImplBase * EventStoreGrpc.EventStoreImplBase */ public static class ServiceBuilder @@ -343,10 +337,10 @@ public static class ServiceBuilder @Override public ServerServiceDefinition build() { checkState(); - final EventStore eventStore = + EventStore eventStore = new EventStore(getStreamExecutor(), getStorageFactory(), getLogger()); - final EventStoreGrpc.EventStoreImplBase grpcService = new GrpcService(eventStore); - final ServerServiceDefinition result = grpcService.bindService(); + EventStoreGrpc.EventStoreImplBase grpcService = new GrpcService(eventStore); + ServerServiceDefinition result = grpcService.bindService(); return result; } } diff --git a/server/src/main/java/io/spine/server/event/EventSubscriberMethod.java b/server/src/main/java/io/spine/server/event/EventSubscriberMethod.java index ec4741a431e..5cbbb04f9e0 100644 --- a/server/src/main/java/io/spine/server/event/EventSubscriberMethod.java +++ b/server/src/main/java/io/spine/server/event/EventSubscriberMethod.java @@ -21,6 +21,7 @@ package io.spine.server.event; import com.google.common.base.Predicate; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.EventClass; import io.spine.core.EventContext; @@ -71,6 +72,7 @@ public static HandlerMethod.Factory factory() { return Factory.getInstance(); } + @CanIgnoreReturnValue // since event subscriber methods do not return values @Override public Object invoke(Object target, Message message, EventContext context) { ensureExternalMatch(this, context.getExternal()); diff --git a/server/src/main/java/io/spine/server/event/package-info.java b/server/src/main/java/io/spine/server/event/package-info.java index 566543f3ede..3062ff4ef15 100644 --- a/server/src/main/java/io/spine/server/event/package-info.java +++ b/server/src/main/java/io/spine/server/event/package-info.java @@ -21,8 +21,10 @@ /** * This package provides classes for server-side event processing. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.event; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/integration/IntegrationBus.java b/server/src/main/java/io/spine/server/integration/IntegrationBus.java index e55d1d8285e..d2ec27e07a6 100644 --- a/server/src/main/java/io/spine/server/integration/IntegrationBus.java +++ b/server/src/main/java/io/spine/server/integration/IntegrationBus.java @@ -22,6 +22,7 @@ import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.Message; import io.spine.core.Ack; @@ -296,16 +297,16 @@ public void unregister(ExternalMessageDispatcher dispatcher) { * the set of message types that are now requested by this instance of * integration bus */ + @SuppressWarnings("CheckReturnValue") // calling builder private void notifyOfNeeds(Iterable currentlyRequested) { - final RequestForExternalMessages.Builder resultBuilder = + RequestForExternalMessages.Builder resultBuilder = RequestForExternalMessages.newBuilder(); for (ChannelId channelId : currentlyRequested) { - final ExternalMessageType type = fromId(channelId); + ExternalMessageType type = fromId(channelId); resultBuilder.addRequestedMessageTypes(type); } - final RequestForExternalMessages result = resultBuilder.build(); - final ExternalMessage externalMessage = ExternalMessages.of(result, - boundedContextName); + RequestForExternalMessages result = resultBuilder.build(); + ExternalMessage externalMessage = ExternalMessages.of(result, boundedContextName); publisherHub.get(CONFIG_EXCHANGE_CHANNEL_ID) .publish(pack(newUuid()), externalMessage); } @@ -421,6 +422,7 @@ public Optional getEventBus() { return Optional.fromNullable(eventBus); } + @CanIgnoreReturnValue public Builder setEventBus(EventBus eventBus) { this.eventBus = checkNotNull(eventBus); return self(); @@ -437,16 +439,19 @@ public Optional getBoundedContextName() { return Optional.fromNullable(value); } + @CanIgnoreReturnValue public Builder setRejectionBus(RejectionBus rejectionBus) { this.rejectionBus = checkNotNull(rejectionBus); return self(); } + @CanIgnoreReturnValue public Builder setBoundedContextName(BoundedContextName boundedContextName) { this.boundedContextName = checkNotNull(boundedContextName); return self(); } + @CanIgnoreReturnValue public Builder setTransportFactory(TransportFactory transportFactory) { this.transportFactory = checkNotNull(transportFactory); return self(); diff --git a/server/src/main/java/io/spine/server/integration/grpc/package-info.java b/server/src/main/java/io/spine/server/integration/grpc/package-info.java index 54a3662cf61..e3ff12e2a4a 100644 --- a/server/src/main/java/io/spine/server/integration/grpc/package-info.java +++ b/server/src/main/java/io/spine/server/integration/grpc/package-info.java @@ -23,9 +23,11 @@ */ @Internal +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.integration.grpc; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.Internal; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/integration/package-info.java b/server/src/main/java/io/spine/server/integration/package-info.java index 5add8a191ed..c745de6087a 100644 --- a/server/src/main/java/io/spine/server/integration/package-info.java +++ b/server/src/main/java/io/spine/server/integration/package-info.java @@ -21,8 +21,10 @@ /** * This package contains classes and interfaces for communications between bounded contexts. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.integration; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/model/HandlerMethod.java b/server/src/main/java/io/spine/server/model/HandlerMethod.java index 20f75524256..2a162ecdac9 100644 --- a/server/src/main/java/io/spine/server/model/HandlerMethod.java +++ b/server/src/main/java/io/spine/server/model/HandlerMethod.java @@ -225,14 +225,15 @@ protected static List toList(@Nullable Object output) { * @return the result of message handling */ public Object invoke(Object target, Message message, C context) { + checkNotNull(target); checkNotNull(message); checkNotNull(context); try { - final int paramCount = getParamCount(); - final Object returnedValue = (paramCount == 1) - ? method.invoke(target, message) - : method.invoke(target, message, context); - return returnedValue; + int paramCount = getParamCount(); + Object result = (paramCount == 1) + ? method.invoke(target, message) + : method.invoke(target, message, context); + return result; } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { throw whyFailed(target, message, context, e); } diff --git a/server/src/main/java/io/spine/server/outbus/enrich/package-info.java b/server/src/main/java/io/spine/server/outbus/enrich/package-info.java index 438c33e282e..1f223e21daf 100644 --- a/server/src/main/java/io/spine/server/outbus/enrich/package-info.java +++ b/server/src/main/java/io/spine/server/outbus/enrich/package-info.java @@ -21,8 +21,10 @@ /** * This package contains classes and interfaces for event enrichment. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.outbus.enrich; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/outbus/package-info.java b/server/src/main/java/io/spine/server/outbus/package-info.java index 563ba502ebc..619e93eeb73 100644 --- a/server/src/main/java/io/spine/server/outbus/package-info.java +++ b/server/src/main/java/io/spine/server/outbus/package-info.java @@ -22,8 +22,10 @@ * This package provides classes for working with the * {@linkplain io.spine.server.commandbus.CommandBus bus} output. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.outbus; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/projection/package-info.java b/server/src/main/java/io/spine/server/projection/package-info.java index 37ca44c7fe9..56de59d347a 100644 --- a/server/src/main/java/io/spine/server/projection/package-info.java +++ b/server/src/main/java/io/spine/server/projection/package-info.java @@ -21,7 +21,10 @@ /** * This package provides classes for working with event stream projections. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.projection; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/reflect/package-info.java b/server/src/main/java/io/spine/server/reflect/package-info.java index 49e630b814b..921d9803cfd 100644 --- a/server/src/main/java/io/spine/server/reflect/package-info.java +++ b/server/src/main/java/io/spine/server/reflect/package-info.java @@ -22,9 +22,11 @@ * This package contains internal utilities for obtaining Reflection information. */ @Internal +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.reflect; +import com.google.errorprone.annotations.CheckReturnValue; import io.spine.annotation.Internal; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/rejection/RejectionSubscriberMethod.java b/server/src/main/java/io/spine/server/rejection/RejectionSubscriberMethod.java index 068e9fd3994..d27f7a2b365 100644 --- a/server/src/main/java/io/spine/server/rejection/RejectionSubscriberMethod.java +++ b/server/src/main/java/io/spine/server/rejection/RejectionSubscriberMethod.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.annotation.Internal; import io.spine.core.RejectionContext; @@ -68,6 +69,7 @@ public class RejectionSubscriberMethod extends RejectionHandlerMethod { * @param context * the context of the rejection */ + @CanIgnoreReturnValue @Override public Object invoke(Object target, Message rejectionMessage, RejectionContext context) { ensureExternalMatch(this, context.getExternal()); diff --git a/server/src/main/java/io/spine/server/rejection/package-info.java b/server/src/main/java/io/spine/server/rejection/package-info.java index ac2c79bd5a5..d8aa8d0071f 100644 --- a/server/src/main/java/io/spine/server/rejection/package-info.java +++ b/server/src/main/java/io/spine/server/rejection/package-info.java @@ -22,7 +22,10 @@ * This package provides classes for working with command rejections. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.rejection; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/route/package-info.java b/server/src/main/java/io/spine/server/route/package-info.java index 43a609f6ac6..e94c863ce03 100644 --- a/server/src/main/java/io/spine/server/route/package-info.java +++ b/server/src/main/java/io/spine/server/route/package-info.java @@ -21,8 +21,10 @@ /** * This package contains classes and interfaces for obtaining entity identifiers. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.route; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/storage/memory/package-info.java b/server/src/main/java/io/spine/server/storage/memory/package-info.java index 0c06147751b..3843f7215a8 100644 --- a/server/src/main/java/io/spine/server/storage/memory/package-info.java +++ b/server/src/main/java/io/spine/server/storage/memory/package-info.java @@ -26,7 +26,10 @@ *

In-memory storage supports multitenancy. Data for each tenant is stored * in a "slice" represented by a data class prefixed with {@code Tenant}. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.storage.memory; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/tenant/package-info.java b/server/src/main/java/io/spine/server/tenant/package-info.java index 42fb24c821e..ad9d4695630 100644 --- a/server/src/main/java/io/spine/server/tenant/package-info.java +++ b/server/src/main/java/io/spine/server/tenant/package-info.java @@ -21,8 +21,10 @@ /** * This package contains classes and interfaces for supporting multi-tenancy. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.tenant; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/transport/Publisher.java b/server/src/main/java/io/spine/server/transport/Publisher.java index db7e3d2b146..842855c49f3 100644 --- a/server/src/main/java/io/spine/server/transport/Publisher.java +++ b/server/src/main/java/io/spine/server/transport/Publisher.java @@ -19,6 +19,7 @@ */ package io.spine.server.transport; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import io.spine.core.Ack; import io.spine.server.integration.ExternalMessage; @@ -40,6 +41,7 @@ public interface Publisher extends MessageChannel { * @return an acknowledgment of message publishing * @see Ack */ + @CanIgnoreReturnValue @SuppressWarnings("UnusedReturnValue") // Return value is planned for future use. Ack publish(Any id, ExternalMessage message); } diff --git a/server/src/main/java/io/spine/server/transport/memory/package-info.java b/server/src/main/java/io/spine/server/transport/memory/package-info.java index 2567f66ab95..002feedce42 100644 --- a/server/src/main/java/io/spine/server/transport/memory/package-info.java +++ b/server/src/main/java/io/spine/server/transport/memory/package-info.java @@ -24,8 +24,10 @@ * *

Should be used in test purposes only. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.transport.memory; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/transport/package-info.java b/server/src/main/java/io/spine/server/transport/package-info.java index cacb80beabd..be989004be6 100644 --- a/server/src/main/java/io/spine/server/transport/package-info.java +++ b/server/src/main/java/io/spine/server/transport/package-info.java @@ -24,7 +24,10 @@ * *

Typical transport options include gRPC servers, messaging system integration etc. */ +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.transport; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/src/main/java/io/spine/server/tuple/Tuple.java b/server/src/main/java/io/spine/server/tuple/Tuple.java index d470543019c..b201cc50740 100644 --- a/server/src/main/java/io/spine/server/tuple/Tuple.java +++ b/server/src/main/java/io/spine/server/tuple/Tuple.java @@ -23,12 +23,13 @@ import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.UnmodifiableIterator; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Empty; import com.google.protobuf.GeneratedMessageV3; import com.google.protobuf.Message; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import javax.annotation.Nonnull; import java.io.Serializable; import java.util.Iterator; import java.util.List; @@ -81,8 +82,8 @@ protected Tuple(Object... values) { * @return the passed value * @throws IllegalArgumentException if the passed value is {@link Empty} */ - @Nullable - static + @CanIgnoreReturnValue + static @Nullable M checkNotEmpty(Class checkingClass, @Nullable M value) { if (value == null) { return null; @@ -97,6 +98,7 @@ M checkNotEmpty(Class checkingClass, @Nullable M value) { return value; } + @CanIgnoreReturnValue static M checkNotNullOrEmpty(Class checkingClass, M value) { checkNotNull(value); @@ -117,9 +119,8 @@ void checkAllNotEmpty(Class checkingClass, Message... values) { } } - @Nonnull @Override - public final Iterator iterator() { + public final @NonNull Iterator iterator() { final Iterator result = new ExtractingIterator(values); return result; } diff --git a/server/src/main/java/io/spine/server/tuple/package-info.java b/server/src/main/java/io/spine/server/tuple/package-info.java index 44347c27d16..64205d9f7c2 100644 --- a/server/src/main/java/io/spine/server/tuple/package-info.java +++ b/server/src/main/java/io/spine/server/tuple/package-info.java @@ -86,8 +86,10 @@ * {@link io.spine.server.tuple.Pair#withEither(com.google.protobuf.Message, * io.spine.server.tuple.Either) Pair.withEither()}. */ - +@CheckReturnValue @ParametersAreNonnullByDefault package io.spine.server.tuple; +import com.google.errorprone.annotations.CheckReturnValue; + import javax.annotation.ParametersAreNonnullByDefault; From 6a287f4bc18e40fc0a6141764cd90e59a0ef63b6 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 23 May 2018 19:04:23 +0300 Subject: [PATCH 04/53] Handle checking return values --- .idea/inspectionProfiles/Project_Default.xml | 9 ++--- .../io/spine/model/assemble/AssignLookup.java | 35 +++++-------------- .../server/entity/EventPlayingEntity.java | 3 +- .../io/spine/server/event/EventFactory.java | 10 +++--- .../server/procman/AbstractCommandRouter.java | 2 ++ .../spine/server/procman/CommandRouter.java | 1 + .../procman/IteratingCommandRouter.java | 1 + .../spine/server/procman/PmTransaction.java | 3 ++ .../spine/server/storage/RecordStorage.java | 5 +-- .../memory/InMemoryProjectionStorage.java | 3 +- .../storage/memory/InMemoryRecordStorage.java | 8 +++-- .../storage/memory/InMemoryStandStorage.java | 22 +++++------- .../server/storage/memory/TenantRecords.java | 8 +++-- 13 files changed, 48 insertions(+), 62 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index e4700808ca5..376fa9a7645 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -87,6 +87,7 @@

Calling this method will cause the {@linkplain #commandHandlers current commandHandlers} * not to contain duplicate entries in any {@code repeated} field. */ + @SuppressWarnings("CheckReturnValue") // calling builder private void removeDuplicates() { - final ProtocolStringList handlingTypesList = commandHandlers.getCommandHandlingTypesList(); - final Set commandHandlingTypes = newTreeSet(handlingTypesList); + ProtocolStringList list = commandHandlers.getCommandHandlingTypesList(); + Set types = newTreeSet(list); commandHandlers.clearCommandHandlingTypes() - .addAllCommandHandlingTypes(commandHandlingTypes); - } - - /** - * Ensures the given file existence. - * - *

Performs no action if the given file {@linkplain File#exists() exists}. - * - *

If the given file does not exist, it is created (with the parent dirs if required). - * - * @param file a file to create - */ - private static void ensureFile(File file) { - try { - if (!file.exists()) { - createParentDirs(file); - file.createNewFile(); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - private static boolean existsNonEmpty(File file) { - return file.exists() && file.length() > 0; + .addAllCommandHandlingTypes(types); } /** diff --git a/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java b/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java index 4ac8d2848a7..eda9e45c28c 100644 --- a/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java +++ b/server/src/main/java/io/spine/server/entity/EventPlayingEntity.java @@ -57,7 +57,8 @@ public abstract class EventPlayingEntity , S, B> transaction; + private volatile + @Nullable Transaction, S, B> transaction; /** * Creates a new instance. diff --git a/server/src/main/java/io/spine/server/event/EventFactory.java b/server/src/main/java/io/spine/server/event/EventFactory.java index 363b626449d..7a0de91c46e 100644 --- a/server/src/main/java/io/spine/server/event/EventFactory.java +++ b/server/src/main/java/io/spine/server/event/EventFactory.java @@ -152,11 +152,13 @@ private static EventContext toEventContext(IntegrationEventContext value) { .build(); } + @SuppressWarnings("CheckReturnValue") // calling builder private EventContext createContext(@Nullable Version version) { - final Timestamp timestamp = getCurrentTime(); - final EventContext.Builder builder = EventContext.newBuilder() - .setTimestamp(timestamp) - .setProducerId(producerId); + Timestamp timestamp = getCurrentTime(); + EventContext.Builder builder = + EventContext.newBuilder() + .setTimestamp(timestamp) + .setProducerId(producerId); origin.setOriginFields(builder); if (version != null) { builder.setVersion(version); diff --git a/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java b/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java index a59cd7cbff8..b92f0c730f2 100644 --- a/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java +++ b/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java @@ -23,6 +23,7 @@ import com.google.common.collect.Iterators; import com.google.common.collect.Queues; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.grpc.stub.StreamObserver; import io.spine.client.ActorRequestFactory; @@ -96,6 +97,7 @@ protected Command getSource() { /** * Adds {@code commandMessage} to be routed. */ + @CanIgnoreReturnValue public T add(Message commandMessage) { queue.add(commandMessage); return getThis(); diff --git a/server/src/main/java/io/spine/server/procman/CommandRouter.java b/server/src/main/java/io/spine/server/procman/CommandRouter.java index 2c89f058aa5..c1fdec1cddd 100644 --- a/server/src/main/java/io/spine/server/procman/CommandRouter.java +++ b/server/src/main/java/io/spine/server/procman/CommandRouter.java @@ -50,6 +50,7 @@ protected CommandRouter getThis() { * * @return the event with the source and produced commands */ + @SuppressWarnings("CheckReturnValue") // calling builder public CommandRouted routeAll() { final CommandRouted.Builder result = CommandRouted.newBuilder(); result.setSource(getSource()); diff --git a/server/src/main/java/io/spine/server/procman/IteratingCommandRouter.java b/server/src/main/java/io/spine/server/procman/IteratingCommandRouter.java index be2c7beab57..1de7a941b36 100644 --- a/server/src/main/java/io/spine/server/procman/IteratingCommandRouter.java +++ b/server/src/main/java/io/spine/server/procman/IteratingCommandRouter.java @@ -62,6 +62,7 @@ protected IteratingCommandRouter getThis() { * * @see CommandRouted#getMessageToFollowList() */ + @SuppressWarnings("CheckReturnValue") // calling builder protected CommandRouted routeFirst() { final CommandRouted.Builder result = CommandRouted.newBuilder(); result.setSource(getSource()); diff --git a/server/src/main/java/io/spine/server/procman/PmTransaction.java b/server/src/main/java/io/spine/server/procman/PmTransaction.java index 5d1ad171c1e..c5a1da70f55 100644 --- a/server/src/main/java/io/spine/server/procman/PmTransaction.java +++ b/server/src/main/java/io/spine/server/procman/PmTransaction.java @@ -58,6 +58,9 @@ class PmTransaction readMultipleRecords(Iterable ids); /** @see BulkStorageOperationsMixin#readMultiple(java.lang.Iterable) */ - protected abstract Iterator readMultipleRecords(Iterable ids, - FieldMask fieldMask); + protected abstract Iterator<@Nullable EntityRecord> readMultipleRecords(Iterable ids, + FieldMask fieldMask); /** @see BulkStorageOperationsMixin#readAll() */ protected abstract Iterator readAllRecords(); diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java index c95f428f963..d425ab0fcce 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryProjectionStorage.java @@ -120,7 +120,8 @@ protected Iterator readMultipleRecords(Iterable ids) { } @Override - protected Iterator readMultipleRecords(Iterable ids, FieldMask fieldMask) { + protected Iterator<@Nullable EntityRecord> readMultipleRecords(Iterable ids, + FieldMask fieldMask) { return recordStorage.readMultiple(ids, fieldMask); } diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryRecordStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryRecordStorage.java index e72806df0e0..0255867ccb6 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryRecordStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryRecordStorage.java @@ -21,6 +21,7 @@ package io.spine.server.storage.memory; import com.google.common.base.Optional; +import com.google.common.collect.Lists; import com.google.protobuf.FieldMask; import io.spine.server.entity.Entity; import io.spine.server.entity.EntityRecord; @@ -28,6 +29,7 @@ import io.spine.server.entity.storage.EntityQuery; import io.spine.server.entity.storage.EntityRecordWithColumns; import io.spine.server.storage.RecordStorage; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.Iterator; @@ -79,13 +81,13 @@ public boolean delete(I id) { } @Override - protected Iterator readMultipleRecords(final Iterable givenIds, - FieldMask fieldMask) { + protected Iterator<@Nullable EntityRecord> readMultipleRecords(Iterable givenIds, + FieldMask fieldMask) { final TenantRecords storage = getStorage(); // It is not possible to return an immutable collection, // since null may be present in it. - final Collection result = new LinkedList<>(); + final Collection result = Lists.newLinkedList(); for (I givenId : givenIds) { final EntityRecord matchingResult = storage.findAndApplyFieldMask(givenId, fieldMask); diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java index 0011217d6bb..511b16bc56d 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java @@ -20,7 +20,6 @@ package io.spine.server.storage.memory; import com.google.common.base.Optional; -import com.google.common.base.Predicate; import com.google.protobuf.FieldMask; import io.spine.core.BoundedContextName; import io.spine.server.entity.AbstractVersionableEntity; @@ -91,13 +90,10 @@ private static Iterator filterByType(Iterator record final TypeUrl expectedType) { final Iterator result = filter(records, - new Predicate() { - @Override - public boolean apply(@Nullable EntityRecord entityRecord) { - checkNotNull(entityRecord); - final TypeUrl actualType = ofEnclosed(entityRecord.getState()); - return expectedType.equals(actualType); - } + entityRecord -> { + checkNotNull(entityRecord); + final TypeUrl actualType = ofEnclosed(entityRecord.getState()); + return expectedType.equals(actualType); }); return result; } @@ -112,7 +108,6 @@ public boolean delete(AggregateStateId id) { return recordStorage().delete(id); } - @Nullable @Override protected Optional readRecord(AggregateStateId id) { final RecordReadRequest request = new RecordReadRequest<>(id); @@ -125,8 +120,8 @@ protected Iterator readMultipleRecords(Iterable } @Override - protected Iterator readMultipleRecords(Iterable ids, - FieldMask fieldMask) { + protected Iterator<@Nullable EntityRecord> readMultipleRecords(Iterable ids, + FieldMask fieldMask) { return recordStorage().readMultiple(ids, fieldMask); } @@ -141,9 +136,8 @@ protected Iterator readAllRecords(FieldMask fieldMask) { } @Override - protected Iterator readAllRecords( - EntityQuery query, - FieldMask fieldMask) { + protected Iterator readAllRecords(EntityQuery query, + FieldMask fieldMask) { return recordStorage().readAll(query, fieldMask); } diff --git a/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java b/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java index 341c186eada..aaf28fc0779 100644 --- a/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java +++ b/server/src/main/java/io/spine/server/storage/memory/TenantRecords.java @@ -103,8 +103,10 @@ Map readAllRecords(EntityQuery query, FieldMask fieldMask) { return result; } + @SuppressWarnings("CheckReturnValue") // calling builder + @Nullable EntityRecord findAndApplyFieldMask(I givenId, FieldMask fieldMask) { - EntityRecord matchingResult = null; + EntityRecord result = null; for (I recordId : filtered.keySet()) { if (recordId.equals(givenId)) { final Optional record = get(recordId); @@ -121,10 +123,10 @@ EntityRecord findAndApplyFieldMask(I givenId, FieldMask fieldMask) { final Any processed = pack(maskedState); matchingRecord.setState(processed); - matchingResult = matchingRecord.build(); + result = matchingRecord.build(); } } - return matchingResult; + return result; } Map readAllRecords(FieldMask fieldMask) { From 3c8ba1199e665f8caf82334d593b0dd459140a6b Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 23 May 2018 19:07:12 +0300 Subject: [PATCH 05/53] Handle checking return values --- .../src/main/java/io/spine/model/assemble/AssignLookup.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java b/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java index 178e226f6a2..b5d8ace373d 100644 --- a/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java +++ b/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java @@ -79,10 +79,12 @@ public Set getSupportedOptions() { return result; } + @SuppressWarnings("CheckReturnValue") // calling builder @Override protected void processElement(Element element) { - final TypeElement enclosingTypeElement = (TypeElement) element.getEnclosingElement(); - final String typeName = enclosingTypeElement.getQualifiedName().toString(); + TypeElement enclosingTypeElement = (TypeElement) element.getEnclosingElement(); + String typeName = enclosingTypeElement.getQualifiedName() + .toString(); commandHandlers.addCommandHandlingTypes(typeName); } From 9243298f61596c8e3816d1f305baaee009bd501d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 23 May 2018 19:11:55 +0300 Subject: [PATCH 06/53] Extract variable --- .../io/spine/model/verify/ModelVerifier.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java b/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java index d4b8114c4f0..6c2f1d16f5f 100644 --- a/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java +++ b/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java @@ -82,31 +82,32 @@ final class ModelVerifier { void verify(CommandHandlers spineModel) { for (String commandHandlingClass : spineModel.getCommandHandlingTypesList()) { final Class cls; + Logger log = log(); try { - log().debug("Trying to load class \'{}\'", commandHandlingClass); + log.debug("Trying to load class \'{}\'", commandHandlingClass); cls = getModelClass(commandHandlingClass); } catch (ClassNotFoundException e) { - log().warn("Failed to load class {}." + - " Consider using io.spine.tools.spine-model-verifier plugin" + - " only for the modules with the sufficient classpath.", - commandHandlingClass); + log.warn("Failed to load class {}." + + " Consider using io.spine.tools.spine-model-verifier plugin" + + " only for the modules with the sufficient classpath.", + commandHandlingClass); continue; } if (Aggregate.class.isAssignableFrom(cls)) { final Class aggregateClass = (Class) cls; model.asAggregateClass(aggregateClass); - log().debug("\'{}\' classified as Aggregate type.", aggregateClass); + log.debug("\'{}\' classified as Aggregate type.", aggregateClass); } else if (ProcessManager.class.isAssignableFrom(cls)) { final Class procManClass = (Class) cls; model.asProcessManagerClass(procManClass); - log().debug("\'{}\' classified as ProcessManager type.", procManClass); + log.debug("\'{}\' classified as ProcessManager type.", procManClass); } else if (CommandHandler.class.isAssignableFrom(cls)) { final Class commandHandler = (Class) cls; model.asCommandHandlerClass(commandHandler); - log().debug("\'{}\' classified as CommandHandler type.", commandHandler); + log.debug("\'{}\' classified as CommandHandler type.", commandHandler); } else { throw newIllegalArgumentException("Class %s is not a command handling type.", cls.getName()); @@ -144,7 +145,8 @@ public void execute(Project project) { } private static Collection javaCompile(Project project) { - return project.getTasks().withType(JavaCompile.class); + return project.getTasks() + .withType(JavaCompile.class); } private static URL[] extractDestinationDirs(Collection tasks) { From a963623609d9d51c248498d80da4f2aae890c5ee Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 24 May 2018 17:33:53 +0300 Subject: [PATCH 07/53] Use `Nullable` from the Checker framework Also handled ignored return values. --- .../io/spine/client/ActorRequestFactory.java | 2 +- .../java/io/spine/client/CommandFactory.java | 2 +- .../main/java/io/spine/client/Queries.java | 2 +- .../java/io/spine/client/QueryBuilder.java | 2 +- .../java/io/spine/client/QueryFactory.java | 2 +- .../main/java/io/spine/client/Targets.java | 2 +- .../java/io/spine/grpc/LoggingObserver.java | 2 +- .../java/io/spine/grpc/MemoizingObserver.java | 2 +- .../io/spine/client/QueryBuilderShould.java | 2 +- .../src/main/java/io/spine/core/Commands.java | 2 +- .../java/io/spine/core/EventPredicates.java | 2 +- ext.gradle | 4 +- .../io/spine/model/verify/ModelVerifier.java | 67 +++++++++---------- .../java/io/spine/server/package-info.java | 3 + .../spine/server/procman/PmTransaction.java | 9 +-- .../aggregate/AggregateStorageShould.java | 2 +- .../aggregate/AggregateTransactionShould.java | 2 +- .../given/AggregateRepositoryTestEnv.java | 2 +- .../given/aggregate/TaskAggregate.java | 2 +- .../server/commandbus/CommandStoreShould.java | 2 +- .../server/delivery/ShardedStreamShould.java | 2 +- .../entity/ThrowingValidatingBuilder.java | 2 +- .../entity/storage/ColumnRecordsShould.java | 2 +- .../entity/storage/given/ColumnTestEnv.java | 2 +- .../entity/storage/given/ColumnsTestEnv.java | 2 +- .../DelegatingEventDispatcherShould.java | 2 +- .../io/spine/server/event/EventBusShould.java | 2 +- .../event/given/CommandHandlerTestEnv.java | 2 +- .../event/given/EventEnricherTestEnv.java | 2 +- .../event/given/EventSubscriberTestEnv.java | 2 +- .../outbus/enrich/EnricherBuilderShould.java | 2 +- .../enrich/EnrichmentFunctionShould.java | 2 +- .../enrich/given/EnricherBuilderTestEnv.java | 2 +- .../given/EventMessageEnricherTestEnv.java | 2 +- .../given/ReferenceValidatorTestEnv.java | 2 +- .../procman/AbstractCommandRouterShould.java | 2 +- .../ProcessManagerRepositoryShould.java | 2 +- .../procman/given/PmTransactionTestEnv.java | 2 +- .../ProjectionTransactionShould.java | 2 +- .../given/ProjectionRepositoryTestEnv.java | 2 +- .../rejection/RejectionEnricherShould.java | 2 +- .../given/RejectionEnrichmentConsumer.java | 2 +- .../given/RejectionReactorMethodTestEnv.java | 2 +- .../RejectionSubscriberMethodTestEnv.java | 2 +- .../io/spine/server/stand/StandShould.java | 2 +- .../server/stand/StandStorageShould.java | 2 +- .../server/storage/RecordStorageShould.java | 2 +- .../io/spine/server/TestEventClasses.java | 2 +- .../server/aggregate/AggregateBuilder.java | 2 + .../aggregate/AggregateCommandTest.java | 2 +- .../aggregate/AggregatePartBuilder.java | 2 + .../aggregate/AggregatePartCommandTest.java | 2 +- .../io/spine/server/command/CommandTest.java | 2 +- .../server/command/TestEventFactory.java | 2 +- .../io/spine/server/entity/EntityBuilder.java | 17 ++--- .../server/procman/ProcessManagerBuilder.java | 7 +- .../procman/ProcessManagerDispatcher.java | 1 + .../server/projection/ProjectionBuilder.java | 3 + 58 files changed, 111 insertions(+), 100 deletions(-) diff --git a/client/src/main/java/io/spine/client/ActorRequestFactory.java b/client/src/main/java/io/spine/client/ActorRequestFactory.java index 057a8879635..d1969e843b7 100644 --- a/client/src/main/java/io/spine/client/ActorRequestFactory.java +++ b/client/src/main/java/io/spine/client/ActorRequestFactory.java @@ -28,7 +28,7 @@ import io.spine.time.ZoneOffset; import io.spine.time.ZoneOffsets; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.base.Time.getCurrentTime; diff --git a/client/src/main/java/io/spine/client/CommandFactory.java b/client/src/main/java/io/spine/client/CommandFactory.java index 720622363c5..734b10e8f08 100644 --- a/client/src/main/java/io/spine/client/CommandFactory.java +++ b/client/src/main/java/io/spine/client/CommandFactory.java @@ -34,7 +34,7 @@ import io.spine.time.ZoneOffset; import io.spine.validate.ValidationException; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.base.Time.getCurrentTime; diff --git a/client/src/main/java/io/spine/client/Queries.java b/client/src/main/java/io/spine/client/Queries.java index 1e118c1ad68..2cccd4cfb4b 100644 --- a/client/src/main/java/io/spine/client/Queries.java +++ b/client/src/main/java/io/spine/client/Queries.java @@ -25,7 +25,7 @@ import io.spine.base.Identifier; import io.spine.type.TypeUrl; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/client/src/main/java/io/spine/client/QueryBuilder.java b/client/src/main/java/io/spine/client/QueryBuilder.java index 15e08d4687e..a56f470fadf 100644 --- a/client/src/main/java/io/spine/client/QueryBuilder.java +++ b/client/src/main/java/io/spine/client/QueryBuilder.java @@ -27,7 +27,7 @@ import com.google.protobuf.Message; import io.spine.base.Identifier; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.Set; diff --git a/client/src/main/java/io/spine/client/QueryFactory.java b/client/src/main/java/io/spine/client/QueryFactory.java index 45f12409ef7..77cb97c72f3 100644 --- a/client/src/main/java/io/spine/client/QueryFactory.java +++ b/client/src/main/java/io/spine/client/QueryFactory.java @@ -24,7 +24,7 @@ import com.google.protobuf.Message; import io.spine.core.ActorContext; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Arrays; import java.util.Set; diff --git a/client/src/main/java/io/spine/client/Targets.java b/client/src/main/java/io/spine/client/Targets.java index 68ee52eb18f..81089c7f612 100644 --- a/client/src/main/java/io/spine/client/Targets.java +++ b/client/src/main/java/io/spine/client/Targets.java @@ -26,7 +26,7 @@ import io.spine.protobuf.AnyPacker; import io.spine.type.TypeUrl; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collections; import java.util.Set; diff --git a/client/src/main/java/io/spine/grpc/LoggingObserver.java b/client/src/main/java/io/spine/grpc/LoggingObserver.java index cbcff70e471..9ea10caccf4 100644 --- a/client/src/main/java/io/spine/grpc/LoggingObserver.java +++ b/client/src/main/java/io/spine/grpc/LoggingObserver.java @@ -29,7 +29,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.util.Exceptions.unsupported; import static java.lang.String.format; diff --git a/client/src/main/java/io/spine/grpc/MemoizingObserver.java b/client/src/main/java/io/spine/grpc/MemoizingObserver.java index cc88264d3a9..357572611a6 100644 --- a/client/src/main/java/io/spine/grpc/MemoizingObserver.java +++ b/client/src/main/java/io/spine/grpc/MemoizingObserver.java @@ -23,7 +23,7 @@ import io.grpc.stub.StreamObserver; import io.spine.annotation.Internal; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import static com.google.common.collect.Lists.newArrayList; diff --git a/client/src/test/java/io/spine/client/QueryBuilderShould.java b/client/src/test/java/io/spine/client/QueryBuilderShould.java index 1b336440407..8dda9baed15 100644 --- a/client/src/test/java/io/spine/client/QueryBuilderShould.java +++ b/client/src/test/java/io/spine/client/QueryBuilderShould.java @@ -33,7 +33,7 @@ import io.spine.type.TypeUrl; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.List; diff --git a/core/src/main/java/io/spine/core/Commands.java b/core/src/main/java/io/spine/core/Commands.java index f4f583ec3a5..f5f52023b70 100644 --- a/core/src/main/java/io/spine/core/Commands.java +++ b/core/src/main/java/io/spine/core/Commands.java @@ -33,7 +33,7 @@ import io.spine.string.StringifierRegistry; import io.spine.time.Timestamps2; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collections; import java.util.Comparator; import java.util.List; diff --git a/core/src/main/java/io/spine/core/EventPredicates.java b/core/src/main/java/io/spine/core/EventPredicates.java index 77f7bc89155..9151cfd5a04 100644 --- a/core/src/main/java/io/spine/core/EventPredicates.java +++ b/core/src/main/java/io/spine/core/EventPredicates.java @@ -24,7 +24,7 @@ import com.google.protobuf.Timestamp; import io.spine.time.Timestamps2; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/ext.gradle b/ext.gradle index 73df8cb0de4..d12ab613b08 100644 --- a/ext.gradle +++ b/ext.gradle @@ -25,7 +25,7 @@ * as we want to manage the versions in a single source. */ -def final SPINE_VERSION = '0.10.37-SNAPSHOT' +def final SPINE_VERSION = '0.10.39-SNAPSHOT' //noinspection GroovyAssignabilityCheck ext { @@ -40,7 +40,7 @@ ext { spineVersion = SPINE_VERSION // Depend on `base` for the general definitions and a model compiler. - spineBaseVersion = '0.10.38-SNAPSHOT' + spineBaseVersion = '0.10.39-SNAPSHOT' spineTimeVersion = '0.10.29-SNAPSHOT' diff --git a/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java b/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java index 6c2f1d16f5f..3b82b86a8d6 100644 --- a/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java +++ b/model/model-verifier/src/main/java/io/spine/model/verify/ModelVerifier.java @@ -28,13 +28,12 @@ import io.spine.server.model.Model; import io.spine.server.procman.ProcessManager; import io.spine.tools.gradle.ProjectHierarchy; -import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.tasks.compile.JavaCompile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.io.File; import java.net.MalformedURLException; import java.net.URI; @@ -75,43 +74,47 @@ final class ModelVerifier { * * @param spineModel the listing of the Spine model classes */ - @SuppressWarnings({ - "IfStatementWithTooManyBranches", // OK in this case. - "unchecked" // Checked by the `if` statements - }) void verify(CommandHandlers spineModel) { + Logger log = log(); for (String commandHandlingClass : spineModel.getCommandHandlingTypesList()) { final Class cls; - Logger log = log(); try { log.debug("Trying to load class \'{}\'", commandHandlingClass); cls = getModelClass(commandHandlingClass); } catch (ClassNotFoundException e) { log.warn("Failed to load class {}." + - " Consider using io.spine.tools.spine-model-verifier plugin" + - " only for the modules with the sufficient classpath.", + " Consider using io.spine.tools.spine-model-verifier plugin" + + " only for the modules with the sufficient classpath.", commandHandlingClass); continue; } - if (Aggregate.class.isAssignableFrom(cls)) { - final Class aggregateClass = - (Class) cls; - model.asAggregateClass(aggregateClass); - log.debug("\'{}\' classified as Aggregate type.", aggregateClass); - } else if (ProcessManager.class.isAssignableFrom(cls)) { - final Class procManClass = - (Class) cls; - model.asProcessManagerClass(procManClass); - log.debug("\'{}\' classified as ProcessManager type.", procManClass); - } else if (CommandHandler.class.isAssignableFrom(cls)) { - final Class commandHandler = - (Class) cls; - model.asCommandHandlerClass(commandHandler); - log.debug("\'{}\' classified as CommandHandler type.", commandHandler); - } else { - throw newIllegalArgumentException("Class %s is not a command handling type.", - cls.getName()); - } + verifyClass(cls); + } + } + + @SuppressWarnings({ + "unchecked" /* Checked by the `if` statements */, + "CheckReturnValue" /* Returned values for asXxxClass() are ignored because we use + these methods only for verification of the classes. */ + }) + private void verifyClass(Class cls) { + Logger log = log(); + if (Aggregate.class.isAssignableFrom(cls)) { + Class aggregateClass = (Class) cls; + model.asAggregateClass(aggregateClass); + log.debug("\'{}\' classified as Aggregate type.", aggregateClass); + } else if (ProcessManager.class.isAssignableFrom(cls)) { + Class procManClass = (Class) cls; + model.asProcessManagerClass(procManClass); + log.debug("\'{}\' classified as ProcessManager type.", procManClass); + } else if (CommandHandler.class.isAssignableFrom(cls)) { + Class commandHandler = (Class) cls; + model.asCommandHandlerClass(commandHandler); + log.debug("\'{}\' classified as CommandHandler type.", commandHandler); + } else { + throw newIllegalArgumentException( + "Class %s is not a command handling type.", cls.getName() + ); } } @@ -135,12 +138,8 @@ private static URLClassLoader createClassLoaderForProject(Project project) { private static Collection allJavaCompile(Project project) { final Collection tasks = newLinkedList(); - ProjectHierarchy.applyToAll(project.getRootProject(), new Action() { - @Override - public void execute(Project project) { - tasks.addAll(javaCompile(project)); - } - }); + ProjectHierarchy.applyToAll(project.getRootProject(), + p -> tasks.addAll(javaCompile(p))); return tasks; } diff --git a/server/src/main/java/io/spine/server/package-info.java b/server/src/main/java/io/spine/server/package-info.java index 36c62574d8b..9eac9b00b3f 100644 --- a/server/src/main/java/io/spine/server/package-info.java +++ b/server/src/main/java/io/spine/server/package-info.java @@ -24,6 +24,9 @@ *

Some of the classes in this package are also generated from Protobuf. * Those classes represent general data structures for working with backend data in * a multi-language system. + * + *

Classes and interfaces under this package are NOT meant be at the client site + * of an application. */ @CheckReturnValue @ParametersAreNonnullByDefault diff --git a/server/src/main/java/io/spine/server/procman/PmTransaction.java b/server/src/main/java/io/spine/server/procman/PmTransaction.java index c5a1da70f55..f7146d0c4ec 100644 --- a/server/src/main/java/io/spine/server/procman/PmTransaction.java +++ b/server/src/main/java/io/spine/server/procman/PmTransaction.java @@ -28,6 +28,8 @@ import io.spine.server.entity.TransactionListener; import io.spine.validate.ValidatingBuilder; +import java.sql.Connection; + /** * A transaction, within which {@linkplain ProcessManager ProcessManager instances} are modified. * @@ -109,10 +111,9 @@ PmTransaction start(ProcessManager processManager) { */ static > - PmTransaction startWith(ProcessManager processManager, - S state, - Version version) { + B extends ValidatingBuilder, + P extends ProcessManager> + PmTransaction startWith(P processManager, S state, Version version) { final PmTransaction tx = new PmTransaction<>(processManager, state, version); return tx; } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java index 154545fd9ae..19a5a9568a8 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java @@ -43,7 +43,7 @@ import io.spine.testdata.Sample; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Iterator; import java.util.List; diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java index 36b86c4835a..c7f5835f732 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java @@ -37,7 +37,7 @@ import io.spine.test.aggregate.event.AggTaskAdded; import io.spine.validate.ConstraintViolation; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import static com.google.common.collect.Lists.newLinkedList; diff --git a/server/src/test/java/io/spine/server/aggregate/given/AggregateRepositoryTestEnv.java b/server/src/test/java/io/spine/server/aggregate/given/AggregateRepositoryTestEnv.java index 3cdeca32902..9b8de639055 100644 --- a/server/src/test/java/io/spine/server/aggregate/given/AggregateRepositoryTestEnv.java +++ b/server/src/test/java/io/spine/server/aggregate/given/AggregateRepositoryTestEnv.java @@ -74,7 +74,7 @@ import io.spine.validate.BoolValueVBuilder; import io.spine.validate.StringValueVBuilder; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/aggregate/given/aggregate/TaskAggregate.java b/server/src/test/java/io/spine/server/aggregate/given/aggregate/TaskAggregate.java index 1096cfc0134..b48c6b5eb6d 100644 --- a/server/src/test/java/io/spine/server/aggregate/given/aggregate/TaskAggregate.java +++ b/server/src/test/java/io/spine/server/aggregate/given/aggregate/TaskAggregate.java @@ -39,7 +39,7 @@ import io.spine.test.aggregate.task.AggTaskId; import io.spine.test.aggregate.task.AggTaskVBuilder; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * An aggregate that fires a {@linkplain Pair pair} with an optional upon handling a command, diff --git a/server/src/test/java/io/spine/server/commandbus/CommandStoreShould.java b/server/src/test/java/io/spine/server/commandbus/CommandStoreShould.java index 22d8e85cd39..ebda9999672 100644 --- a/server/src/test/java/io/spine/server/commandbus/CommandStoreShould.java +++ b/server/src/test/java/io/spine/server/commandbus/CommandStoreShould.java @@ -46,7 +46,7 @@ import org.junit.Test; import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/delivery/ShardedStreamShould.java b/server/src/test/java/io/spine/server/delivery/ShardedStreamShould.java index 717e4be1923..bf69879e11e 100644 --- a/server/src/test/java/io/spine/server/delivery/ShardedStreamShould.java +++ b/server/src/test/java/io/spine/server/delivery/ShardedStreamShould.java @@ -34,7 +34,7 @@ import io.spine.test.aggregate.ProjectId; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.server.delivery.given.ShardedStreamTestEnv.anotherProjectsShardOne; import static io.spine.server.delivery.given.ShardedStreamTestEnv.anotherProjectsShardZero; diff --git a/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java b/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java index 8551fd52afe..d12cd2908a1 100644 --- a/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java +++ b/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java @@ -23,7 +23,7 @@ import io.spine.validate.AbstractValidatingBuilder; import io.spine.validate.ValidationException; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java index 0537b8581bd..a22490272b2 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java @@ -26,7 +26,7 @@ import io.spine.test.Tests; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java b/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java index 00e44ae3609..2fa92de8751 100644 --- a/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java +++ b/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java @@ -27,7 +27,7 @@ import io.spine.server.entity.VersionableEntity; import io.spine.server.entity.storage.Column; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.test.Tests.nullRef; import static org.junit.Assert.fail; diff --git a/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java b/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java index f409bed0e85..b2fe9121ea9 100644 --- a/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java +++ b/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java @@ -30,7 +30,7 @@ import io.spine.test.entity.ProjectId; import io.spine.testdata.Sample; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Dmytro Grankin diff --git a/server/src/test/java/io/spine/server/event/DelegatingEventDispatcherShould.java b/server/src/test/java/io/spine/server/event/DelegatingEventDispatcherShould.java index aec202a71a2..1f7502d9119 100644 --- a/server/src/test/java/io/spine/server/event/DelegatingEventDispatcherShould.java +++ b/server/src/test/java/io/spine/server/event/DelegatingEventDispatcherShould.java @@ -35,7 +35,7 @@ import org.junit.Before; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Set; import static io.spine.test.TestValues.newUuidValue; diff --git a/server/src/test/java/io/spine/server/event/EventBusShould.java b/server/src/test/java/io/spine/server/event/EventBusShould.java index 7355132a4b6..ceec1102367 100644 --- a/server/src/test/java/io/spine/server/event/EventBusShould.java +++ b/server/src/test/java/io/spine/server/event/EventBusShould.java @@ -50,7 +50,7 @@ import org.junit.Ignore; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java index 609eee255b7..096ba42e525 100644 --- a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java @@ -43,7 +43,7 @@ import io.spine.test.command.event.CmdTaskAdded; import org.slf4j.Logger; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.LinkedList; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java b/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java index 8b14646468f..1e80ef5b3c3 100644 --- a/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java @@ -43,7 +43,7 @@ import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.base.Identifier.newUuid; diff --git a/server/src/test/java/io/spine/server/event/given/EventSubscriberTestEnv.java b/server/src/test/java/io/spine/server/event/given/EventSubscriberTestEnv.java index 37e53d42843..6f65a57eda4 100644 --- a/server/src/test/java/io/spine/server/event/given/EventSubscriberTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/EventSubscriberTestEnv.java @@ -28,7 +28,7 @@ import io.spine.core.Subscribe; import io.spine.server.event.EventSubscriber; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Alexander Yevsyukov diff --git a/server/src/test/java/io/spine/server/outbus/enrich/EnricherBuilderShould.java b/server/src/test/java/io/spine/server/outbus/enrich/EnricherBuilderShould.java index a4c869a610e..0a22498fbe3 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/EnricherBuilderShould.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/EnricherBuilderShould.java @@ -32,7 +32,7 @@ import org.junit.Before; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.protobuf.TypeConverter.toMessage; import static org.junit.Assert.assertFalse; diff --git a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java index 0117f8afa5d..d81342a91cf 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java @@ -32,7 +32,7 @@ import org.junit.Before; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java index c5e7c37ec76..d62e096d0ba 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java @@ -34,7 +34,7 @@ import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Alexander Yevsyukov diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java index 562cda9f263..85bf3afb521 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java @@ -34,7 +34,7 @@ import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Alexander Yevsyukov diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java index 684b34bad80..506e2ca4c0d 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java @@ -34,7 +34,7 @@ import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * @author Alexander Yevsyukov diff --git a/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java b/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java index 8c4d33de903..04bbcc29eda 100644 --- a/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java +++ b/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java @@ -38,7 +38,7 @@ import io.spine.server.commandbus.CommandDispatcher; import org.junit.Before; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java b/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java index c21c0c7e21f..00b6b35e7bb 100644 --- a/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java +++ b/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java @@ -67,7 +67,7 @@ import org.junit.Before; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Set; diff --git a/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java b/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java index efc4995255d..dd461d75186 100644 --- a/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java +++ b/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java @@ -32,7 +32,7 @@ import io.spine.test.procman.event.PmTaskAdded; import io.spine.validate.ConstraintViolation; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import static com.google.common.collect.Lists.newLinkedList; diff --git a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java index 16299ccd6aa..929d9af276b 100644 --- a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java +++ b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java @@ -37,7 +37,7 @@ import org.junit.Ignore; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collections; import java.util.List; diff --git a/server/src/test/java/io/spine/server/projection/given/ProjectionRepositoryTestEnv.java b/server/src/test/java/io/spine/server/projection/given/ProjectionRepositoryTestEnv.java index 4b02379e8fd..dda54ccd5a2 100644 --- a/server/src/test/java/io/spine/server/projection/given/ProjectionRepositoryTestEnv.java +++ b/server/src/test/java/io/spine/server/projection/given/ProjectionRepositoryTestEnv.java @@ -41,7 +41,7 @@ import io.spine.test.projection.event.PrjProjectStarted; import io.spine.test.projection.event.PrjTaskAdded; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Set; public class ProjectionRepositoryTestEnv { diff --git a/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java b/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java index 653976fca16..805353881d6 100644 --- a/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java +++ b/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java @@ -32,7 +32,7 @@ import org.junit.Before; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.server.rejection.given.Given.invalidProjectNameRejection; import static org.junit.Assert.assertNotEquals; diff --git a/server/src/test/java/io/spine/server/rejection/given/RejectionEnrichmentConsumer.java b/server/src/test/java/io/spine/server/rejection/given/RejectionEnrichmentConsumer.java index 4b753bdca0b..d65867b3519 100644 --- a/server/src/test/java/io/spine/server/rejection/given/RejectionEnrichmentConsumer.java +++ b/server/src/test/java/io/spine/server/rejection/given/RejectionEnrichmentConsumer.java @@ -25,7 +25,7 @@ import io.spine.server.rejection.RejectionSubscriber; import io.spine.test.rejection.ProjectRejections.InvalidProjectName; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A rejection subscriber which listens to {@link InvalidProjectName} and remembers diff --git a/server/src/test/java/io/spine/server/rejection/given/RejectionReactorMethodTestEnv.java b/server/src/test/java/io/spine/server/rejection/given/RejectionReactorMethodTestEnv.java index 2598f67af69..f14f05df1e8 100644 --- a/server/src/test/java/io/spine/server/rejection/given/RejectionReactorMethodTestEnv.java +++ b/server/src/test/java/io/spine/server/rejection/given/RejectionReactorMethodTestEnv.java @@ -27,7 +27,7 @@ import io.spine.test.reflect.ReflectRejections.InvalidProjectName; import io.spine.test.rejection.command.RjUpdateProjectName; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Method; /** diff --git a/server/src/test/java/io/spine/server/rejection/given/RejectionSubscriberMethodTestEnv.java b/server/src/test/java/io/spine/server/rejection/given/RejectionSubscriberMethodTestEnv.java index 3da958ebe43..1ad8004696d 100644 --- a/server/src/test/java/io/spine/server/rejection/given/RejectionSubscriberMethodTestEnv.java +++ b/server/src/test/java/io/spine/server/rejection/given/RejectionSubscriberMethodTestEnv.java @@ -25,7 +25,7 @@ import io.spine.test.reflect.ReflectRejections.InvalidProjectName; import io.spine.test.rejection.command.RjUpdateProjectName; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Method; /** diff --git a/server/src/test/java/io/spine/server/stand/StandShould.java b/server/src/test/java/io/spine/server/stand/StandShould.java index 45bfc0c6786..7dfb087865d 100644 --- a/server/src/test/java/io/spine/server/stand/StandShould.java +++ b/server/src/test/java/io/spine/server/stand/StandShould.java @@ -75,7 +75,7 @@ import org.mockito.ArgumentMatcher; import org.mockito.ArgumentMatchers; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Arrays; import java.util.Collection; import java.util.Collections; diff --git a/server/src/test/java/io/spine/server/stand/StandStorageShould.java b/server/src/test/java/io/spine/server/stand/StandStorageShould.java index 8b8dbaa3819..0ba3b2c8631 100644 --- a/server/src/test/java/io/spine/server/stand/StandStorageShould.java +++ b/server/src/test/java/io/spine/server/stand/StandStorageShould.java @@ -40,7 +40,7 @@ import io.spine.type.TypeUrl; import org.junit.Test; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; diff --git a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java index 5486ae67540..20a7171f528 100644 --- a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java +++ b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java @@ -60,7 +60,7 @@ import org.junit.Test; import org.mockito.ArgumentMatcher; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; diff --git a/testutil-server/src/main/java/io/spine/server/TestEventClasses.java b/testutil-server/src/main/java/io/spine/server/TestEventClasses.java index 9f2c6b96c81..167e8cad257 100644 --- a/testutil-server/src/main/java/io/spine/server/TestEventClasses.java +++ b/testutil-server/src/main/java/io/spine/server/TestEventClasses.java @@ -25,7 +25,7 @@ import io.spine.core.Event; import io.spine.core.EventClass; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import static com.google.common.collect.Collections2.transform; diff --git a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateBuilder.java b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateBuilder.java index 8e3f2261c7a..04386a691e7 100644 --- a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateBuilder.java @@ -21,6 +21,7 @@ package io.spine.server.aggregate; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.Version; import io.spine.server.entity.EntityBuilder; @@ -46,6 +47,7 @@ public AggregateBuilder() { // Have the constructor for easier location of usages. } + @CanIgnoreReturnValue @Override public AggregateBuilder setResultClass(Class entityClass) { super.setResultClass(entityClass); diff --git a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateCommandTest.java b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateCommandTest.java index 2838bcac273..9e056952992 100644 --- a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateCommandTest.java +++ b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateCommandTest.java @@ -25,7 +25,7 @@ import io.spine.client.ActorRequestFactory; import io.spine.server.command.CommandTest; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * An abstract base for test suites testing aggregate commands. diff --git a/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartBuilder.java b/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartBuilder.java index 8e0d3c60249..189e8430825 100644 --- a/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartBuilder.java @@ -20,6 +20,7 @@ package io.spine.server.aggregate; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.server.entity.EntityBuilder; import io.spine.server.entity.EntityClass; @@ -53,6 +54,7 @@ public EntityBuilder withRoot(R aggregateRoot) { return this; } + @CanIgnoreReturnValue @Override public AggregatePartBuilder setResultClass(Class entityClass) { super.setResultClass(entityClass); diff --git a/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartCommandTest.java b/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartCommandTest.java index 9109b7b0485..07fe783eec9 100644 --- a/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartCommandTest.java +++ b/testutil-server/src/main/java/io/spine/server/aggregate/AggregatePartCommandTest.java @@ -25,7 +25,7 @@ import io.spine.client.ActorRequestFactory; import io.spine.server.command.CommandTest; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; /** * An abstract base for test suites testing aggregate part commands. diff --git a/testutil-server/src/main/java/io/spine/server/command/CommandTest.java b/testutil-server/src/main/java/io/spine/server/command/CommandTest.java index 3a9e4670af8..92a6c937b87 100644 --- a/testutil-server/src/main/java/io/spine/server/command/CommandTest.java +++ b/testutil-server/src/main/java/io/spine/server/command/CommandTest.java @@ -29,7 +29,7 @@ import io.spine.core.Command; import io.spine.core.CommandContext; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/testutil-server/src/main/java/io/spine/server/command/TestEventFactory.java b/testutil-server/src/main/java/io/spine/server/command/TestEventFactory.java index 1d96fbc8437..4666bc5ed4f 100644 --- a/testutil-server/src/main/java/io/spine/server/command/TestEventFactory.java +++ b/testutil-server/src/main/java/io/spine/server/command/TestEventFactory.java @@ -31,7 +31,7 @@ import io.spine.core.Version; import io.spine.server.event.EventFactory; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static io.spine.protobuf.AnyPacker.pack; diff --git a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java index be2c4d9f323..1bace40ac2d 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java @@ -21,6 +21,7 @@ package io.spine.server.entity; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import com.google.protobuf.Timestamp; import io.spine.base.Identifier; @@ -28,7 +29,7 @@ import io.spine.core.Versions; import io.spine.test.ReflectiveBuilder; -import javax.annotation.Nullable; +import org.checkerframework.checker.nullness.qual.Nullable; import java.lang.reflect.Constructor; import static com.google.common.base.Preconditions.checkNotNull; @@ -51,23 +52,19 @@ public class EntityBuilder, I, S exten * *

Is null until {@link #setResultClass(Class)} is called. */ - @Nullable - private EntityClass entityClass; + private @Nullable EntityClass entityClass; /** The ID of the entity. If not set, a value default to the type will be used. */ - @Nullable - private I id; + private @Nullable I id; /** The entity state. If not set, a default instance will be used. */ - @Nullable - private S state; + private @Nullable S state; /** The entity version. Or zero if not set. */ private int version; /** The entity timestamp or default {@code Timestamp} if not set. */ - @Nullable - private Timestamp whenModified; + private @Nullable Timestamp whenModified; /** * Creates new instance of the builder. @@ -77,7 +74,7 @@ public EntityBuilder() { // Have the constructor for finding usages easier. } - @SuppressWarnings("CheckReturnValue") // calling builder method + @CanIgnoreReturnValue @Override public EntityBuilder setResultClass(Class entityClass) { super.setResultClass(entityClass); diff --git a/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerBuilder.java b/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerBuilder.java index c2c9559dca3..b31c7da040b 100644 --- a/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerBuilder.java @@ -21,6 +21,7 @@ package io.spine.server.procman; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.Version; import io.spine.server.entity.EntityBuilder; @@ -42,12 +43,13 @@ public class ProcessManagerBuilder

, B extends ValidatingBuilder> extends EntityBuilder { + /** Creates new instance. */ public ProcessManagerBuilder() { super(); // Have the constructor for easier location of usages. } - @SuppressWarnings("MethodDoesntCallSuperMethod") // fix IDEA bug + @CanIgnoreReturnValue @Override public ProcessManagerBuilder setResultClass(Class

entityClass) { super.setResultClass(entityClass); @@ -56,6 +58,7 @@ public ProcessManagerBuilder setResultClass(Class

entityClass) { @Override protected void setState(P result, S state, Version version) { - PmTransaction.startWith(result, state, version).commit(); + PmTransaction.startWith(result, state, version) + .commit(); } } diff --git a/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerDispatcher.java b/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerDispatcher.java index 16597ebeb56..596b7f7cf37 100644 --- a/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerDispatcher.java +++ b/testutil-server/src/main/java/io/spine/server/procman/ProcessManagerDispatcher.java @@ -76,6 +76,7 @@ public static List dispatch(ProcessManager pm, EventEnvelope eve /** * Dispatches a {@linkplain RejectionEnvelope rejection} to the given {@code ProcessManager}. */ + @SuppressWarnings("CheckReturnValue") // OK to ignore events in this test utility. public static void dispatch(ProcessManager pm, RejectionEnvelope rejection) { checkNotNull(pm); checkNotNull(rejection); diff --git a/testutil-server/src/main/java/io/spine/server/projection/ProjectionBuilder.java b/testutil-server/src/main/java/io/spine/server/projection/ProjectionBuilder.java index 1d2164046d3..0178233c390 100644 --- a/testutil-server/src/main/java/io/spine/server/projection/ProjectionBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/projection/ProjectionBuilder.java @@ -20,6 +20,7 @@ package io.spine.server.projection; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.Version; import io.spine.server.entity.EntityBuilder; @@ -40,11 +41,13 @@ public class ProjectionBuilder

, B extends ValidatingBuilder> extends EntityBuilder { + /** Creates new instance. */ public ProjectionBuilder() { super(); // Have the constructor for easier location of usages. } + @CanIgnoreReturnValue @Override public ProjectionBuilder setResultClass(Class

entityClass) { super.setResultClass(entityClass); From d519c98c4b29a0ab0c92a4c675f80a9982421583 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 24 May 2018 17:50:52 +0300 Subject: [PATCH 08/53] Fix using generic param as qualifier --- server/src/test/java/io/spine/testdata/Sample.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/test/java/io/spine/testdata/Sample.java b/server/src/test/java/io/spine/testdata/Sample.java index 7f00862a780..c2c51c80ab3 100644 --- a/server/src/test/java/io/spine/testdata/Sample.java +++ b/server/src/test/java/io/spine/testdata/Sample.java @@ -20,6 +20,7 @@ package io.spine.testdata; +import com.google.common.base.Charsets; import com.google.protobuf.Any; import com.google.protobuf.ByteString; import com.google.protobuf.Descriptors; @@ -112,7 +113,7 @@ public static M messageOfType(Class clazz) { return result; } - final M.Builder builder = builderForType(clazz); + final Message.Builder builder = builderForType(clazz); @SuppressWarnings("unchecked") // Checked cast final M result = (M) builder.build(); @@ -154,7 +155,7 @@ private static Object valueFor(FieldDescriptor field) { case STRING: final byte[] bytes = new byte[8]; random.nextBytes(bytes); - return new String(bytes); + return new String(bytes, Charsets.UTF_8); case BYTE_STRING: final byte[] bytesPrimitive = new byte[8]; random.nextBytes(bytesPrimitive); From a3c5013d656bafcdfff23d433fe204eb849d3081 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 24 May 2018 19:02:47 +0300 Subject: [PATCH 09/53] Handle return values --- .../io/spine/core/EventPredicatesShould.java | 21 +++++++++----- .../test/java/io/spine/core/EventsShould.java | 13 +++++++-- .../io/spine/server/bus/BusBuilderShould.java | 1 + .../commandbus/CommandBusBuilderShould.java | 29 ++++++++++++------- .../commandbus/CommandSchedulingShould.java | 4 +++ .../CommandDispatcherRegistryTestEnv.java | 3 ++ .../event/given/CommandHandlerTestEnv.java | 24 +++++++-------- .../tenant/TenantAwareFunction0Should.java | 11 +++++-- .../tenant/TenantAwareOperationShould.java | 13 +++++++-- 9 files changed, 80 insertions(+), 39 deletions(-) diff --git a/server/src/test/java/io/spine/core/EventPredicatesShould.java b/server/src/test/java/io/spine/core/EventPredicatesShould.java index 20ed2bbfafd..b96d13c7631 100644 --- a/server/src/test/java/io/spine/core/EventPredicatesShould.java +++ b/server/src/test/java/io/spine/core/EventPredicatesShould.java @@ -24,7 +24,9 @@ import com.google.common.testing.NullPointerTester; import com.google.protobuf.Timestamp; import io.spine.core.given.GivenEvent; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.base.Time.getCurrentTime; import static io.spine.core.EventPredicates.isAfter; @@ -41,6 +43,9 @@ */ public class EventPredicatesShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_utility_ctor() { assertHasPrivateParameterlessCtor(EventPredicates.class); @@ -83,7 +88,7 @@ public void return_false_from_null_input_in_IsBefore_predicate() { @Test public void verify_if_an_event_is_before_another() { - final Predicate predicate = isBefore(minutesAgo(100)); + Predicate predicate = isBefore(minutesAgo(100)); assertFalse(predicate.apply(GivenEvent.occurredMinutesAgo(20))); assertTrue(predicate.apply(GivenEvent.occurredMinutesAgo(360))); } @@ -93,14 +98,16 @@ public void return_null_from_null_input_in_IsBetween_predicate() { assertFalse(isBetween(secondsAgo(5), secondsAgo(1)).apply(null)); } - @Test(expected = IllegalArgumentException.class) + @Test public void check_that_range_start_is_before_end() { + thrown.expect(IllegalArgumentException.class); isBetween(minutesAgo(2), minutesAgo(10)); } - @Test(expected = IllegalArgumentException.class) + @Test public void do_not_accept_zero_length_time_range() { - final Timestamp timestamp = minutesAgo(5); + Timestamp timestamp = minutesAgo(5); + thrown.expect(IllegalArgumentException.class); isBetween(timestamp, timestamp); } @@ -108,10 +115,8 @@ public void do_not_accept_zero_length_time_range() { public void verify_if_an_event_is_within_time_range() { final Event event = GivenEvent.occurredMinutesAgo(5); - assertTrue(isBetween(minutesAgo(10), minutesAgo(1)) - .apply(event)); + assertTrue(isBetween(minutesAgo(10), minutesAgo(1)).apply(event)); - assertFalse(isBetween(minutesAgo(2), minutesAgo(1)) - .apply(event)); + assertFalse(isBetween(minutesAgo(2), minutesAgo(1)).apply(event)); } } diff --git a/server/src/test/java/io/spine/core/EventsShould.java b/server/src/test/java/io/spine/core/EventsShould.java index 1f5463f5b28..43a6025d89b 100644 --- a/server/src/test/java/io/spine/core/EventsShould.java +++ b/server/src/test/java/io/spine/core/EventsShould.java @@ -35,7 +35,9 @@ import io.spine.test.Tests; import io.spine.type.TypeName; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Comparator; import java.util.List; @@ -81,6 +83,9 @@ public class EventsShould { @SuppressWarnings("MagicNumber") private final DoubleValue doubleValue = toMessage(10.1); + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { final TestActorRequestFactory requestFactory = @@ -126,7 +131,7 @@ public void have_event_comparator() { final Comparator comparator = Events.eventComparator(); assertTrue(comparator.compare(event1, event2) < 0); assertTrue(comparator.compare(event2, event1) > 0); - assertTrue(comparator.compare(event1, event1) == 0); + assertEquals(0, comparator.compare(event1, event1)); } @Test @@ -178,8 +183,9 @@ public void provide_EventId_stringifier() { assertEquals(id, convertedBack); } - @Test(expected = IllegalArgumentException.class) + @Test public void reject_empty_event_id() { + thrown.expect(IllegalArgumentException.class); checkValid(EventId.getDefaultInstance()); } @@ -219,8 +225,9 @@ public void provide_empty_Iterable() { } } - @Test(expected = NullPointerException.class) + @Test public void throw_NPE_when_getting_tenant_id_of_null_event() { + thrown.expect(NullPointerException.class); Events.getTenantId(Tests.nullRef()); } diff --git a/server/src/test/java/io/spine/server/bus/BusBuilderShould.java b/server/src/test/java/io/spine/server/bus/BusBuilderShould.java index fb2710c9073..9affac9ff95 100644 --- a/server/src/test/java/io/spine/server/bus/BusBuilderShould.java +++ b/server/src/test/java/io/spine/server/bus/BusBuilderShould.java @@ -67,6 +67,7 @@ public void allow_removing_filter() { .contains(filter)); } + @SuppressWarnings("CheckReturnValue") // calling builder @Test public void preserve_filters_order() { @SuppressWarnings("unchecked") diff --git a/server/src/test/java/io/spine/server/commandbus/CommandBusBuilderShould.java b/server/src/test/java/io/spine/server/commandbus/CommandBusBuilderShould.java index bc388337ead..6bd76e35155 100644 --- a/server/src/test/java/io/spine/server/commandbus/CommandBusBuilderShould.java +++ b/server/src/test/java/io/spine/server/commandbus/CommandBusBuilderShould.java @@ -32,9 +32,12 @@ import io.spine.server.transport.memory.InMemoryTransportFactory; import io.spine.test.Tests; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.server.BoundedContext.newName; +import static io.spine.server.tenant.TenantAwareTest.createTenantIndex; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -45,13 +48,13 @@ * @author Alexander Yevsyukov */ @SuppressWarnings("ConstantConditions") -public class CommandBusBuilderShould extends BusBuilderShould { +public class CommandBusBuilderShould + extends BusBuilderShould { private CommandStore commandStore; - private TransportFactory transportFactory; + @Rule + public ExpectedException thrown = ExpectedException.none(); @Override protected CommandBus.Builder builder() { @@ -61,22 +64,22 @@ protected CommandBus.Builder builder() { @Before public void setUp() { final boolean multitenant = true; - final InMemoryStorageFactory storageFactory = + InMemoryStorageFactory storageFactory = InMemoryStorageFactory.newInstance(newName(getClass().getSimpleName()), multitenant); - final TenantIndex tenantIndex = - TenantAwareTest.createTenantIndex(multitenant, storageFactory); + TenantIndex tenantIndex = createTenantIndex(multitenant, storageFactory); commandStore = new CommandStore(storageFactory, tenantIndex); - transportFactory = InMemoryTransportFactory.newInstance(); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_CommandStore() { - builder().setCommandStore(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setCommandStore(Tests.nullRef()); } - @Test(expected = IllegalStateException.class) + @Test public void not_allow_to_omit_setting_CommandStore() { + thrown.expect(IllegalStateException.class); CommandBus.newBuilder().build(); } @@ -94,6 +97,8 @@ public void allow_to_specify_command_scheduler() { final CommandBus.Builder builder = builder().setCommandStore(commandStore) .setCommandScheduler(expectedScheduler); + assertTrue(builder.getCommandScheduler() + .isPresent()); assertEquals(expectedScheduler, builder.getCommandScheduler() .get()); @@ -110,6 +115,8 @@ public void allow_to_specify_rejeciton_bus() { final CommandBus.Builder builder = builder().setCommandStore(commandStore) .setRejectionBus(expectedRejectionBus); + assertTrue(builder.getRejectionBus() + .isPresent()); assertEquals(expectedRejectionBus, builder.getRejectionBus() .get()); } diff --git a/server/src/test/java/io/spine/server/commandbus/CommandSchedulingShould.java b/server/src/test/java/io/spine/server/commandbus/CommandSchedulingShould.java index ccf6cfd0d74..bac77ff0e49 100644 --- a/server/src/test/java/io/spine/server/commandbus/CommandSchedulingShould.java +++ b/server/src/test/java/io/spine/server/commandbus/CommandSchedulingShould.java @@ -117,6 +117,8 @@ public void reschedule_commands_from_storage() { } } + @SuppressWarnings("CheckReturnValue") + // OK to ignore stored command for the purpose of this test. @Test public void reschedule_commands_from_storage_in_parallel_on_build_if_thread_spawning_allowed() { final String mainThreadName = Thread.currentThread().getName(); @@ -151,6 +153,8 @@ public void reschedule_commands_from_storage_in_parallel_on_build_if_thread_spaw assertNotEquals(mainThreadName, actualThreadName); } + @SuppressWarnings("CheckReturnValue") + // OK to ignore stored command for the purpose of this test. @Test public void reschedule_commands_from_storage_synchronously_on_build_if_thread_spawning_NOT_allowed() { final String mainThreadName = Thread.currentThread().getName(); diff --git a/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java b/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java index a996c5a39e2..21e261fc668 100644 --- a/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java +++ b/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java @@ -87,6 +87,7 @@ public void on(CmdProjectCreated event) { handleProjectCreated(event.getProjectId()); } + @SuppressWarnings("CheckReturnValue") // calling builder private void handleProjectCreated(ProjectId projectId) { final Project newState = getState().toBuilder() .setId(projectId) @@ -103,6 +104,7 @@ public void on(CmdTaskAdded event) { handleTaskAdded(task); } + @SuppressWarnings("CheckReturnValue") // calling builder private void handleTaskAdded(Task task) { final Project newState = getState().toBuilder() .addTask(task) @@ -117,6 +119,7 @@ public void on(CmdProjectStarted event) { handleProjectStarted(); } + @SuppressWarnings("CheckReturnValue") // calling builder private void handleProjectStarted() { final Project newState = getState().toBuilder() .setStatus(Project.Status.STARTED) diff --git a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java index 096ba42e525..dc3351251f5 100644 --- a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.protobuf.Message; import com.google.protobuf.StringValue; import io.spine.core.Command; @@ -59,7 +60,7 @@ private CommandHandlerTestEnv() { public static class EventCatcher implements EventDispatcher { - private final List dispatched = new LinkedList<>(); + private final List dispatched = Lists.newLinkedList(); @Override public Set getMessageClasses() { @@ -93,10 +94,8 @@ public static class TestCommandHandler extends CommandHandler { private final CommandHistory commandsHandled = new CommandHistory(); - @Nullable - private CommandEnvelope lastErrorEnvelope; - @Nullable - private RuntimeException lastException; + private @Nullable CommandEnvelope lastErrorEnvelope; + private @Nullable RuntimeException lastException; public TestCommandHandler(EventBus eventBus) { super(eventBus); @@ -106,8 +105,10 @@ public void assertHandled(Command expected) { commandsHandled.assertHandled(expected); } + @SuppressWarnings("CheckReturnValue") + // can ignore the returned ID of the command handler in these tests public void handle(Command cmd) { - final CommandEnvelope commandEnvelope = CommandEnvelope.of(cmd); + CommandEnvelope commandEnvelope = CommandEnvelope.of(cmd); dispatch(commandEnvelope); } @@ -146,19 +147,18 @@ public void onError(CommandEnvelope envelope, RuntimeException exception) { lastException = exception; } - @Nullable - public CommandEnvelope getLastErrorEnvelope() { + public @Nullable CommandEnvelope getLastErrorEnvelope() { return lastErrorEnvelope; } - @Nullable - public RuntimeException getLastException() { + public @Nullable RuntimeException getLastException() { return lastException; } private static ImmutableList createEventsOnStartProjectCmd() { - final ImmutableList.Builder builder = ImmutableList.builder(); - builder.add(CmdProjectStarted.getDefaultInstance(), StringValue.getDefaultInstance()); + ImmutableList.Builder builder = ImmutableList.builder() + .add(CmdProjectStarted.getDefaultInstance(), + StringValue.getDefaultInstance()); return builder.build(); } } diff --git a/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java b/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java index 7a847eca243..0fc790dc45c 100644 --- a/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java +++ b/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java @@ -22,7 +22,9 @@ import com.google.protobuf.Timestamp; import io.spine.base.Time; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.core.given.GivenTenantId.newUuid; @@ -31,7 +33,10 @@ */ public class TenantAwareFunction0Should { - @Test(expected = IllegalStateException.class) + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test public void require_current_tenant_set() { final TenantAwareFunction0 whichTime = new TenantAwareFunction0() { @Override @@ -40,14 +45,16 @@ public Timestamp apply() { } }; - // This should pass. + // This should pass since we're executing the operation with the current tenant ID set. new TenantAwareOperation(newUuid()) { + @SuppressWarnings("CheckReturnValue") // can ignore in this test. @Override public void run() { whichTime.execute(); } }.execute(); + thrown.expect(IllegalStateException.class); // This should fail. whichTime.execute(); } diff --git a/server/src/test/java/io/spine/server/tenant/TenantAwareOperationShould.java b/server/src/test/java/io/spine/server/tenant/TenantAwareOperationShould.java index 8287559e8c9..c4d8d5e08b5 100644 --- a/server/src/test/java/io/spine/server/tenant/TenantAwareOperationShould.java +++ b/server/src/test/java/io/spine/server/tenant/TenantAwareOperationShould.java @@ -22,7 +22,9 @@ import io.spine.core.TenantId; import io.spine.test.Tests; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.core.given.GivenTenantId.newUuid; import static org.junit.Assert.assertEquals; @@ -35,9 +37,13 @@ // OK for the tests. We set right before we get(). public class TenantAwareOperationShould { - @Test(expected = NullPointerException.class) + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test public void do_not_accept_null_tenant() { - createOperation(Tests.nullRef()); + thrown.expect(NullPointerException.class); + createOperation(Tests.nullRef()); } @Test @@ -105,10 +111,11 @@ public void create_instance_for_non_command_execution_context() { assertEquals(tenant, getTenantFromRun(op)); } - @Test(expected = IllegalStateException.class) + @Test public void do_not_allow_creating_instance_in_non_command_execution_without_current_tenant() { CurrentTenant.clear(); + thrown.expect(IllegalStateException.class); // This should fail. createOperation(); } From 9b3849c2da43dc5163a6c0a50d3db08cc47c506f Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Sun, 27 May 2018 01:07:14 +0300 Subject: [PATCH 10/53] Handle ignored return values Also bump Guava -> `25.1-jre` --- .idea/inspectionProfiles/Project_Default.xml | 6 +- ext.gradle | 5 +- .../entity/storage/ColumnTypeRegistry.java | 7 +- .../spine/server/entity/storage/Columns.java | 43 +-- .../entity/storage/EntityColumnCache.java | 13 +- .../server/rejection/RejectionSubscriber.java | 2 +- .../io/spine/server/route/CommandRouting.java | 3 + .../io/spine/server/route/EventRouting.java | 4 + .../spine/server/route/RejectionRouting.java | 4 + .../spine/server/transport/GrpcContainer.java | 34 ++- .../io/spine/server/QueryServiceShould.java | 14 +- .../spine/server/bc/BoundedContextShould.java | 131 +++++---- .../bc/given/BoundedContextTestEnv.java | 16 +- .../server/entity/AbstractEntityShould.java | 12 +- .../server/entity/EntityEqualsShould.java | 18 +- .../io/spine/server/entity/EntityShould.java | 1 + .../spine/server/entity/FieldMasksShould.java | 88 +++--- .../entity/RecordBasedRepositoryShould.java | 255 +++++++++--------- .../spine/server/entity/RepositoryShould.java | 33 +-- .../server/entity/TransactionShould.java | 64 +++-- .../server/entity/VisibilityGuardShould.java | 17 +- .../entity/storage/ColumnReaderShould.java | 50 ++-- .../server/entity/storage/ColumnShould.java | 107 ++++---- .../storage/ColumnTypeRegistryShould.java | 52 ++-- .../server/entity/storage/ColumnsShould.java | 95 ++++--- .../CompositeQueryParameterShould.java | 104 +++---- .../storage/EntityColumnCacheShould.java | 36 +-- .../entity/storage/EntityQueriesShould.java | 160 ++++++----- .../EntityRecordWithColumnsShould.java | 102 +++---- .../server/route/EventRoutingShould.java | 1 + .../server/route/given/switchman/Log.java | 7 +- .../route/given/switchman/Switchman.java | 1 + .../given/switchman/SwitchmanBureau.java | 2 + .../server/tuple/EitherOfFiveShould.java | 53 ++-- .../server/tuple/EitherOfFourShould.java | 41 ++- .../server/tuple/EitherOfThreeShould.java | 23 +- .../spine/server/tuple/EitherOfTwoShould.java | 11 +- .../io/spine/server/tuple/PairShould.java | 17 +- .../io/spine/server/tuple/TripletShould.java | 14 +- 39 files changed, 959 insertions(+), 687 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 376fa9a7645..ce135191ae6 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -190,9 +190,6 @@ - - + + +

By using predefined {@linkplain EntityColumn entity columns} the process of * {@linkplain ColumnReader#readColumns() obtaining columns} from the given {@link Entity} class * can be skipped. * - *

This method will return {@linkplain Collections#emptyMap() empty map} for {@link Entity} classes - * that are non-public or cannot be subjected to column extraction for some other reason. + *

This method will return {@linkplain Collections#emptyMap() empty map} for + * {@link Entity} classes that are non-public or cannot be subjected to column extraction + * for some other reason. * - * @param entity an {@link Entity} to get the {@linkplain EntityColumn column} values from - * @param entityColumns {@linkplain EntityColumn entity columns} which values should be extracted - * @param the type of the {@link Entity} + * @param entity + * an {@link Entity} to get the {@linkplain EntityColumn column} values from + * @param entityColumns + * {@linkplain EntityColumn entity columns} which values should be extracted + * @param + * the type of the {@link Entity} * @return a {@code Map} of the column {@linkplain EntityColumn#getStoredName() * names for storing} to their {@linkplain MemoizedValue memoized values} * @see MemoizedValue @@ -130,7 +143,7 @@ static EntityColumn findColumn(Class entityClass, String colum checkNotNull(entity); checkNotNull(entityColumns); - final ColumnValueExtractor columnValueExtractor = ColumnValueExtractor.create(entity, entityColumns); + ColumnValueExtractor columnValueExtractor = create(entity, entityColumns); return columnValueExtractor.extractColumnValues(); } } diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumnCache.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumnCache.java index fd2d5523eec..5d8f277aa79 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumnCache.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumnCache.java @@ -29,8 +29,8 @@ import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; -import static io.spine.validate.Validate.checkNotEmptyOrBlank; -import static java.lang.String.format; +import static io.spine.server.entity.storage.Columns.checkColumnName; +import static io.spine.server.entity.storage.Columns.couldNotFindColumn; import static java.util.Collections.synchronizedMap; /** @@ -104,17 +104,14 @@ public static EntityColumnCache initializeFor(Class entityClas * @throws IllegalArgumentException if the {@link EntityColumn} is not found */ public EntityColumn findColumn(String columnName) { - checkNotEmptyOrBlank(columnName, "entity column name"); + checkColumnName(columnName); ensureColumnsCached(); - final EntityColumn entityColumn = entityColumnData.get(columnName); + EntityColumn entityColumn = entityColumnData.get(columnName); if (entityColumn == null) { - throw new IllegalArgumentException( - format("Could not find an EntityColumn description for %s.%s.", - entityClass.getCanonicalName(), - columnName)); + throw couldNotFindColumn(entityClass, columnName); } return entityColumn; } diff --git a/server/src/main/java/io/spine/server/rejection/RejectionSubscriber.java b/server/src/main/java/io/spine/server/rejection/RejectionSubscriber.java index 2e8fef5dbbd..507ba23babe 100644 --- a/server/src/main/java/io/spine/server/rejection/RejectionSubscriber.java +++ b/server/src/main/java/io/spine/server/rejection/RejectionSubscriber.java @@ -61,7 +61,7 @@ public class RejectionSubscriber implements RejectionDispatcher { * the subscriber, or empty set if dispatching failed */ @Override - public Set dispatch(final RejectionEnvelope envelope) { + public Set dispatch(RejectionEnvelope envelope) { final Command originCommand = envelope.getOuterObject() .getContext() .getCommand(); diff --git a/server/src/main/java/io/spine/server/route/CommandRouting.java b/server/src/main/java/io/spine/server/route/CommandRouting.java index 325f465d452..d974e67e2a0 100644 --- a/server/src/main/java/io/spine/server/route/CommandRouting.java +++ b/server/src/main/java/io/spine/server/route/CommandRouting.java @@ -21,6 +21,7 @@ package io.spine.server.route; import com.google.common.base.Optional; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.CommandClass; import io.spine.core.CommandContext; @@ -72,6 +73,7 @@ public final CommandRoute getDefault() { * @param newDefault the new route to be used as default * @return {@code this} to allow chained calls when configuring the routing */ + @CanIgnoreReturnValue public CommandRouting replaceDefault(CommandRoute newDefault) { checkNotNull(newDefault); return (CommandRouting) super.replaceDefault(newDefault); @@ -94,6 +96,7 @@ public CommandRouting replaceDefault(CommandRoute newDefault) { * @return {@code this} to allow chained calls when configuring the routing * @throws IllegalStateException if the route for this command class is already set */ + @CanIgnoreReturnValue public CommandRouting route(Class commandClass, CommandRoute via) throws IllegalStateException { diff --git a/server/src/main/java/io/spine/server/route/EventRouting.java b/server/src/main/java/io/spine/server/route/EventRouting.java index 94a15381d56..e872319cc82 100644 --- a/server/src/main/java/io/spine/server/route/EventRouting.java +++ b/server/src/main/java/io/spine/server/route/EventRouting.java @@ -21,6 +21,7 @@ package io.spine.server.route; import com.google.common.base.Optional; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.EventClass; import io.spine.core.EventContext; @@ -63,6 +64,7 @@ private EventRouting(EventRoute defaultRoute) { * @param the type of entity identifiers returned by new routing * @return new routing instance */ + @CanIgnoreReturnValue public static EventRouting withDefault(EventRoute defaultRoute) { checkNotNull(defaultRoute); return new EventRouting<>(defaultRoute); @@ -84,6 +86,7 @@ public final EventRoute getDefault() { * @param newDefault the new route to be used as default * @return {@code this} to allow chained calls when configuring the routing */ + @CanIgnoreReturnValue public EventRouting replaceDefault(EventRoute newDefault) { return (EventRouting) super.replaceDefault(newDefault); } @@ -108,6 +111,7 @@ public EventRouting replaceDefault(EventRoute newDefault) { * @return {@code this} to allow chained calls when configuring the routing * @throws IllegalStateException if the route for this event class is already set */ + @CanIgnoreReturnValue public EventRouting route(Class eventClass, EventRoute via) throws IllegalStateException { @SuppressWarnings("unchecked") // The cast is required to adapt the type to internal API. diff --git a/server/src/main/java/io/spine/server/route/RejectionRouting.java b/server/src/main/java/io/spine/server/route/RejectionRouting.java index e760b1aa7d5..b3f5aaa86fe 100644 --- a/server/src/main/java/io/spine/server/route/RejectionRouting.java +++ b/server/src/main/java/io/spine/server/route/RejectionRouting.java @@ -21,6 +21,7 @@ package io.spine.server.route; import com.google.common.base.Optional; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.RejectionClass; import io.spine.core.RejectionContext; @@ -57,6 +58,7 @@ private RejectionRouting(Route> defaultRoute) * @param defaultRoute * the route to use if a custom one is not {@linkplain #route(Class, RejectionRoute) set} */ + @CanIgnoreReturnValue public static RejectionRouting withDefault(RejectionRoute defaultRoute) { checkNotNull(defaultRoute); return new RejectionRouting<>(defaultRoute); @@ -78,6 +80,7 @@ public final RejectionRoute getDefault() { * @param newDefault the new route to be used as default * @return {@code this} to allow chained calls when configuring the routing */ + @CanIgnoreReturnValue public RejectionRouting replaceDefault(RejectionRoute newDefault) { return (RejectionRouting) super.replaceDefault(newDefault); } @@ -102,6 +105,7 @@ public RejectionRouting replaceDefault(RejectionRoute newDefault) * @return {@code this} to allow chained calls when configuring the routing * @throws IllegalStateException if the route for this rejection class is already set */ + @CanIgnoreReturnValue public RejectionRouting route(Class rejectionClass, RejectionRoute via) throws IllegalStateException { diff --git a/server/src/main/java/io/spine/server/transport/GrpcContainer.java b/server/src/main/java/io/spine/server/transport/GrpcContainer.java index 5a503e372ae..193e1217da3 100644 --- a/server/src/main/java/io/spine/server/transport/GrpcContainer.java +++ b/server/src/main/java/io/spine/server/transport/GrpcContainer.java @@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.grpc.BindableService; import io.grpc.Server; import io.grpc.ServerBuilder; @@ -51,8 +52,7 @@ public class GrpcContainer { private final int port; private final ImmutableSet services; - @Nullable - private Server grpcServer; + private @Nullable Server grpcServer; public static Builder newBuilder() { return new Builder(); @@ -168,25 +168,21 @@ Server createGrpcServer() { return builder.build(); } + // Use stderr here since the logger may have been reset by its JVM shutdown hook. + @SuppressWarnings("UseOfSystemOutOrSystemErr") @VisibleForTesting Runnable getOnShutdownCallback() { - return new Runnable() { - // Use stderr here since the logger may have been reset by its JVM shutdown hook. - @SuppressWarnings("UseOfSystemOutOrSystemErr") - @Override - public void run() { - final String serverClass = GrpcContainer.this.getClass() - .getName(); - try { - if (!isShutdown()) { - System.err.println("Shutting down " + - serverClass + " since JVM is shutting down..."); - shutdown(); - System.err.println(serverClass + " shut down."); - } - } catch (RuntimeException e) { - e.printStackTrace(System.err); + return () -> { + final String serverClass = getClass().getName(); + try { + if (!isShutdown()) { + System.err.println("Shutting down " + + serverClass + " since JVM is shutting down..."); + shutdown(); + System.err.println(serverClass + " shut down."); } + } catch (RuntimeException e) { + e.printStackTrace(System.err); } }; } @@ -205,11 +201,13 @@ public int getPort() { return this.port; } + @CanIgnoreReturnValue public Builder addService(BindableService service) { serviceDefinitions.add(service.bindService()); return this; } + @CanIgnoreReturnValue public Builder removeService(ServerServiceDefinition service) { serviceDefinitions.remove(service); return this; diff --git a/server/src/test/java/io/spine/server/QueryServiceShould.java b/server/src/test/java/io/spine/server/QueryServiceShould.java index c37ca94ab32..c444f283e40 100644 --- a/server/src/test/java/io/spine/server/QueryServiceShould.java +++ b/server/src/test/java/io/spine/server/QueryServiceShould.java @@ -39,7 +39,9 @@ import io.spine.test.projection.ProjectVBuilder; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Set; @@ -72,6 +74,9 @@ public class QueryServiceShould { StreamObservers.memoizingObserver(); private ProjectDetailsRepository projectDetailsRepository; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { ModelTests.clearModel(); @@ -141,20 +146,23 @@ public void dispatch_queries_to_proper_bounded_context() { verify(customersContext.getStand(), never()).execute(query, responseObserver); } - @Test(expected = IllegalStateException.class) + @Test public void fail_to_create_with_removed_bounded_context_from_builder() { final BoundedContext boundedContext = BoundedContext.newBuilder() .build(); final QueryService.Builder builder = QueryService.newBuilder(); + + thrown.expect(IllegalStateException.class); builder.add(boundedContext) .remove(boundedContext) .build(); } @SuppressWarnings("ResultOfMethodCallIgnored") - @Test(expected = IllegalStateException.class) + @Test public void fail_to_create_with_no_bounded_context() { + thrown.expect(IllegalStateException.class); QueryService.newBuilder() .build(); } @@ -207,7 +215,7 @@ public BoundedContextName getBoundedContextName() { private static class ProjectDetails extends Projection { - public ProjectDetails(ProjectId id) { + private ProjectDetails(ProjectId id) { super(id); } diff --git a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java index e63561e411d..5e13c9a20ef 100644 --- a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java +++ b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java @@ -50,7 +50,9 @@ import io.spine.test.bc.event.BcProjectCreated; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.lang.reflect.Field; import java.util.Map; @@ -75,9 +77,9 @@ /** * Messages used in this test suite are defined in: *

* * @author Alexander Litus @@ -97,6 +99,47 @@ public class BoundedContextShould { private boolean handlersRegistered = false; + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static Object getObjectFromNestedEnumField(String fullClassName, String fieldName) { + Object result = null; + try { + final Class aClass = Class.forName(fullClassName); + final Object enumConstant = aClass.getEnumConstants()[0]; + final Field field = aClass.getDeclaredField(fieldName); + field.setAccessible(true); + result = field.get(enumConstant); + } catch (ClassNotFoundException e) { + failMissingClass(fullClassName); + } catch (NoSuchFieldException e) { + failMissingField(fieldName); + } catch (IllegalAccessException e) { + fail(e.getMessage()); + } + assertNotNull(result); + return result; + } + + private static void failMissingClass(String fullClassName) { + fail("Class " + fullClassName + " not found."); + } + + private static void failMissingField(String fieldName) { + fail("Field " + fieldName + " should exist."); + } + + private static void injectField(Object target, String fieldName, Object valueToInject) { + try { + final Field defaultStates = target.getClass() + .getDeclaredField(fieldName); + defaultStates.setAccessible(true); + defaultStates.set(target, valueToInject); + } catch (NoSuchFieldException | IllegalAccessException ignored) { + failMissingField(fieldName); + } + } + @Before public void setUp() { ModelTests.clearModel(); @@ -108,7 +151,8 @@ public void setUp() { @After public void tearDown() throws Exception { if (handlersRegistered) { - boundedContext.getEventBus().unregister(subscriber); + boundedContext.getEventBus() + .unregister(subscriber); } boundedContext.close(); } @@ -117,7 +161,8 @@ public void tearDown() throws Exception { private void registerAll() { final ProjectAggregateRepository repo = new ProjectAggregateRepository(); boundedContext.register(repo); - boundedContext.getEventBus().register(subscriber); + boundedContext.getEventBus() + .register(subscriber); handlersRegistered = true; } @@ -148,7 +193,7 @@ public void register_AggregateRepository() { boundedContext.register(repository); } - @Test(expected = IllegalStateException.class) + @Test public void not_allow_two_aggregate_repositories_with_aggregates_with_the_same_state() { final ProjectAggregateRepository repository = new ProjectAggregateRepository(); @@ -156,6 +201,8 @@ public void not_allow_two_aggregate_repositories_with_aggregates_with_the_same_s final AnotherProjectAggregateRepository anotherRepo = new AnotherProjectAggregateRepository(); + + thrown.expect(IllegalStateException.class); boundedContext.register(anotherRepo); } @@ -182,7 +229,8 @@ public void notify_integration_event_subscriber() { boundedContext.notify(event, observer); - assertEquals(Responses.statusOk(), observer.firstResponse().getStatus()); + assertEquals(Responses.statusOk(), observer.firstResponse() + .getStatus()); assertEquals(subscriber.getHandledEvent(), msg); } @@ -203,7 +251,9 @@ public void not_notify_integration_event_subscriber_if_event_is_invalid() { final MemoizingObserver observer = memoizingObserver(); boundedContext.notify(event, observer); - assertEquals(ERROR, observer.firstResponse().getStatus().getStatusCase()); + assertEquals(ERROR, observer.firstResponse() + .getStatus() + .getStatusCase()); } @Test @@ -242,12 +292,13 @@ public void do_not_set_storage_factory_if_EventStore_is_set() { final EventStore eventStore = mock(EventStore.class); final BoundedContext bc = BoundedContext.newBuilder() .setEventBus(EventBus.newBuilder() - .setEventStore(eventStore)) + .setEventStore(eventStore)) .build(); assertEquals(eventStore, bc.getEventBus() .getEventStore()); } + @SuppressWarnings("unchecked") // OK for the purpose of the created Matcher. @Test public void propagate_registered_repositories_to_stand() { final BoundedContext boundedContext = BoundedContext.newBuilder() @@ -255,7 +306,8 @@ public void propagate_registered_repositories_to_stand() { final Stand stand = Spy.ofClass(Stand.class) .on(boundedContext); - verify(stand, never()).registerTypeSupplier(any(Repository.class)); + final Repository any = any(Repository.class); + verify(stand, never()).registerTypeSupplier(any); final ProjectAggregateRepository repository = new ProjectAggregateRepository(); @@ -263,8 +315,9 @@ public void propagate_registered_repositories_to_stand() { verify(stand).registerTypeSupplier(eq(repository)); } - @Test(expected = IllegalStateException.class) + @Test public void match_multi_tenancy_with_CommandBus() { + thrown.expect(IllegalStateException.class); BoundedContext.newBuilder() .setMultitenant(true) .setCommandBus(CommandBus.newBuilder() @@ -289,8 +342,9 @@ public void set_multi_tenancy_in_CommandBus() { .isMultitenant()); } - @Test(expected = IllegalStateException.class) + @Test public void match_multi_tenancy_with_Stand() { + thrown.expect(IllegalStateException.class); BoundedContext.newBuilder() .setMultitenant(true) .setStand(Stand.newBuilder() @@ -302,8 +356,8 @@ public void match_multi_tenancy_with_Stand() { @Test public void set_same_multitenancy_in_Stand() { BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(true) - .build(); + .setMultitenant(true) + .build(); assertEquals(bc.isMultitenant(), bc.getStand() .isMultitenant()); @@ -326,17 +380,17 @@ public void set_same_multitenancy_in_Stand() { @Test public void obtain_entity_types_by_visibility() { assertTrue(boundedContext.getEntityTypes(EntityOption.Visibility.FULL) - .isEmpty()); + .isEmpty()); registerAll(); assertFalse(boundedContext.getEntityTypes(EntityOption.Visibility.FULL) - .isEmpty()); + .isEmpty()); } - - @Test(expected = IllegalStateException.class) + @Test public void throw_ISE_when_no_repository_registered() { + thrown.expect(IllegalStateException.class); // Attempt to get a repository without registering. boundedContext.findRepository(Project.class); } @@ -366,52 +420,27 @@ public void do_not_expose_invisible_aggregate() { * {@code Model} and {@code BoundedContext}. However, previously such an issue was caught. * Therefore this test case ensures it's never happening again. */ + @SuppressWarnings("ProhibitedExceptionCaught") + // NPE is specifically handled in this case to prevent such cases in the future. @Test(expected = NullPointerException.class) public void throw_NPE_when_registering_repository_and_default_state_is_null() { final ProjectAggregateRepository repository = new ProjectAggregateRepository(); final Map mockMap = mock(Map.class); when(mockMap.get(any())).thenReturn(null); - final Object defaultStateRegistry = getObjectFromNestedEnumField( - DEFAULT_STATE_REGISTRY_FULL_CLASS_NAME, DEFAULT_STATE_REGISTRY_SINGLETON_FIELD_NAME); + final Object defaultStateRegistry = + getObjectFromNestedEnumField( + DEFAULT_STATE_REGISTRY_FULL_CLASS_NAME, + DEFAULT_STATE_REGISTRY_SINGLETON_FIELD_NAME + ); injectField(defaultStateRegistry, DEFAULT_STATES_FIELD_NAME, mockMap); try { boundedContext.register(repository); - }catch (NullPointerException e) { + } catch (NullPointerException e) { // reassigning mock map to real map, to prevent failing other tests final Map, Message> defaultState = newConcurrentMap(); injectField(defaultStateRegistry, DEFAULT_STATES_FIELD_NAME, defaultState); throw e; } } - - private Object getObjectFromNestedEnumField(String fullClassName, String fieldName) { - Object result = null; - try { - final Class aClass = Class.forName(fullClassName); - final Object enumConstant = aClass.getEnumConstants()[0]; - final Field field = aClass.getDeclaredField(fieldName); - field.setAccessible(true); - result = field.get(enumConstant); - } catch (ClassNotFoundException e) { - fail("Class " + fullClassName + " not found."); - } catch (NoSuchFieldException e) { - fail("Field " + fieldName + " should exist."); - } catch (IllegalAccessException e) { - fail(e.getMessage()); - } - assertNotNull(result); - return result; - } - - private void injectField(Object target, String fieldName, Object valueToInject) { - try { - final Field defaultStates = target.getClass() - .getDeclaredField(fieldName); - defaultStates.setAccessible(true); - defaultStates.set(target, valueToInject); - } catch (NoSuchFieldException | IllegalAccessException ignored) { - fail("Field " + fieldName + " should exist."); - } - } } diff --git a/server/src/test/java/io/spine/server/bc/given/BoundedContextTestEnv.java b/server/src/test/java/io/spine/server/bc/given/BoundedContextTestEnv.java index 4d9f8af66a5..b0238495742 100644 --- a/server/src/test/java/io/spine/server/bc/given/BoundedContextTestEnv.java +++ b/server/src/test/java/io/spine/server/bc/given/BoundedContextTestEnv.java @@ -55,7 +55,8 @@ public class BoundedContextTestEnv { - private BoundedContextTestEnv() {} + private BoundedContextTestEnv() { + } public static class ProjectAggregate extends Aggregate { @@ -82,9 +83,8 @@ public List handle(BcStartProject cmd, CommandContext ctx) { @Apply void event(BcProjectCreated event) { - getBuilder() - .setId(event.getProjectId()) - .setStatus(Project.Status.CREATED); + getBuilder().setId(event.getProjectId()) + .setStatus(Project.Status.CREATED); } @Apply @@ -94,15 +94,13 @@ void event(BcTaskAdded event) { @Apply void event(BcProjectStarted event) { - getBuilder() - .setId(event.getProjectId()) - .setStatus(Project.Status.STARTED) - .build(); + getBuilder().setId(event.getProjectId()) + .setStatus(Project.Status.STARTED); } } public static class ProjectAggregateRepository - extends AggregateRepository { + extends AggregateRepository { } public static class TestEventSubscriber extends EventSubscriber { diff --git a/server/src/test/java/io/spine/server/entity/AbstractEntityShould.java b/server/src/test/java/io/spine/server/entity/AbstractEntityShould.java index 0750d75a694..2df7a33295a 100644 --- a/server/src/test/java/io/spine/server/entity/AbstractEntityShould.java +++ b/server/src/test/java/io/spine/server/entity/AbstractEntityShould.java @@ -23,8 +23,9 @@ import com.google.protobuf.Message; import com.google.protobuf.StringValue; import io.spine.test.entity.number.NaturalNumber; -import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -40,6 +41,9 @@ */ public class AbstractEntityShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + /** * Ensures that {@link AbstractEntity#updateState(Message)} is final so that * it's not possible to override the default behaviour. @@ -84,9 +88,11 @@ public void throw_InvalidEntityStateException_if_state_is_invalid() { } @SuppressWarnings("ConstantConditions") // The goal of the test. - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_to_checkEntityState() { - final AnEntity entity = new AnEntity(0L); + AnEntity entity = new AnEntity(0L); + + thrown.expect(NullPointerException.class); entity.checkEntityState(null); } diff --git a/server/src/test/java/io/spine/server/entity/EntityEqualsShould.java b/server/src/test/java/io/spine/server/entity/EntityEqualsShould.java index 109e0f899b4..2aa09540c3a 100644 --- a/server/src/test/java/io/spine/server/entity/EntityEqualsShould.java +++ b/server/src/test/java/io/spine/server/entity/EntityEqualsShould.java @@ -27,9 +27,8 @@ import static io.spine.base.Identifier.newUuid; import static io.spine.test.Tests.nullRef; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; /** * This test suite tests {@link AbstractVersionableEntity#equals(Object)}. @@ -53,24 +52,24 @@ public void setUp() { public void assure_same_entities_are_equal() { final TestEntity another = TestEntity.withStateOf(entity); - assertTrue(entity.equals(another)); + assertEquals(entity, another); } @SuppressWarnings("EqualsWithItself") // is the purpose of this method. @Test public void assure_entity_is_equal_to_itself() { - assertTrue(entity.equals(entity)); + assertEquals(entity, entity); } @Test public void assure_entity_is_not_equal_to_null() { - assertFalse(entity.equals(nullRef())); + assertNotEquals(entity, nullRef()); } @SuppressWarnings("EqualsBetweenInconvertibleTypes") // is the purpose of this method. @Test public void assure_entity_is_not_equal_to_object_of_another_class() { - assertFalse(entity.equals(newUuid())); + assertNotEquals(entity, newUuid()); } @Test @@ -78,7 +77,7 @@ public void assure_entities_with_different_ids_are_not_equal() { final TestEntity another = TestEntity.newInstance(newUuid()); assertNotEquals(entity.getId(), another.getId()); - assertFalse(entity.equals(another)); + assertNotEquals(entity, another); } @Test @@ -87,14 +86,15 @@ public void assure_entities_with_different_states_are_not_equal() { another.updateState(Sample.messageOfType(Project.class), another.getVersion()); assertNotEquals(entity.getState(), another.getState()); - assertFalse(entity.equals(another)); + assertNotEquals(entity, another); } + @SuppressWarnings("CheckReturnValue") // The entity version can be ignored in this test. @Test public void assure_entities_with_different_versions_are_not_equal() { final TestEntity another = TestEntity.withStateOf(entity); another.incrementVersion(); - assertFalse(entity.equals(another)); + assertNotEquals(entity, another); } } diff --git a/server/src/test/java/io/spine/server/entity/EntityShould.java b/server/src/test/java/io/spine/server/entity/EntityShould.java index b83f0680e8f..e8b12c6928a 100644 --- a/server/src/test/java/io/spine/server/entity/EntityShould.java +++ b/server/src/test/java/io/spine/server/entity/EntityShould.java @@ -186,6 +186,7 @@ public void increment_version_by_one() { assertEquals(1, version); } + @SuppressWarnings("CheckReturnValue") // New entity version number can be ignored in this test. @Test public void record_modification_time_when_incrementing_version() { final long timeBeforeincrement = TimeTests.currentTimeSeconds(); diff --git a/server/src/test/java/io/spine/server/entity/FieldMasksShould.java b/server/src/test/java/io/spine/server/entity/FieldMasksShould.java index 8349e1d303b..348d96c4ae8 100644 --- a/server/src/test/java/io/spine/server/entity/FieldMasksShould.java +++ b/server/src/test/java/io/spine/server/entity/FieldMasksShould.java @@ -20,7 +20,7 @@ package io.spine.server.entity; -import com.google.protobuf.Descriptors; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.FieldMask; import io.spine.test.aggregate.Project; import io.spine.test.aggregate.ProjectId; @@ -29,7 +29,9 @@ import io.spine.test.aggregate.TaskId; import io.spine.test.commandservice.customer.Customer; import io.spine.type.TypeUrl; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Iterator; @@ -43,13 +45,17 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; /** * @author Dmytro Dashenkov */ public class FieldMasksShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void have_private_constructor() { assertHasPrivateParameterlessCtor(FieldMasks.class); @@ -57,34 +63,34 @@ public void have_private_constructor() { @Test public void create_masks_for_given_field_tags() { - final Descriptors.Descriptor descriptor = Project.getDescriptor(); - final int[] fieldNumbers = {1, 2, 3}; + Descriptor descriptor = Project.getDescriptor(); + int[] fieldNumbers = {1, 2, 3}; @SuppressWarnings("DuplicateStringLiteralInspection") - final String[] fieldNames = {"id", "name", "task"}; - final FieldMask mask = FieldMasks.maskOf(descriptor, fieldNumbers); + String[] fieldNames = {"id", "name", "task"}; + FieldMask mask = FieldMasks.maskOf(descriptor, fieldNumbers); - final List paths = mask.getPathsList(); + List paths = mask.getPathsList(); assertSize(fieldNumbers.length, paths); for (int i = 0; i < paths.size(); i++) { - final String expectedPath = descriptor.getFullName() + '.' + fieldNames[i]; + String expectedPath = descriptor.getFullName() + '.' + fieldNames[i]; assertEquals(expectedPath, paths.get(i)); } } @Test public void retrieve_default_field_mask_if_no_field_tags_requested() { - final Descriptors.Descriptor descriptor = Project.getDescriptor(); - final FieldMask mask = FieldMasks.maskOf(descriptor); + Descriptor descriptor = Project.getDescriptor(); + FieldMask mask = FieldMasks.maskOf(descriptor); assertEquals(FieldMask.getDefaultInstance(), mask); } @Test public void apply_mask_to_single_message() { - final FieldMask fieldMask = Given.fieldMask(Project.ID_FIELD_NUMBER, Project.NAME_FIELD_NUMBER); - final Project original = Given.newProject("some-string-id"); + FieldMask fieldMask = Given.fieldMask(Project.ID_FIELD_NUMBER, Project.NAME_FIELD_NUMBER); + Project original = Given.newProject("some-string-id"); - final Project masked = FieldMasks.applyMask(fieldMask, original, Given.TYPE); + Project masked = FieldMasks.applyMask(fieldMask, original, Given.TYPE); assertNotEquals(original, masked); assertMatchesMask(masked, fieldMask); @@ -93,18 +99,18 @@ public void apply_mask_to_single_message() { @SuppressWarnings({"MethodWithMultipleLoops", "ObjectEquality"}) @Test public void apply_mask_to_message_collections() { - final FieldMask fieldMask = Given.fieldMask(Project.STATUS_FIELD_NUMBER, + FieldMask fieldMask = Given.fieldMask(Project.STATUS_FIELD_NUMBER, Project.TASK_FIELD_NUMBER); - final int count = 5; + int count = 5; - final Collection original = new LinkedList<>(); + Collection original = new LinkedList<>(); for (int i = 0; i < count; i++) { - final Project project = Given.newProject(format("project-%s", i)); + Project project = Given.newProject(format("project-%s", i)); original.add(project); } - final Collection masked = FieldMasks.applyMask(fieldMask, original, Given.TYPE); + Collection masked = FieldMasks.applyMask(fieldMask, original, Given.TYPE); assertSize(original.size(), masked); @@ -122,56 +128,56 @@ public void apply_mask_to_message_collections() { @Test public void apply_only_non_empty_mask_to_single_item() { - final FieldMask emptyMask = Given.fieldMask(); + FieldMask emptyMask = Given.fieldMask(); - final Project origin = Given.newProject("read_whole_message"); - final Project clone = Project.newBuilder(origin) + Project origin = Given.newProject("read_whole_message"); + Project clone = Project.newBuilder(origin) .build(); - final Project processed = FieldMasks.applyMask(emptyMask, origin, Given.TYPE); + Project processed = FieldMasks.applyMask(emptyMask, origin, Given.TYPE); // Check object itself was returned - assertTrue(processed == origin); + assertSame(processed, origin); // Check object was not changed - assertTrue(processed.equals(clone)); + assertEquals(processed, clone); } @SuppressWarnings({"ObjectEquality", "MethodWithMultipleLoops"}) @Test public void apply_only_non_empty_mask_to_collection() { - final FieldMask emptyMask = Given.fieldMask(); + FieldMask emptyMask = Given.fieldMask(); - final Collection original = new LinkedList<>(); - final int count = 5; + Collection original = new LinkedList<>(); + int count = 5; for (int i = 0; i < count; i++) { - final Project project = Given.newProject(format("test-data--%s", i)); + Project project = Given.newProject(format("test-data--%s", i)); original.add(project); } - final Collection processed = FieldMasks.applyMask(emptyMask, original, Given.TYPE); + Collection processed = FieldMasks.applyMask(emptyMask, original, Given.TYPE); assertSize(original.size(), processed); // The argument is not returned - assertFalse(original == processed); + assertNotSame(original, processed); // A copy of the argument is returned (Collection type may differ) - final Iterator processedProjects = processed.iterator(); + Iterator processedProjects = processed.iterator(); for (Project anOriginal : original) { - assertTrue(processedProjects.next() - .equals(anOriginal)); + assertEquals(processedProjects.next(), anOriginal); } } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_mask_message_if_passed_type_does_not_match() { - final FieldMask mask = Given.fieldMask(Project.ID_FIELD_NUMBER); + FieldMask mask = Given.fieldMask(Project.ID_FIELD_NUMBER); - final Project origin = Given.newProject("some-string"); + Project origin = Given.newProject("some-string"); + thrown.expect(IllegalArgumentException.class); FieldMasks.applyMask(mask, origin, Given.OTHER_TYPE); } @@ -180,27 +186,27 @@ private static class Given { private static final TypeUrl TYPE = TypeUrl.of(Project.class); private static final TypeUrl OTHER_TYPE = TypeUrl.of(Customer.class); - private static final Descriptors.Descriptor TYPE_DESCRIPTOR = Project.getDescriptor(); + private static final Descriptor TYPE_DESCRIPTOR = Project.getDescriptor(); private static Project newProject(String id) { - final ProjectId projectId = ProjectId.newBuilder() + ProjectId projectId = ProjectId.newBuilder() .setId(id) .build(); - final Task first = Task.newBuilder() + Task first = Task.newBuilder() .setTaskId(TaskId.newBuilder() .setId(1) .build()) .setTitle("First Task") .build(); - final Task second = Task.newBuilder() + Task second = Task.newBuilder() .setTaskId(TaskId.newBuilder() .setId(2) .build()) .setTitle("Second Task") .build(); - final Project project = Project.newBuilder() + Project project = Project.newBuilder() .setId(projectId) .setName(format("Test project : %s", id)) .addTask(first) diff --git a/server/src/test/java/io/spine/server/entity/RecordBasedRepositoryShould.java b/server/src/test/java/io/spine/server/entity/RecordBasedRepositoryShould.java index c8d52f83035..afbc8c0627a 100644 --- a/server/src/test/java/io/spine/server/entity/RecordBasedRepositoryShould.java +++ b/server/src/test/java/io/spine/server/entity/RecordBasedRepositoryShould.java @@ -22,7 +22,8 @@ import com.google.common.base.Optional; import com.google.common.collect.Lists; -import com.google.protobuf.Descriptors; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.FieldMask; import com.google.protobuf.Message; import com.google.protobuf.StringValue; @@ -79,6 +80,12 @@ public abstract class RecordBasedRepositoryShould repository; + private static > + void assertMatches(E entity, FieldMask fieldMask) { + Message state = entity.getState(); + Tests.assertMatchesMask(state, fieldMask); + } + protected abstract RecordBasedRepository createRepository(); protected abstract E createEntity(); @@ -94,32 +101,33 @@ public void setUp() { setCurrentTenant(newUuid()); } + /* + * Store/load functions for working in multi-tenant execution context + **********************************************************************/ + @After public void tearDown() throws Exception { clearCurrentTenant(); } - /* - * Store/load functions for working in multi-tenant execution context - **********************************************************************/ - - private void storeEntity(final E entity) { + private void storeEntity(E entity) { repository.store(entity); } - private List createAndStoreEntities(final RecordBasedRepository repo, int count) { - final List entities = createEntities(count); + @CanIgnoreReturnValue + private List createAndStoreEntities(RecordBasedRepository repo, int count) { + List entities = createEntities(count); for (E entity : entities) { repo.store(entity); } return entities; } - private Optional find(final I id) { + private Optional find(I id) { return repository.find(id); } - private Iterator loadMany(final List ids) { + private Iterator loadMany(List ids) { return repository.loadAll(ids); } @@ -127,45 +135,46 @@ private Iterator loadAll() { return repository.loadAll(); } - private E loadOrCreate(final I id) { + private E loadOrCreate(I id) { return repository.findOrCreate(id); } - private Iterator find(EntityFilters filters, - FieldMask firstFieldOnly) { - return repository.find(filters, firstFieldOnly); - } - /* * Tests ************/ + private Iterator find(EntityFilters filters, FieldMask firstFieldOnly) { + return repository.find(filters, firstFieldOnly); + } + @Test public void create_entities() { - final I id = createId(5); - final E projectEntity = repository.create(id); + I id = createId(5); + E projectEntity = repository.create(id); assertNotNull(projectEntity); assertEquals(id, projectEntity.getId()); } @Test public void find_single_entity_by_id() { - final E entity = createEntity(); + E entity = createEntity(); storeEntity(entity); - final Entity found = find(entity.getId()).get(); + final Optional optional = find(entity.getId()); + assertTrue(optional.isPresent()); + Entity found = optional.get(); assertEquals(found, entity); } @SuppressWarnings("MethodWithMultipleLoops") @Test public void find_multiple_entities_by_ids() { - final int count = 10; - final List entities = createAndStoreEntities(repository, count); + int count = 10; + List entities = createAndStoreEntities(repository, count); - final List ids = Lists.newLinkedList(); + List ids = Lists.newLinkedList(); // Find some of the records (half of them in this case) for (int i = 0; i < count / 2; i++) { @@ -173,7 +182,7 @@ public void find_multiple_entities_by_ids() { .getId()); } - final Collection found = newArrayList(loadMany(ids)); + Collection found = newArrayList(loadMany(ids)); assertSize(ids.size(), found); @@ -185,8 +194,8 @@ public void find_multiple_entities_by_ids() { @SuppressWarnings("MethodWithMultipleLoops") @Test public void find_all_entities() { - final List entities = createAndStoreEntities(repository, 150); - final Collection found = newArrayList(loadAll()); + List entities = createAndStoreEntities(repository, 150); + Collection found = newArrayList(loadAll()); assertSize(entities.size(), found); for (E entity : found) { @@ -196,32 +205,35 @@ public void find_all_entities() { @Test public void find_entities_by_query() { - final I id1 = createId(271); - final I id2 = createId(314); - final Class entityClass = repository.getEntityClass(); - final E entity1 = Given.entityOfClass(entityClass) - .withId(id1) - .build(); - final E entity2 = Given.entityOfClass(entityClass) - .withId(id2) - .build(); + I id1 = createId(271); + I id2 = createId(314); + Class entityClass = repository.getEntityClass(); + E entity1 = Given.entityOfClass(entityClass) + .withId(id1) + .build(); + E entity2 = Given.entityOfClass(entityClass) + .withId(id2) + .build(); repository.store(entity1); repository.store(entity2); - final String fieldPath = "idString"; - final StringValue fieldValue = StringValue.newBuilder() - .setValue(id1.toString()) - .build(); - final ColumnFilter filter = eq(fieldPath, fieldValue); - final CompositeColumnFilter aggregatingFilter = CompositeColumnFilter.newBuilder() - .addFilter(filter) - .setOperator(ALL) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(aggregatingFilter) - .build(); - final Collection found = newArrayList(repository.find(filters, - FieldMask.getDefaultInstance())); + String fieldPath = "idString"; + StringValue fieldValue = StringValue.newBuilder() + .setValue(id1.toString()) + .build(); + ColumnFilter filter = eq(fieldPath, fieldValue); + CompositeColumnFilter aggregatingFilter = CompositeColumnFilter + .newBuilder() + .addFilter(filter) + .setOperator(ALL) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .addFilter(aggregatingFilter) + .build(); + Collection found = newArrayList( + repository.find(filters, FieldMask.getDefaultInstance()) + ); assertSize(1, found); assertContains(entity1, found); assertNotContains(entity2, found); @@ -229,17 +241,17 @@ public void find_entities_by_query() { @Test public void find_no_entities_if_empty() { - final Collection found = newArrayList(loadAll()); + Collection found = newArrayList(loadAll()); assertSize(0, found); } @Test public void create_entity_on_loadOrCreate_if_not_found() { - final int count = 3; + int count = 3; createAndStoreEntities(repository, count); - final I id = createId(count + 1); - final E entity = loadOrCreate(id); + I id = createId(count + 1); + E entity = loadOrCreate(id); assertNotNull(entity); assertEquals(id, entity.getId()); @@ -248,17 +260,17 @@ public void create_entity_on_loadOrCreate_if_not_found() { @SuppressWarnings("MethodWithMultipleLoops") @Test public void handle_wrong_passed_ids() { - final int count = 10; - final List entities = createAndStoreEntities(repository, count); - final List ids = Lists.newLinkedList(); + int count = 10; + List entities = createAndStoreEntities(repository, count); + List ids = Lists.newLinkedList(); for (int i = 0; i < count; i++) { ids.add(entities.get(i) .getId()); } - final Entity sideEntity = createEntity(); + Entity sideEntity = createEntity(); ids.add(sideEntity.getId()); - final Collection found = newArrayList(loadMany(ids)); + Collection found = newArrayList(loadMany(ids)); assertSize(ids.size() - 1, found); // Check we've found all existing items for (E entity : found) { @@ -269,32 +281,35 @@ public void handle_wrong_passed_ids() { @SuppressWarnings("MethodWithMultipleLoops") @Test public void retrieve_all_records_with_entity_filters_and_field_mask_applied() { - final int count = 10; - final List entities = createAndStoreEntities(repository, count); - final List ids = Lists.newLinkedList(); + int count = 10; + List entities = createAndStoreEntities(repository, count); + List ids = Lists.newLinkedList(); // Find some of the records (half of them in this case) for (int i = 0; i < count / 2; i++) { - final Message entityId = (Message) entities.get(i) - .getId(); - final EntityId id = EntityId.newBuilder() - .setId(pack(entityId)) - .build(); + Message entityId = (Message) entities.get(i) + .getId(); + EntityId id = EntityId.newBuilder() + .setId(pack(entityId)) + .build(); ids.add(id); } - final EntityIdFilter filter = EntityIdFilter.newBuilder() - .addAllIds(ids) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .setIdFilter(filter) - .build(); - final Descriptors.Descriptor entityDescriptor = entities.get(0) - .getState() - .getDescriptorForType(); - final FieldMask firstFieldOnly = FieldMasks.maskOf(entityDescriptor, 1); - final Iterator readEntities = find(filters, firstFieldOnly); - final Collection foundList = newArrayList(readEntities); + EntityIdFilter filter = EntityIdFilter + .newBuilder() + .addAllIds(ids) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .setIdFilter(filter) + .build(); + Descriptor entityDescriptor = + entities.get(0) + .getState() + .getDescriptorForType(); + FieldMask firstFieldOnly = FieldMasks.maskOf(entityDescriptor, 1); + Iterator readEntities = find(filters, firstFieldOnly); + Collection foundList = newArrayList(readEntities); assertSize(ids.size(), foundList); @@ -303,24 +318,20 @@ public void retrieve_all_records_with_entity_filters_and_field_mask_applied() { } } - private static > - void assertMatches(E entity, FieldMask fieldMask) { - final Message state = entity.getState(); - Tests.assertMatchesMask(state, fieldMask); - } - @Test public void mark_records_archived() { - final E entity = createEntity(); - final I id = entity.getId(); + E entity = createEntity(); + I id = entity.getId(); storeEntity(entity); assertTrue(find(id).isPresent()); - entity.setLifecycleFlags(LifecycleFlags.newBuilder() - .setArchived(true) - .build()); + entity.setLifecycleFlags( + LifecycleFlags.newBuilder() + .setArchived(true) + .build() + ); storeEntity(entity); assertFalse(find(id).isPresent()); @@ -328,16 +339,19 @@ public void mark_records_archived() { @Test public void mark_records_deleted() { - final E entity = createEntity(); - final I id = entity.getId(); + E entity = createEntity(); + I id = entity.getId(); storeEntity(entity); assertTrue(find(id).isPresent()); - entity.setLifecycleFlags(LifecycleFlags.newBuilder() - .setDeleted(true) - .build()); + entity.setLifecycleFlags( + LifecycleFlags + .newBuilder() + .setDeleted(true) + .build() + ); storeEntity(entity); assertFalse(find(id).isPresent()); @@ -345,13 +359,13 @@ public void mark_records_deleted() { @Test public void exclude_non_active_records_from_entity_query() { - final I archivedId = createId(42); - final I deletedId = createId(314); - final I activeId = createId(271); + I archivedId = createId(42); + I deletedId = createId(314); + I activeId = createId(271); - final E activeEntity = repository.create(activeId); - final E archivedEntity = repository.create(archivedId); - final E deletedEntity = repository.create(deletedId); + E activeEntity = repository.create(activeId); + E archivedEntity = repository.create(archivedId); + E deletedEntity = repository.create(deletedId); delete((EventPlayingEntity) deletedEntity); archive((EventPlayingEntity) archivedEntity); @@ -360,24 +374,24 @@ public void exclude_non_active_records_from_entity_query() { repository.store(archivedEntity); repository.store(deletedEntity); - final Iterator found = repository.find(EntityFilters.getDefaultInstance(), - FieldMask.getDefaultInstance()); - final List foundList = newArrayList(found); + Iterator found = repository.find(EntityFilters.getDefaultInstance(), + FieldMask.getDefaultInstance()); + List foundList = newArrayList(found); // Check results assertSize(1, foundList); - final E actualEntity = foundList.get(0); + E actualEntity = foundList.get(0); assertEquals(activeEntity, actualEntity); } @Test public void allow_any_lifecycle_if_column_involved() { - final I archivedId = createId(42); - final I deletedId = createId(314); - final I activeId = createId(271); + I archivedId = createId(42); + I deletedId = createId(314); + I activeId = createId(271); - final E activeEntity = repository.create(activeId); - final E archivedEntity = repository.create(archivedId); - final E deletedEntity = repository.create(deletedId); + E activeEntity = repository.create(activeId); + E archivedEntity = repository.create(archivedId); + E deletedEntity = repository.create(deletedId); delete((EventPlayingEntity) deletedEntity); archive((EventPlayingEntity) archivedEntity); @@ -386,13 +400,14 @@ public void allow_any_lifecycle_if_column_involved() { repository.store(archivedEntity); repository.store(deletedEntity); - final CompositeColumnFilter columnFilter = all(eq(archived.name(), false)); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(columnFilter) - .build(); + CompositeColumnFilter columnFilter = all(eq(archived.name(), false)); + EntityFilters filters = EntityFilters + .newBuilder() + .addFilter(columnFilter) + .build(); - final Iterator found = repository.find(filters, FieldMask.getDefaultInstance()); - final Collection foundList = newArrayList(found); + Iterator found = repository.find(filters, FieldMask.getDefaultInstance()); + Collection foundList = newArrayList(found); // Check result assertSize(2, foundList); assertContainsAll(foundList, activeEntity, deletedEntity); @@ -400,14 +415,14 @@ public void allow_any_lifecycle_if_column_involved() { @Test public void cache_entity_columns_on_registration() { - if(!repository.isRegistered()) { + if (!repository.isRegistered()) { repository.onRegistered(); } - final RecordStorage storage = repository.recordStorage(); - final EntityColumnCache entityColumnCache = storage.entityColumnCache(); + RecordStorage storage = repository.recordStorage(); + EntityColumnCache entityColumnCache = storage.entityColumnCache(); // Verify that cache contains searched column - entityColumnCache.findColumn("idString"); + assertNotNull(entityColumnCache.findColumn("idString")); } } diff --git a/server/src/test/java/io/spine/server/entity/RepositoryShould.java b/server/src/test/java/io/spine/server/entity/RepositoryShould.java index 26bbb9757a7..66c38d65a9e 100644 --- a/server/src/test/java/io/spine/server/entity/RepositoryShould.java +++ b/server/src/test/java/io/spine/server/entity/RepositoryShould.java @@ -34,7 +34,9 @@ import io.spine.test.entity.ProjectId; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; import java.util.List; @@ -53,6 +55,9 @@ public class RepositoryShould { private StorageFactory storageFactory; private TenantId tenantId; + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static ProjectId createId(String value) { return ProjectId.newBuilder() .setId(value) @@ -78,8 +83,9 @@ public void tearDown() throws Exception { * Tests of initialization **************************/ - @Test(expected = ModelError.class) + @Test public void check_for_entity_id_class() { + thrown.expect(ModelError.class); new RepoForEntityWithUnsupportedId().getIdClass(); } @@ -88,8 +94,9 @@ public void report_unregistered_on_init() { assertFalse(new TestRepo().isRegistered()); } - @Test(expected = IllegalStateException.class) + @Test public void not_allow_getting_BoundedContext_before_registration() { + thrown.expect(IllegalStateException.class); new TestRepo().getBoundedContext(); } @@ -97,9 +104,11 @@ public void not_allow_getting_BoundedContext_before_registration() { * Tests of regular work **************************/ - @Test(expected = IllegalStateException.class) + @Test public void reject_repeated_storage_initialization() { repository.initStorage(storageFactory); + + thrown.expect(IllegalStateException.class); repository.initStorage(storageFactory); } @@ -108,8 +117,9 @@ public void have_no_storage_upon_creation() { assertFalse(repository.isStorageAssigned()); } - @Test(expected = IllegalStateException.class) - public void throw_ISE_on_getting_unassigned_storage() { + @Test + public void prohibit_obtaining_unassigned_storage() { + thrown.expect(IllegalStateException.class); repository.getStorage(); } @@ -120,14 +130,8 @@ public void init_storage_with_factory() { assertNotNull(repository.getStorage()); } - @Test(expected = IllegalStateException.class) - public void allow_initializing_storage_only_once() { - repository.initStorage(storageFactory); - repository.initStorage(storageFactory); - } - @Test - public void close_storage_on_close() throws Exception { + public void close_storage_on_close() { repository.initStorage(storageFactory); final RecordStorage storage = (RecordStorage) repository.getStorage(); @@ -138,7 +142,7 @@ public void close_storage_on_close() throws Exception { } @Test - public void disconnect_from_storage_on_close() throws Exception { + public void disconnect_from_storage_on_close() { repository.initStorage(storageFactory); repository.close(); @@ -182,8 +186,7 @@ private Iterator getIterator(TenantId tenantId) { new TenantAwareFunction0>(tenantId) { @Override public Iterator apply() { - return repository.iterator( - Predicates.alwaysTrue()); + return repository.iterator(Predicates.alwaysTrue()); } }; return op.execute(); diff --git a/server/src/test/java/io/spine/server/entity/TransactionShould.java b/server/src/test/java/io/spine/server/entity/TransactionShould.java index 0c180efdfee..dbb22938e77 100644 --- a/server/src/test/java/io/spine/server/entity/TransactionShould.java +++ b/server/src/test/java/io/spine/server/entity/TransactionShould.java @@ -23,6 +23,7 @@ import com.google.protobuf.Message; import io.spine.core.Event; import io.spine.core.EventEnvelope; +import io.spine.core.Events; import io.spine.core.Version; import io.spine.server.command.TestEventFactory; import io.spine.server.entity.Transaction.Phase; @@ -32,7 +33,9 @@ import io.spine.validate.ValidatingBuilder; import io.spine.validate.ValidationException; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.ArgumentMatcher; import java.util.List; @@ -40,7 +43,6 @@ import static com.google.common.collect.Lists.newArrayList; import static io.spine.base.Time.getCurrentTime; import static io.spine.core.Versions.newVersion; -import static io.spine.protobuf.AnyPacker.unpack; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; @@ -65,6 +67,9 @@ public abstract class TransactionShould createTx(E entity); protected abstract Transaction createTxWithState(E entity, @@ -227,23 +232,27 @@ public void init_state_and_version_if_specified_in_ctor(){ assertEquals(entity.getVersion(), newVersion); } - @Test(expected = IllegalStateException.class) + @SuppressWarnings("CheckReturnValue") // can ignore new entity version in this test. + @Test public void not_allow_injecting_state_if_entity_has_non_zero_version_already(){ - final E entity = createEntity(); + E entity = createEntity(); entity.incrementVersion(); - final S newState = createNewState(); - final Version newVersion = someVersion(); + S newState = createNewState(); + Version newVersion = someVersion(); + thrown.expect(IllegalStateException.class); createTxWithState(entity, newState, newVersion); } - @Test(expected = IllegalStateException.class) + @Test public void propagate_phase_failure_exception_as_ISE() { - final E entity = createEntity(); + E entity = createEntity(); - final Transaction tx = createTx(entity); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessageThatFailsInHandler()); + Event event = createEvent(createEventMessageThatFailsInHandler()); + + thrown.expect(IllegalStateException.class); applyEvent(tx, event); } @@ -266,11 +275,11 @@ public void rollback_automatically_if_phase_failed() { @Test public void propagate_exception_wrapped_as_ISE_if_commit_fails() { - final E entity = createEntity(someViolations()); - final S newState = createNewState(); - final Version version = someVersion(); + E entity = createEntity(someViolations()); + S newState = createNewState(); + Version version = someVersion(); - final Transaction tx = createTxWithState(entity, newState, version); + Transaction tx = createTxWithState(entity, newState, version); try { tx.commit(); fail("Expected an exception due to a failed commit."); @@ -279,16 +288,18 @@ public void propagate_exception_wrapped_as_ISE_if_commit_fails() { } } - @Test(expected = InvalidEntityStateException.class) + @Test public void throw_InvalidEntityStateException_if_constraints_violated_on_commit() { - final E entity = createEntity(); + E entity = createEntity(); - final S newState = createNewState(); - final Version version = someVersion(); + S newState = createNewState(); + Version version = someVersion(); - final Transaction tx = createTxWithState(entity, newState, version); - final ValidationException toThrow = validationException(); + Transaction tx = createTxWithState(entity, newState, version); + ValidationException toThrow = validationException(); breakEntityValidation(entity, toThrow); + + thrown.expect(InvalidEntityStateException.class); tx.commit(); } @@ -331,7 +342,7 @@ protected final Event createEvent(Message eventMessage) { } private static ValidationException validationException() { - final ValidationException ex = new ValidationException(Lists.newLinkedList()); + final ValidationException ex = new ValidationException(Lists.newLinkedList()); return ex; } @@ -351,17 +362,14 @@ private static List someViolations() { } private ArgumentMatcher> matchesSuccessfulPhaseFor(final Event event) { - return new ArgumentMatcher>() { - @Override - public boolean matches(Phase phase) { - return checkPhase(event, phase, true); - } - }; + return phase -> checkPhase(event, phase, true); } private static boolean checkPhase(Event event, Phase phase, boolean successful) { - return unpack(event.getMessage()).equals(phase.getEventMessage()) - && event.getContext().equals(phase.getContext()) + Message eventMessage = Events.getMessage(event); + return eventMessage.equals(phase.getEventMessage()) + && event.getContext() + .equals(phase.getContext()) && phase.isSuccessful() == successful; } diff --git a/server/src/test/java/io/spine/server/entity/VisibilityGuardShould.java b/server/src/test/java/io/spine/server/entity/VisibilityGuardShould.java index 42f52848258..0e1e63a47df 100644 --- a/server/src/test/java/io/spine/server/entity/VisibilityGuardShould.java +++ b/server/src/test/java/io/spine/server/entity/VisibilityGuardShould.java @@ -34,7 +34,9 @@ import io.spine.type.TypeName; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.List; import java.util.Set; @@ -55,6 +57,9 @@ public class VisibilityGuardShould { private List repositories; private BoundedContext boundedContext; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { boundedContext = BoundedContext.newBuilder() @@ -94,15 +99,15 @@ public void deny_access_to_invisible_repos() { @Test public void obtain_repos_by_visibility() { - final Set full = guard.getEntityTypes(Visibility.FULL); + Set full = guard.getEntityTypes(Visibility.FULL); assertEquals(1, full.size()); assertTrue(full.contains(TypeName.of(FullAccessAggregate.class))); - final Set subscribable = guard.getEntityTypes(Visibility.SUBSCRIBE); + Set subscribable = guard.getEntityTypes(Visibility.SUBSCRIBE); assertEquals(1, subscribable.size()); assertTrue(subscribable.contains(TypeName.of(SubscribableAggregate.class))); - final Set hidden = guard.getEntityTypes(Visibility.NONE); + Set hidden = guard.getEntityTypes(Visibility.NONE); assertEquals(1, hidden.size()); assertTrue(hidden.contains(TypeName.of(HiddenAggregate.class))); } @@ -116,13 +121,15 @@ public void shut_down_repositories() { } } - @Test(expected = IllegalStateException.class) + @Test public void do_not_allow_double_registration() { + thrown.expect(IllegalStateException.class); register(new ExposedRepository()); } - @Test(expected = IllegalArgumentException.class) + @Test public void reject_unregistered_state_class() { + thrown.expect(IllegalArgumentException.class); guard.getRepository(Empty.class); } diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnReaderShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnReaderShould.java index d5976874eb7..6f2698a7143 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnReaderShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnReaderShould.java @@ -22,16 +22,27 @@ import com.google.common.testing.NullPointerTester; import com.google.common.testing.NullPointerTester.Visibility; -import io.spine.server.entity.storage.given.ColumnsTestEnv.*; +import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithColumnFromInterface; +import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithManyGetters; +import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithManyGettersDescendant; +import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithNoStorageFields; +import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithRepeatedColumnNames; +import io.spine.server.entity.storage.given.ColumnsTestEnv.RealLifeEntity; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import static com.google.common.base.Preconditions.checkNotNull; +import static io.spine.server.entity.storage.ColumnReader.forClass; import static io.spine.server.storage.EntityField.version; import static io.spine.server.storage.LifecycleFlagField.archived; import static io.spine.server.storage.LifecycleFlagField.deleted; -import static io.spine.test.Verify.*; +import static io.spine.test.Verify.assertFalse; +import static io.spine.test.Verify.assertNotNull; +import static io.spine.test.Verify.assertSize; +import static io.spine.test.Verify.assertTrue; import static io.spine.validate.Validate.checkNotEmptyOrBlank; /** @@ -39,6 +50,9 @@ */ public class ColumnReaderShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void pass_null_check() { new NullPointerTester().testStaticMethods(ColumnReader.class, Visibility.PACKAGE); @@ -46,8 +60,8 @@ public void pass_null_check() { @Test public void retrieve_entity_columns_from_class() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithManyGetters.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(EntityWithManyGetters.class); + Collection entityColumns = columnReader.readColumns(); assertSize(3, entityColumns); assertTrue(containsColumn(entityColumns, "someMessage")); @@ -57,38 +71,39 @@ public void retrieve_entity_columns_from_class() { @Test public void handle_class_without_columns() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithNoStorageFields.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(EntityWithNoStorageFields.class); + Collection entityColumns = columnReader.readColumns(); assertNotNull(entityColumns); assertTrue(entityColumns.isEmpty()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_error_on_invalid_column_definitions() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithRepeatedColumnNames.class); + ColumnReader columnReader = forClass(EntityWithRepeatedColumnNames.class); + thrown.expect(IllegalStateException.class); columnReader.readColumns(); } @Test public void ignore_non_public_getters_with_column_annotation_from_super_class() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithManyGettersDescendant.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(EntityWithManyGettersDescendant.class); + Collection entityColumns = columnReader.readColumns(); assertSize(3, entityColumns); } @Test public void ignore_static_members() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithManyGetters.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(EntityWithManyGetters.class); + Collection entityColumns = columnReader.readColumns(); assertFalse(containsColumn(entityColumns, "staticMember")); } @Test public void handle_inherited_fields() { - final ColumnReader columnReader = ColumnReader.forClass(RealLifeEntity.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(RealLifeEntity.class); + Collection entityColumns = columnReader.readColumns(); assertSize(5, entityColumns); assertTrue(containsColumn(entityColumns, archived.name())); @@ -100,8 +115,8 @@ public void handle_inherited_fields() { @Test public void obtain_fields_from_implemented_interfaces() { - final ColumnReader columnReader = ColumnReader.forClass(EntityWithColumnFromInterface.class); - final Collection entityColumns = columnReader.readColumns(); + ColumnReader columnReader = forClass(EntityWithColumnFromInterface.class); + Collection entityColumns = columnReader.readColumns(); assertSize(1, entityColumns); assertTrue(containsColumn(entityColumns, "integerFieldValue")); @@ -112,8 +127,7 @@ private static boolean containsColumn(Iterable entityColumns, Stri checkNotEmptyOrBlank(columnName, "column name"); for (EntityColumn column : entityColumns) { - if (column.getName() - .equals(columnName)) { + if (columnName.equals(column.getName())) { return true; } } diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java index 4025585f85c..b1b4985abfb 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java @@ -24,6 +24,7 @@ import com.google.protobuf.Any; import io.spine.core.Version; import io.spine.server.entity.AbstractVersionableEntity; +import io.spine.server.entity.Entity; import io.spine.server.entity.EntityWithLifecycle; import io.spine.server.entity.VersionableEntity; import io.spine.server.entity.given.Given; @@ -32,7 +33,9 @@ import io.spine.server.entity.storage.given.ColumnTestEnv.EntityRedefiningColumnAnnotation; import io.spine.server.entity.storage.given.ColumnTestEnv.EntityWithDefaultColumnNameForStoring; import io.spine.server.entity.storage.given.ColumnTestEnv.TestEntity; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.lang.reflect.Method; @@ -52,36 +55,39 @@ public class ColumnShould { private static final String CUSTOM_COLUMN_NAME = " customColumnName "; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void be_serializable() { - final EntityColumn column = forMethod("getVersion", VersionableEntity.class); + EntityColumn column = forMethod("getVersion", VersionableEntity.class); reserializeAndAssert(column); } @Test public void support_toString() { - final EntityColumn column = forMethod("getVersion", VersionableEntity.class); + EntityColumn column = forMethod("getVersion", VersionableEntity.class); assertEquals("VersionableEntity.version", column.toString()); } @Test public void invoke_getter() { - final String entityId = "entity-id"; - final int version = 2; - final EntityColumn column = forMethod("getVersion", VersionableEntity.class); - final TestEntity entity = Given.entityOfClass(TestEntity.class) + String entityId = "entity-id"; + int version = 2; + EntityColumn column = forMethod("getVersion", VersionableEntity.class); + TestEntity entity = Given.entityOfClass(TestEntity.class) .withId(entityId) .withVersion(version) .build(); - final Version actualVersion = (Version) column.getFor(entity); + Version actualVersion = (Version) column.getFor(entity); assertEquals(version, actualVersion.getNumber()); } @Test public void have_equals_and_hashCode() { - final EntityColumn col1 = forMethod("getVersion", VersionableEntity.class); - final EntityColumn col2 = forMethod("getVersion", VersionableEntity.class); - final EntityColumn col3 = forMethod("isDeleted", EntityWithLifecycle.class); + EntityColumn col1 = forMethod("getVersion", VersionableEntity.class); + EntityColumn col2 = forMethod("getVersion", VersionableEntity.class); + EntityColumn col3 = forMethod("isDeleted", EntityWithLifecycle.class); new EqualsTester() .addEqualityGroup(col1, col2) .addEqualityGroup(col3) @@ -90,76 +96,86 @@ public void have_equals_and_hashCode() { @Test public void memoize_value_at_at_point_in_time() { - final EntityColumn mutableColumn = forMethod("getMutableState", TestEntity.class); - final TestEntity entity = new TestEntity(""); - final int initialState = 1; - final int changedState = 42; + EntityColumn mutableColumn = forMethod("getMutableState", TestEntity.class); + TestEntity entity = new TestEntity(""); + int initialState = 1; + int changedState = 42; entity.setMutableState(initialState); - final MemoizedValue memoizedState = mutableColumn.memoizeFor(entity); + MemoizedValue memoizedState = mutableColumn.memoizeFor(entity); entity.setMutableState(changedState); - final int extractedState = (int) mutableColumn.getFor(entity); + int extractedState = (int) mutableColumn.getFor(entity); - final Integer value = (Integer) memoizedState.getValue(); + Integer value = (Integer) memoizedState.getValue(); assertNotNull(value); assertEquals(initialState, value.intValue()); assertEquals(changedState, extractedState); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_be_constructed_from_non_getter() { + thrown.expect(IllegalArgumentException.class); forMethod("toString", Object.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_be_constructed_from_non_annotated_getter() { + thrown.expect(IllegalArgumentException.class); forMethod("getClass", Object.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_be_constructed_from_static_method() { + thrown.expect(IllegalArgumentException.class); forMethod("getStatic", TestEntity.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_be_constructed_from_private_getter() { + thrown.expect(IllegalArgumentException.class); forMethod("getFortyTwoLong", TestEntity.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_be_constructed_from_getter_with_parameters() throws NoSuchMethodException { - final Method method = TestEntity.class.getDeclaredMethod("getParameter", + Method method = TestEntity.class.getDeclaredMethod("getParameter", String.class); + thrown.expect(IllegalArgumentException.class); EntityColumn.from(method); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_construct_for_non_serializable_column() { + thrown.expect(IllegalArgumentException.class); forMethod("getFoo", BrokenTestEntity.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_get_value_from_wrong_object() { - final EntityColumn column = forMethod("getMutableState", TestEntity.class); + EntityColumn column = forMethod("getMutableState", TestEntity.class); + + thrown.expect(IllegalArgumentException.class); column.getFor(new EntityWithCustomColumnNameForStoring("")); } - @Test(expected = NullPointerException.class) + @Test public void check_value_if_getter_is_not_null() { - final EntityColumn column = forMethod("getNotNull", TestEntity.class); + EntityColumn column = forMethod("getNotNull", TestEntity.class); + + thrown.expect(NullPointerException.class); column.getFor(new TestEntity("")); } @Test public void allow_nulls_if_getter_is_nullable() { - final EntityColumn column = forMethod("getNull", TestEntity.class); - final Object value = column.getFor(new TestEntity("")); + EntityColumn column = forMethod("getNull", TestEntity.class); + Object value = column.getFor(new TestEntity("")); assertNull(value); } @Test public void tell_if_property_is_nullable() { - final EntityColumn notNullColumn = forMethod("getNotNull", TestEntity.class); - final EntityColumn nullableColumn = forMethod("getNull", TestEntity.class); + EntityColumn notNullColumn = forMethod("getNotNull", TestEntity.class); + EntityColumn nullableColumn = forMethod("getNull", TestEntity.class); assertFalse(notNullColumn.isNullable()); assertTrue(nullableColumn.isNullable()); @@ -167,29 +183,29 @@ public void tell_if_property_is_nullable() { @Test public void contain_property_type() { - final EntityColumn column = forMethod("getLong", TestEntity.class); + EntityColumn column = forMethod("getLong", TestEntity.class); assertEquals(Long.TYPE, column.getType()); } @Test public void memoize_value_regarding_nulls() { - final EntityColumn nullableColumn = forMethod("getNull", TestEntity.class); - final MemoizedValue memoizedNull = nullableColumn.memoizeFor(new TestEntity("")); + EntityColumn nullableColumn = forMethod("getNull", TestEntity.class); + MemoizedValue memoizedNull = nullableColumn.memoizeFor(new TestEntity("")); assertTrue(memoizedNull.isNull()); assertNull(memoizedNull.getValue()); } @Test public void memoize_value_which_has_reference_on_Column_itself() { - final EntityColumn column = forMethod("getMutableState", TestEntity.class); - final TestEntity entity = new TestEntity(""); - final MemoizedValue memoizedValue = column.memoizeFor(entity); + EntityColumn column = forMethod("getMutableState", TestEntity.class); + Entity entity = new TestEntity(""); + MemoizedValue memoizedValue = column.memoizeFor(entity); assertSame(column, memoizedValue.getSourceColumn()); } @Test public void have_valid_name_for_querying_and_storing() { - final EntityColumn column = forMethod("getValue", + EntityColumn column = forMethod("getValue", EntityWithCustomColumnNameForStoring.class); assertEquals("value", column.getName()); assertEquals(CUSTOM_COLUMN_NAME.trim(), column.getStoredName()); @@ -197,30 +213,31 @@ public void have_valid_name_for_querying_and_storing() { @Test public void have_same_names_for_and_querying_storing_if_last_is_not_specified() { - final EntityColumn column = forMethod("getValue", + EntityColumn column = forMethod("getValue", EntityWithDefaultColumnNameForStoring.class); - final String expectedName = "value"; + String expectedName = "value"; assertEquals(expectedName, column.getName()); assertEquals(expectedName, column.getStoredName()); } - @Test(expected = IllegalStateException.class) + @Test public void not_allow_redefine_column_annotation() { + thrown.expect(IllegalStateException.class); forMethod("getVersion", EntityRedefiningColumnAnnotation.class); } private static EntityColumn forMethod(String name, Class enclosingClass) { try { - final Method result = enclosingClass.getDeclaredMethod(name); + Method result = enclosingClass.getDeclaredMethod(name); return EntityColumn.from(result); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } - public static class EntityWithCustomColumnNameForStoring + private static class EntityWithCustomColumnNameForStoring extends AbstractVersionableEntity { - protected EntityWithCustomColumnNameForStoring(String id) { + private EntityWithCustomColumnNameForStoring(String id) { super(id); } diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java index a115afa2e1e..febfa0b4389 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java @@ -43,73 +43,73 @@ */ public class ColumnTypeRegistryShould { + private static EntityColumn mockProperty(Class cls) { + EntityColumn column = mock(EntityColumn.class); + when(column.getType()).thenReturn(cls); + return column; + } + @Test public void have_builder() { - final ColumnTypeRegistry.Builder builder = ColumnTypeRegistry.newBuilder(); + ColumnTypeRegistry.Builder builder = ColumnTypeRegistry.newBuilder(); assertNotNull(builder); } @Test public void have_default_empty_singleton_instance() { - final ColumnTypeRegistry emptyInstance = ColumnTypeRegistry.newBuilder() - .build(); + ColumnTypeRegistry emptyInstance = ColumnTypeRegistry.newBuilder() + .build(); assertEmpty(emptyInstance.getColumnTypeMap()); } @SuppressWarnings("MethodWithMultipleLoops") // OK for a test @Test public void store_column_types() { - final Collection classes = Arrays.asList(String.class, - Integer.class, - Date.class); - final ColumnTypeRegistry.Builder registryBuilder = - ColumnTypeRegistry.newBuilder(); + Collection classes = Arrays.asList(String.class, + Integer.class, + Date.class); + ColumnTypeRegistry.Builder registryBuilder = + ColumnTypeRegistry.newBuilder(); for (Class cls : classes) { - final ColumnType type = new AnyType(); + ColumnType type = new AnyType(); registryBuilder.put(cls, type); } - final ColumnTypeRegistry registry = registryBuilder.build(); + ColumnTypeRegistry registry = registryBuilder.build(); for (Class cls : classes) { - final ColumnType type = registry.get(mockProperty(cls)); + ColumnType type = registry.get(mockProperty(cls)); Verify.assertInstanceOf(AnyType.class, type); } } @Test public void find_closest_superclass_column_type() { - final ColumnTypeRegistry registry = + ColumnTypeRegistry registry = ColumnTypeRegistry.newBuilder() .put(GeneratedMessageV3.class, new GeneratedMessageType()) .put(AbstractMessage.class, new AbstractMessageType()) .build(); - final EntityColumn column = mockProperty(Any.class); - final ColumnType type = registry.get(column); + EntityColumn column = mockProperty(Any.class); + ColumnType type = registry.get(column); assertNotNull(type); assertThat(type, instanceOf(GeneratedMessageType.class)); } @Test public void map_primitives_autoboxed() { - final ColumnTypeRegistry registry = + ColumnTypeRegistry registry = ColumnTypeRegistry.newBuilder() .put(Integer.class, new IntegerType()) .build(); - final ColumnType integerColumnType = registry.get(mockProperty(Integer.class)); + ColumnType integerColumnType = registry.get(mockProperty(Integer.class)); assertNotNull(integerColumnType); - final ColumnType intColumnType = registry.get(mockProperty(int.class)); + ColumnType intColumnType = registry.get(mockProperty(int.class)); assertNotNull(intColumnType); assertEquals(integerColumnType, intColumnType); } - private static EntityColumn mockProperty(Class cls) { - final EntityColumn column = mock(EntityColumn.class); - when(column.getType()).thenReturn(cls); - return column; - } - private static class AnyType extends SimpleColumnType { @Override @@ -132,7 +132,8 @@ public String convertColumnValue(AbstractMessage fieldValue) { } @Override - public void setColumnValue(StringBuilder storageRecord, String value, String columnIdentifier) { + public void setColumnValue(StringBuilder storageRecord, String value, + String columnIdentifier) { storageRecord.append(value); } @@ -151,7 +152,8 @@ public String convertColumnValue(GeneratedMessageV3 fieldValue) { } @Override - public void setColumnValue(StringBuilder storageRecord, String value, String columnIdentifier) { + public void setColumnValue(StringBuilder storageRecord, String value, + String columnIdentifier) { storageRecord.append(value); } diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnsShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnsShould.java index c4eb0ca40dc..059d2fcda6d 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnsShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnsShould.java @@ -25,11 +25,14 @@ import com.google.protobuf.Any; import io.spine.server.entity.AbstractEntity; import io.spine.server.entity.Entity; +import io.spine.server.entity.storage.EntityColumn.MemoizedValue; import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithManyGetters; import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithNoStorageFields; import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithRepeatedColumnNames; import io.spine.server.entity.storage.given.ColumnsTestEnv.RealLifeEntity; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Map; @@ -52,6 +55,39 @@ public class ColumnsShould { private static final String STRING_ID = "some-string-id-never-used"; + @Rule + public ExpectedException thrown = ExpectedException.none(); + + /** + * Helper method that checks all {@link EntityWithManyGetters} field values. + * + *

Created to avoid code duplication, as {@link EntityWithManyGetters} is + * the main {@link Entity} class used to test + * {@linkplain Columns#extractColumnValues(Entity, Collection) column extraction} + * functionality. + */ + private + static void checkEntityWithManyGettersFields(EntityWithManyGetters entity, + Map fields) { + assertNotNull(fields); + + assertSize(3, fields); + + String floatNullKey = "floatNull"; + MemoizedValue floatMemoizedNull = fields.get(floatNullKey); + assertNotNull(floatMemoizedNull); + assertNull(floatMemoizedNull.getValue()); + + assertEquals(entity.getIntegerFieldValue(), + fields.get(CUSTOM_COLUMN_NAME) + .getValue()); + + String messageKey = "someMessage"; + assertEquals(entity.getSomeMessage(), + fields.get(messageKey) + .getValue()); + } + @Test public void have_private_utility_ctor() { assertHasPrivateParameterlessCtor(Columns.class); @@ -64,79 +100,54 @@ public void pass_null_check() { @Test public void get_all_valid_columns_for_entity_class() { - final Collection entityColumns = getAllColumns(EntityWithManyGetters.class); + Collection entityColumns = getAllColumns(EntityWithManyGetters.class); assertNotNull(entityColumns); assertSize(3, entityColumns); } - @Test(expected = IllegalStateException.class) + @Test public void fail_to_obtain_columns_for_invalid_entity_class() { + thrown.expect(IllegalStateException.class); getAllColumns(EntityWithRepeatedColumnNames.class); } @Test public void retrieve_specific_column_metadata_from_given_class() { - final Class> entityClass = RealLifeEntity.class; - final String existingColumnName = archived.name(); - final EntityColumn archivedColumn = findColumn(entityClass, existingColumnName); + Class> entityClass = RealLifeEntity.class; + String existingColumnName = archived.name(); + EntityColumn archivedColumn = findColumn(entityClass, existingColumnName); assertNotNull(archivedColumn); assertEquals(existingColumnName, archivedColumn.getName()); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_retrieve_non_existing_column() { - final Class> entityClass = EntityWithNoStorageFields.class; - final String nonExistingColumnName = "foo"; + Class> entityClass = EntityWithNoStorageFields.class; + String nonExistingColumnName = "foo"; + + thrown.expect(IllegalArgumentException.class); findColumn(entityClass, nonExistingColumnName); } @Test public void extract_column_values_with_names_for_storing() { - final EntityWithManyGetters entity = new EntityWithManyGetters(STRING_ID); - final Collection entityColumns = getAllColumns(entity.getClass()); - final Map fields = extractColumnValues(entity, entityColumns); + EntityWithManyGetters entity = new EntityWithManyGetters(STRING_ID); + Collection entityColumns = getAllColumns(entity.getClass()); + Map fields = extractColumnValues(entity, entityColumns); checkEntityWithManyGettersFields(entity, fields); } @Test public void extract_column_values_using_predefined_columns() { - final EntityWithManyGetters entity = new EntityWithManyGetters(STRING_ID); - final Collection entityColumns = getAllColumns(entity.getClass()); - final Map fields = extractColumnValues(entity, entityColumns); + EntityWithManyGetters entity = new EntityWithManyGetters(STRING_ID); + Collection entityColumns = getAllColumns(entity.getClass()); + Map fields = extractColumnValues(entity, entityColumns); checkEntityWithManyGettersFields(entity, fields); } - /** - * Helper method that checks all {@link EntityWithManyGetters} field values. - * - *

Created to avoid code duplication, as {@link EntityWithManyGetters} is the main {@link Entity} - * class used to test {@linkplain Columns#extractColumnValues(Entity, Collection) column extraction} - * functionality. - */ - private static void checkEntityWithManyGettersFields(EntityWithManyGetters entity, - Map fields) { - assertNotNull(fields); - - assertSize(3, fields); - - final String floatNullKey = "floatNull"; - final EntityColumn.MemoizedValue floatMemoizedNull = fields.get(floatNullKey); - assertNotNull(floatMemoizedNull); - assertNull(floatMemoizedNull.getValue()); - - assertEquals(entity.getIntegerFieldValue(), - fields.get(CUSTOM_COLUMN_NAME) - .getValue()); - - final String messageKey = "someMessage"; - assertEquals(entity.getSomeMessage(), - fields.get(messageKey) - .getValue()); - } - @SuppressWarnings("unused") // Reflective access private static class PrivateEntity extends AbstractEntity { protected PrivateEntity(String id) { diff --git a/server/src/test/java/io/spine/server/entity/storage/CompositeQueryParameterShould.java b/server/src/test/java/io/spine/server/entity/storage/CompositeQueryParameterShould.java index a5a0a45f3bf..8f00d129c47 100644 --- a/server/src/test/java/io/spine/server/entity/storage/CompositeQueryParameterShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/CompositeQueryParameterShould.java @@ -27,7 +27,9 @@ import io.spine.client.ColumnFilter; import io.spine.server.entity.AbstractVersionableEntity; import io.spine.server.entity.Entity; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static com.google.common.collect.ImmutableMultimap.of; import static com.google.common.collect.Lists.newArrayList; @@ -50,6 +52,9 @@ */ public class CompositeQueryParameterShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void not_accept_nulls_on_construction() { new NullPointerTester() @@ -58,81 +63,80 @@ public void not_accept_nulls_on_construction() { @Test public void be_serializable() { - final ImmutableMultimap filters = ImmutableMultimap.of(); - final CompositeQueryParameter parameter = from(filters, ALL); + ImmutableMultimap filters = ImmutableMultimap.of(); + CompositeQueryParameter parameter = from(filters, ALL); SerializableTester.reserializeAndAssert(parameter); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_construct_for_invalid_operator() { - from(ImmutableMultimap.of(), CCF_CO_UNDEFINED); + thrown.expect(IllegalArgumentException.class); + from(ImmutableMultimap.of(), CCF_CO_UNDEFINED); } @Test public void merge_with_other_instances() { - final Class cls = AbstractVersionableEntity.class; - - final String archivedColumnName = archived.name(); - final String deletedColumnName = deleted.name(); - final String versionColumnName = version.name(); - - final EntityColumn archivedColumn = findColumn(cls, archivedColumnName); - final EntityColumn deletedColumn = findColumn(cls, deletedColumnName); - final EntityColumn versionColumn = findColumn(cls, versionColumnName); - - final ColumnFilter archived = eq(archivedColumnName, true); - final ColumnFilter deleted = eq(archivedColumnName, false); - final ColumnFilter versionLower = ge(archivedColumnName, 2); - final ColumnFilter versionUpper = lt(archivedColumnName, 10); - - final CompositeQueryParameter lifecycle = from(of(archivedColumn, archived, - deletedColumn, deleted), - ALL); - final CompositeQueryParameter versionLowerBound = from(of(versionColumn, versionLower), - ALL); - final CompositeQueryParameter versionUpperBound = from(of(versionColumn, versionUpper), - ALL); + Class cls = AbstractVersionableEntity.class; + + String archivedColumnName = archived.name(); + String deletedColumnName = deleted.name(); + String versionColumnName = version.name(); + + EntityColumn archivedColumn = findColumn(cls, archivedColumnName); + EntityColumn deletedColumn = findColumn(cls, deletedColumnName); + EntityColumn versionColumn = findColumn(cls, versionColumnName); + + ColumnFilter archived = eq(archivedColumnName, true); + ColumnFilter deleted = eq(archivedColumnName, false); + ColumnFilter versionLower = ge(archivedColumnName, 2); + ColumnFilter versionUpper = lt(archivedColumnName, 10); + + CompositeQueryParameter lifecycle = + from(of(archivedColumn, archived, deletedColumn, deleted), ALL); + CompositeQueryParameter versionLowerBound = + from(of(versionColumn, versionLower), ALL); + CompositeQueryParameter versionUpperBound = + from(of(versionColumn, versionUpper), ALL); // Merge the instances - final CompositeQueryParameter all = lifecycle.conjunct(newArrayList(versionLowerBound, - versionUpperBound)); + CompositeQueryParameter all = + lifecycle.conjunct(newArrayList(versionLowerBound, versionUpperBound)); // Check assertEquals(all.getOperator(), ALL); - final Multimap asMultimp = all.getFilters(); - assertContainsAll(asMultimp.get(versionColumn), versionLower, versionUpper); - assertContainsAll(asMultimp.get(archivedColumn), archived); - assertContainsAll(asMultimp.get(deletedColumn), deleted); + Multimap asMultimap = all.getFilters(); + assertContainsAll(asMultimap.get(versionColumn), versionLower, versionUpper); + assertContainsAll(asMultimap.get(archivedColumn), archived); + assertContainsAll(asMultimap.get(deletedColumn), deleted); } @Test public void merge_with_single_filter() { - final Class cls = AbstractVersionableEntity.class; + Class cls = AbstractVersionableEntity.class; - final String archivedColumnName = archived.name(); - final String deletedColumnName = deleted.name(); - final String versionColumnName = version.name(); + String archivedColumnName = archived.name(); + String deletedColumnName = deleted.name(); + String versionColumnName = version.name(); - final EntityColumn archivedColumn = findColumn(cls, archivedColumnName); - final EntityColumn deletedColumn = findColumn(cls, deletedColumnName); - final EntityColumn versionColumn = findColumn(cls, versionColumnName); + EntityColumn archivedColumn = findColumn(cls, archivedColumnName); + EntityColumn deletedColumn = findColumn(cls, deletedColumnName); + EntityColumn versionColumn = findColumn(cls, versionColumnName); - final ColumnFilter archived = eq(archivedColumnName, false); - final ColumnFilter deleted = eq(archivedColumnName, false); - final ColumnFilter version = ge(archivedColumnName, 4); + ColumnFilter archived = eq(archivedColumnName, false); + ColumnFilter deleted = eq(archivedColumnName, false); + ColumnFilter version = ge(archivedColumnName, 4); - final CompositeQueryParameter lifecycle = from(of(archivedColumn, archived, - deletedColumn, deleted), - ALL); + CompositeQueryParameter lifecycle = + from(of(archivedColumn, archived, deletedColumn, deleted), ALL); // Merge the instances - final CompositeQueryParameter all = lifecycle.and(versionColumn, version); + CompositeQueryParameter all = lifecycle.and(versionColumn, version); // Check assertEquals(all.getOperator(), ALL); - final Multimap asMultimp = all.getFilters(); - assertContainsAll(asMultimp.get(versionColumn), version); - assertContainsAll(asMultimp.get(archivedColumn), archived); - assertContainsAll(asMultimp.get(deletedColumn), deleted); + Multimap asMultimap = all.getFilters(); + assertContainsAll(asMultimap.get(versionColumn), version); + assertContainsAll(asMultimap.get(archivedColumn), archived); + assertContainsAll(asMultimap.get(deletedColumn), deleted); } } diff --git a/server/src/test/java/io/spine/server/entity/storage/EntityColumnCacheShould.java b/server/src/test/java/io/spine/server/entity/storage/EntityColumnCacheShould.java index 21ce086cd1f..fde2be6603b 100644 --- a/server/src/test/java/io/spine/server/entity/storage/EntityColumnCacheShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/EntityColumnCacheShould.java @@ -24,7 +24,9 @@ import io.spine.server.entity.Entity; import io.spine.server.entity.storage.given.ColumnsTestEnv.EntityWithManyGetters; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.ArrayList; import java.util.Collection; @@ -46,10 +48,12 @@ public class EntityColumnCacheShould { private Class entityClass; private EntityColumnCache entityColumnCache; + @Rule + public ExpectedException thrown = ExpectedException.none(); @Before public void setUp() { - final Entity entity = new EntityWithManyGetters(STRING_ID); + Entity entity = new EntityWithManyGetters(STRING_ID); entityClass = entity.getClass(); entityColumnCache = EntityColumnCache.initializeFor(entityClass); } @@ -65,15 +69,16 @@ public void stay_empty_after_creation() { assertTrue(entityColumnCache.isEmpty()); } + @SuppressWarnings("CheckReturnValue") + // This test does not use the found columns, but simply checks that they are found. @Test public void cache_columns_on_first_access() { - final EntityColumnCache cacheForGetAll = EntityColumnCache.initializeFor(entityClass); + EntityColumnCache cacheForGetAll = EntityColumnCache.initializeFor(entityClass); cacheForGetAll.getColumns(); assertFalse(cacheForGetAll.isEmpty()); - final EntityColumnCache cacheForFind = EntityColumnCache.initializeFor(entityClass); - final String floatNullKey = "floatNull"; - cacheForFind.findColumn(floatNullKey); + EntityColumnCache cacheForFind = EntityColumnCache.initializeFor(entityClass); + cacheForFind.findColumn("floatNull"); assertFalse(cacheForFind.isEmpty()); } @@ -85,31 +90,32 @@ public void allow_to_forcefully_cache_columns() { @Test public void retrieve_column_metadata_from_given_class() { - final String existingColumnName = "floatNull"; - final EntityColumn retrievedColumn = entityColumnCache.findColumn(existingColumnName); + String existingColumnName = "floatNull"; + EntityColumn retrievedColumn = entityColumnCache.findColumn(existingColumnName); assertNotNull(retrievedColumn); assertEquals(existingColumnName, retrievedColumn.getName()); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_retrieve_non_existing_column() { - final String nonExistingColumnName = "foo"; + String nonExistingColumnName = "foo"; + thrown.expect(IllegalArgumentException.class); entityColumnCache.findColumn(nonExistingColumnName); } @Test public void retain_stored_columns_order() { - final Collection columnsFromCache = entityColumnCache.getColumns(); + Collection columnsFromCache = entityColumnCache.getColumns(); assertNotNull(columnsFromCache); - final Collection columnsViaUtil = getAllColumns(entityClass); + Collection columnsViaUtil = getAllColumns(entityClass); - final int columnsFromCacheSize = columnsFromCache.size(); - final int columnsViaUtilSize = columnsViaUtil.size(); + int columnsFromCacheSize = columnsFromCache.size(); + int columnsViaUtilSize = columnsViaUtil.size(); assertEquals(columnsViaUtilSize, columnsFromCacheSize); - final List columnsFromCacheList = new ArrayList(columnsFromCache); - final List columnsViaUtilList = new ArrayList(columnsViaUtil); + List columnsFromCacheList = new ArrayList<>(columnsFromCache); + List columnsViaUtilList = new ArrayList<>(columnsViaUtil); assertEquals(columnsViaUtilList.get(0), columnsFromCacheList.get(0)); assertEquals(columnsViaUtilList.get(1), columnsFromCacheList.get(1)); diff --git a/server/src/test/java/io/spine/server/entity/storage/EntityQueriesShould.java b/server/src/test/java/io/spine/server/entity/storage/EntityQueriesShould.java index 3f8fd9ecd7d..d8ee14c4ebe 100644 --- a/server/src/test/java/io/spine/server/entity/storage/EntityQueriesShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/EntityQueriesShould.java @@ -34,10 +34,13 @@ import io.spine.server.entity.AbstractEntity; import io.spine.server.entity.AbstractVersionableEntity; import io.spine.server.entity.Entity; +import io.spine.server.storage.LifecycleFlagField; import io.spine.server.storage.RecordStorage; import io.spine.test.storage.ProjectId; import io.spine.testdata.Sample; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Collections; @@ -46,6 +49,7 @@ import static com.google.common.collect.Iterators.size; import static com.google.common.collect.Lists.newArrayList; import static io.spine.client.CompositeColumnFilter.CompositeOperator.EITHER; +import static io.spine.server.entity.storage.EntityQueries.from; import static io.spine.server.storage.EntityField.version; import static io.spine.server.storage.LifecycleFlagField.archived; import static io.spine.test.Tests.assertHasPrivateParameterlessCtor; @@ -61,110 +65,136 @@ */ public class EntityQueriesShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static EntityQuery createEntityQuery(EntityFilters filters, + Class entityClass) { + Collection entityColumns = Columns.getAllColumns(entityClass); + return from(filters, entityColumns); + } + @Test public void have_private_utility_ctor() { assertHasPrivateParameterlessCtor(EntityQueries.class); } - @SuppressWarnings("ConstantConditions") // The purpose of the check is passing null for @NotNull field. - @Test(expected = NullPointerException.class) + @SuppressWarnings("ConstantConditions") + // The purpose of the check is passing null for @NotNull field. + @Test public void not_accept_null_filters() { - EntityQueries.from(null, Collections.emptyList()); + thrown.expect(NullPointerException.class); + from(null, Collections.emptyList()); } - @SuppressWarnings("ConstantConditions") // The purpose of the check is passing null for @NotNull field. - @Test(expected = NullPointerException.class) + @SuppressWarnings("ConstantConditions") + // The purpose of the check is passing null for @NotNull field. + @Test public void not_accept_null_storage() { - final RecordStorage storage = null; - EntityQueries.from(EntityFilters.getDefaultInstance(), storage); + RecordStorage storage = null; + thrown.expect(NullPointerException.class); + from(EntityFilters.getDefaultInstance(), storage); } - @SuppressWarnings("ConstantConditions") // The purpose of the check is passing null for @NotNull field. - @Test(expected = NullPointerException.class) + @SuppressWarnings("ConstantConditions") + // The purpose of the check is passing null for @NotNull field. + @Test public void not_accept_null_entity_class() { - final Collection entityColumns = null; - EntityQueries.from(EntityFilters.getDefaultInstance(), entityColumns); + Collection entityColumns = null; + thrown.expect(NullPointerException.class); + from(EntityFilters.getDefaultInstance(), entityColumns); } - @Test(expected = IllegalArgumentException.class) + @Test public void check_filter_type() { // Boolean EntityColumn queried for for an Integer value - final ColumnFilter filter = ColumnFilters.gt(archived.name(), 42); - final CompositeColumnFilter compositeFilter = ColumnFilters.all(filter); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(compositeFilter) - .build(); + ColumnFilter filter = ColumnFilters.gt(archived.name(), 42); + CompositeColumnFilter compositeFilter = ColumnFilters.all(filter); + EntityFilters filters = + EntityFilters.newBuilder() + .addFilter(compositeFilter) + .build(); + + thrown.expect(IllegalArgumentException.class); createEntityQuery(filters, AbstractVersionableEntity.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_create_query_for_non_existing_column() { - final ColumnFilter filter = ColumnFilters.eq("nonExistingColumn", 42); - final CompositeColumnFilter compositeFilter = ColumnFilters.all(filter); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(compositeFilter) - .build(); + ColumnFilter filter = ColumnFilters.eq("nonExistingColumn", 42); + CompositeColumnFilter compositeFilter = ColumnFilters.all(filter); + EntityFilters filters = + EntityFilters.newBuilder() + .addFilter(compositeFilter) + .build(); + + thrown.expect(IllegalArgumentException.class); createEntityQuery(filters, AbstractVersionableEntity.class); } @Test public void construct_empty_queries() { - final EntityFilters filters = EntityFilters.getDefaultInstance(); - final EntityQuery query = createEntityQuery(filters, AbstractEntity.class); + EntityFilters filters = EntityFilters.getDefaultInstance(); + EntityQuery query = createEntityQuery(filters, AbstractEntity.class); assertNotNull(query); - assertEquals(0, size(query.getParameters().iterator())); - assertTrue(query.getIds().isEmpty()); + assertEquals(0, size(query.getParameters() + .iterator())); + assertTrue(query.getIds() + .isEmpty()); } @Test public void construct_non_empty_queries() { - final Message someGenericId = Sample.messageOfType(ProjectId.class); - final Any someId = AnyPacker.pack(someGenericId); - final EntityId entityId = EntityId.newBuilder() - .setId(someId) - .build(); - final EntityIdFilter idFilter = EntityIdFilter.newBuilder() - .addIds(entityId) - .build(); - final Version versionValue = Version.newBuilder() - .setNumber(1) - .build(); - final BoolValue archivedValue = BoolValue.newBuilder() - .setValue(true) - .build(); - final ColumnFilter versionFilter = ColumnFilters.eq(version.name(), versionValue); - final ColumnFilter archivedFilter = ColumnFilters.eq(archived.name(), archivedValue); - final CompositeColumnFilter aggregatingFilter = - CompositeColumnFilter.newBuilder() - .addFilter(versionFilter) - .addFilter(archivedFilter) - .setOperator(EITHER) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .setIdFilter(idFilter) - .addFilter(aggregatingFilter) - .build(); - final EntityQuery query = createEntityQuery(filters, AbstractVersionableEntity.class); + Message someGenericId = Sample.messageOfType(ProjectId.class); + Any someId = AnyPacker.pack(someGenericId); + EntityId entityId = EntityId + .newBuilder() + .setId(someId) + .build(); + EntityIdFilter idFilter = EntityIdFilter + .newBuilder() + .addIds(entityId) + .build(); + Version v1 = Version + .newBuilder() + .setNumber(1) + .build(); + BoolValue archived = BoolValue + .newBuilder() + .setValue(true) + .build(); + ColumnFilter versionFilter = ColumnFilters + .eq(version.name(), v1); + ColumnFilter archivedFilter = ColumnFilters + .eq(LifecycleFlagField.archived.name(), archived); + CompositeColumnFilter aggregatingFilter = CompositeColumnFilter + .newBuilder() + .addFilter(versionFilter) + .addFilter(archivedFilter) + .setOperator(EITHER) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .setIdFilter(idFilter) + .addFilter(aggregatingFilter) + .build(); + EntityQuery query = createEntityQuery(filters, AbstractVersionableEntity.class); assertNotNull(query); - final Collection ids = query.getIds(); + Collection ids = query.getIds(); assertFalse(ids.isEmpty()); assertSize(1, ids); - final Object singleId = ids.iterator().next(); + Object singleId = ids.iterator() + .next(); assertEquals(someGenericId, singleId); - final List values = newArrayList(query.getParameters()); + List values = newArrayList(query.getParameters()); assertSize(1, values); - final CompositeQueryParameter singleParam = values.get(0); - final Collection columnFilters = singleParam.getFilters() - .values(); + CompositeQueryParameter singleParam = values.get(0); + Collection columnFilters = singleParam.getFilters() + .values(); assertEquals(EITHER, singleParam.getOperator()); assertContains(versionFilter, columnFilters); assertContains(archivedFilter, columnFilters); } - - private static EntityQuery createEntityQuery(EntityFilters filters, Class entityClass) { - final Collection entityColumns = Columns.getAllColumns(entityClass); - return EntityQueries.from(filters, entityColumns); - } } diff --git a/server/src/test/java/io/spine/server/entity/storage/EntityRecordWithColumnsShould.java b/server/src/test/java/io/spine/server/entity/storage/EntityRecordWithColumnsShould.java index ec7d9ce2d4a..30e25dfdf66 100644 --- a/server/src/test/java/io/spine/server/entity/storage/EntityRecordWithColumnsShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/EntityRecordWithColumnsShould.java @@ -31,7 +31,9 @@ import io.spine.server.entity.given.Given; import io.spine.test.entity.Project; import io.spine.testdata.Sample; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Collections; @@ -56,32 +58,43 @@ */ public class EntityRecordWithColumnsShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static EntityRecordWithColumns newRecord() { + return of(Sample.messageOfType(EntityRecord.class), + Collections.emptyMap()); + } + + private static EntityRecordWithColumns newEmptyRecord() { + return of(EntityRecord.getDefaultInstance()); + } + @Test public void be_serializable() { - final EntityRecord record = Sample.messageOfType(EntityRecord.class); - final VersionableEntity entity = Given.entityOfClass(TestEntity.class) - .withVersion(1) - .build(); - final String columnName = version.name(); - final EntityColumn column = findColumn(VersionableEntity.class, columnName); - final MemoizedValue value = column.memoizeFor(entity); - - final Map columns = singletonMap(columnName, value); - final EntityRecordWithColumns recordWithColumns = of(record, columns); + EntityRecord record = Sample.messageOfType(EntityRecord.class); + VersionableEntity entity = Given.entityOfClass(TestEntity.class) + .withVersion(1) + .build(); + String columnName = version.name(); + EntityColumn column = findColumn(VersionableEntity.class, columnName); + MemoizedValue value = column.memoizeFor(entity); + + Map columns = singletonMap(columnName, value); + EntityRecordWithColumns recordWithColumns = of(record, columns); reserializeAndAssert(recordWithColumns); } @Test public void initialize_with_record_and_storage_fields() { - final EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance(), - Collections.emptyMap()); + EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance(), + Collections.emptyMap()); assertNotNull(record); } @Test public void initialize_with_record_only() { - final EntityRecordWithColumns record = - of(EntityRecord.getDefaultInstance()); + EntityRecordWithColumns record = newEmptyRecord(); assertNotNull(record); } @@ -94,19 +107,19 @@ public void not_accept_nulls_in_ctor() { @Test public void store_record() { - final EntityRecordWithColumns recordWithFields = newRecord(); - final EntityRecord record = recordWithFields.getRecord(); + EntityRecordWithColumns recordWithFields = newRecord(); + EntityRecord record = recordWithFields.getRecord(); assertNotNull(record); } @Test public void store_column_values() { - final MemoizedValue mockValue = mock(MemoizedValue.class); - final String columnName = "some-key"; - final Map columnsExpected = singletonMap(columnName, mockValue); - final EntityRecordWithColumns record = of(Sample.messageOfType(EntityRecord.class), - columnsExpected); - final Collection columnNames = record.getColumnNames(); + MemoizedValue mockValue = mock(MemoizedValue.class); + String columnName = "some-key"; + Map columnsExpected = singletonMap(columnName, mockValue); + EntityRecordWithColumns record = of(Sample.messageOfType(EntityRecord.class), + columnsExpected); + Collection columnNames = record.getColumnNames(); assertSize(1, columnNames); assertTrue(columnNames.contains(columnName)); assertEquals(mockValue, record.getColumnValue(columnName)); @@ -114,41 +127,41 @@ public void store_column_values() { @Test public void return_empty_names_collection_if_no_storage_fields() { - final EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance()); + EntityRecordWithColumns record = newEmptyRecord(); assertFalse(record.hasColumns()); - final Collection names = record.getColumnNames(); + Collection names = record.getColumnNames(); assertTrue(names.isEmpty()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_on_attempt_to_get_value_by_non_existent_name() { - final EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance()); + EntityRecordWithColumns record = newEmptyRecord(); + + thrown.expect(IllegalStateException.class); record.getColumnValue(""); } @Test public void not_have_columns_if_values_list_is_empty() { - final EntityWithoutColumns entity = new EntityWithoutColumns("ID"); - final Class entityClass = entity.getClass(); - final Collection entityColumns = Columns.getAllColumns(entityClass); - final Map columnValues = extractColumnValues(entity, entityColumns); + EntityWithoutColumns entity = new EntityWithoutColumns("ID"); + Class entityClass = entity.getClass(); + Collection entityColumns = Columns.getAllColumns(entityClass); + Map columnValues = extractColumnValues(entity, entityColumns); assertTrue(columnValues.isEmpty()); - final EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance(), columnValues); + EntityRecordWithColumns record = of(EntityRecord.getDefaultInstance(), columnValues); assertFalse(record.hasColumns()); } @Test public void have_equals() { - final MemoizedValue mockValue = mock(MemoizedValue.class); - final EntityRecordWithColumns noFieldsEnvelope = - of(EntityRecord.getDefaultInstance() - ); - final EntityRecordWithColumns emptyFieldsEnvelope = of( + MemoizedValue mockValue = mock(MemoizedValue.class); + EntityRecordWithColumns noFieldsEnvelope = newEmptyRecord(); + EntityRecordWithColumns emptyFieldsEnvelope = of( EntityRecord.getDefaultInstance(), - Collections.emptyMap() + Collections.emptyMap() ); - final EntityRecordWithColumns notEmptyFieldsEnvelope = + EntityRecordWithColumns notEmptyFieldsEnvelope = of( EntityRecord.getDefaultInstance(), singletonMap("key", mockValue) @@ -160,20 +173,15 @@ public void have_equals() { .testEquals(); } - private static EntityRecordWithColumns newRecord() { - return of(Sample.messageOfType(EntityRecord.class), - Collections.emptyMap()); - } - - public static class TestEntity extends AbstractVersionableEntity { + private static class TestEntity extends AbstractVersionableEntity { - protected TestEntity(String id) { + private TestEntity(String id) { super(id); } } - public static class EntityWithoutColumns extends AbstractEntity { - protected EntityWithoutColumns(String id) { + private static class EntityWithoutColumns extends AbstractEntity { + private EntityWithoutColumns(String id) { super(id); } } diff --git a/server/src/test/java/io/spine/server/route/EventRoutingShould.java b/server/src/test/java/io/spine/server/route/EventRoutingShould.java index 28a0675aeb3..38c95946866 100644 --- a/server/src/test/java/io/spine/server/route/EventRoutingShould.java +++ b/server/src/test/java/io/spine/server/route/EventRoutingShould.java @@ -63,6 +63,7 @@ public class EventRoutingShould { private static final long serialVersionUID = 0L; + @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType") // return immutable instance @Override public Set apply(StringValue message, EventContext context) { return CUSTOM_ROUTE; diff --git a/server/src/test/java/io/spine/server/route/given/switchman/Log.java b/server/src/test/java/io/spine/server/route/given/switchman/Log.java index b4c7efb8ca4..eeb01f69c33 100644 --- a/server/src/test/java/io/spine/server/route/given/switchman/Log.java +++ b/server/src/test/java/io/spine/server/route/given/switchman/Log.java @@ -89,10 +89,13 @@ void event(SwitchWorkRecorded event) { /** * The repository with default routing functions that route to the singleton aggregate. */ - @SuppressWarnings("SerializableInnerClassWithNonSerializableOuterClass") + @SuppressWarnings({ + "SerializableInnerClassWithNonSerializableOuterClass", + "AssignmentOrReturnOfFieldWithMutableType" // returning immutable impl. + }) public static final class Repository extends AggregateRepository { - private static final Set SINGLETON_ID_SET = ImmutableSet.of(ID); + private static final ImmutableSet SINGLETON_ID_SET = ImmutableSet.of(ID); public Repository() { super(); diff --git a/server/src/test/java/io/spine/server/route/given/switchman/Switchman.java b/server/src/test/java/io/spine/server/route/given/switchman/Switchman.java index ffbd471517c..db281911136 100644 --- a/server/src/test/java/io/spine/server/route/given/switchman/Switchman.java +++ b/server/src/test/java/io/spine/server/route/given/switchman/Switchman.java @@ -49,6 +49,7 @@ SwitchPositionConfirmed on(SetSwitch cmd) { .build(); } + @SuppressWarnings("CheckReturnValue") // calling builder @Apply void event(SwitchPositionConfirmed event) { getBuilder().setValue(getState().getValue() + 1); diff --git a/server/src/test/java/io/spine/server/route/given/switchman/SwitchmanBureau.java b/server/src/test/java/io/spine/server/route/given/switchman/SwitchmanBureau.java index 3845cab5132..8620a9f3969 100644 --- a/server/src/test/java/io/spine/server/route/given/switchman/SwitchmanBureau.java +++ b/server/src/test/java/io/spine/server/route/given/switchman/SwitchmanBureau.java @@ -36,6 +36,8 @@ public final class SwitchmanBureau extends AggregateRepository() { diff --git a/server/src/test/java/io/spine/server/tuple/EitherOfFiveShould.java b/server/src/test/java/io/spine/server/tuple/EitherOfFiveShould.java index 9028e8e4d89..2dcceec0edb 100644 --- a/server/src/test/java/io/spine/server/tuple/EitherOfFiveShould.java +++ b/server/src/test/java/io/spine/server/tuple/EitherOfFiveShould.java @@ -31,7 +31,9 @@ import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -61,6 +63,9 @@ public class EitherOfFiveShould { private EitherOfFive eitherWithD; private EitherOfFive eitherWithE; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { eitherWithA = EitherOfFive.withA(a); @@ -140,83 +145,99 @@ public void serialize() { reserializeAndAssert(eitherWithE); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_B() { + thrown.expect(IllegalStateException.class); eitherWithA.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_C() { + thrown.expect(IllegalStateException.class); eitherWithA.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_D() { + thrown.expect(IllegalStateException.class); eitherWithA.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_E() { + thrown.expect(IllegalStateException.class); eitherWithA.getE(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_A() { + thrown.expect(IllegalStateException.class); eitherWithB.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_C() { + thrown.expect(IllegalStateException.class); eitherWithB.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_D() { + thrown.expect(IllegalStateException.class); eitherWithB.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_E() { + thrown.expect(IllegalStateException.class); eitherWithB.getE(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_A() { + thrown.expect(IllegalStateException.class); eitherWithC.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_B() { + thrown.expect(IllegalStateException.class); eitherWithC.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_D() { + thrown.expect(IllegalStateException.class); eitherWithC.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_E() { + thrown.expect(IllegalStateException.class); eitherWithC.getE(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_A() { + thrown.expect(IllegalStateException.class); eitherWithD.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_B() { + thrown.expect(IllegalStateException.class); eitherWithD.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_C() { + thrown.expect(IllegalStateException.class); eitherWithD.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_E() { + thrown.expect(IllegalStateException.class); eitherWithD.getE(); } } diff --git a/server/src/test/java/io/spine/server/tuple/EitherOfFourShould.java b/server/src/test/java/io/spine/server/tuple/EitherOfFourShould.java index 2121bf80250..ae87e9f16bb 100644 --- a/server/src/test/java/io/spine/server/tuple/EitherOfFourShould.java +++ b/server/src/test/java/io/spine/server/tuple/EitherOfFourShould.java @@ -30,7 +30,9 @@ import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -56,6 +58,9 @@ public class EitherOfFourShould { private EitherOfFour eitherWithC; private EitherOfFour eitherWithD; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { eitherWithA = EitherOfFour.withA(a); @@ -117,63 +122,75 @@ public void return_only_one_value_in_iteration() { assertFalse(iteratorD.hasNext()); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_B() { + thrown.expect(IllegalStateException.class); eitherWithA.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_C() { + thrown.expect(IllegalStateException.class); eitherWithA.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_D() { + thrown.expect(IllegalStateException.class); eitherWithA.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_A() { + thrown.expect(IllegalStateException.class); eitherWithB.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_C() { + thrown.expect(IllegalStateException.class); eitherWithB.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_D() { + thrown.expect(IllegalStateException.class); eitherWithB.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_A() { + thrown.expect(IllegalStateException.class); eitherWithC.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_B() { + thrown.expect(IllegalStateException.class); eitherWithC.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_D() { + thrown.expect(IllegalStateException.class); eitherWithC.getD(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_A() { + thrown.expect(IllegalStateException.class); eitherWithD.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_B() { + thrown.expect(IllegalStateException.class); eitherWithD.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_D_C() { + thrown.expect(IllegalStateException.class); eitherWithD.getC(); } diff --git a/server/src/test/java/io/spine/server/tuple/EitherOfThreeShould.java b/server/src/test/java/io/spine/server/tuple/EitherOfThreeShould.java index 44f48fc8e7f..0ca04dc1423 100644 --- a/server/src/test/java/io/spine/server/tuple/EitherOfThreeShould.java +++ b/server/src/test/java/io/spine/server/tuple/EitherOfThreeShould.java @@ -29,7 +29,9 @@ import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -53,6 +55,9 @@ public class EitherOfThreeShould { private EitherOfThree eitherWithB; private EitherOfThree eitherWithC; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { eitherWithA = EitherOfThree.withA(a); @@ -105,33 +110,39 @@ public void return_only_one_value_in_iteration() { assertFalse(iteratorC.hasNext()); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_B() { + thrown.expect(IllegalStateException.class); eitherWithA.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A_C() { + thrown.expect(IllegalStateException.class); eitherWithA.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_A() { + thrown.expect(IllegalStateException.class); eitherWithB.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B_C() { + thrown.expect(IllegalStateException.class); eitherWithB.getC(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_A() { + thrown.expect(IllegalStateException.class); eitherWithC.getA(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_C_B() { + thrown.expect(IllegalStateException.class); eitherWithC.getB(); } diff --git a/server/src/test/java/io/spine/server/tuple/EitherOfTwoShould.java b/server/src/test/java/io/spine/server/tuple/EitherOfTwoShould.java index 6e0634ebc64..1233da358e3 100644 --- a/server/src/test/java/io/spine/server/tuple/EitherOfTwoShould.java +++ b/server/src/test/java/io/spine/server/tuple/EitherOfTwoShould.java @@ -28,7 +28,9 @@ import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -48,6 +50,9 @@ public class EitherOfTwoShould { private EitherOfTwo eitherWithA; private EitherOfTwo eitherWithB; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { eitherWithA = EitherOfTwo.withA(a); @@ -91,13 +96,15 @@ public void return_only_one_value_in_iteration() { assertFalse(iteratorB.hasNext()); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_B() { + thrown.expect(IllegalStateException.class); eitherWithA.getB(); } - @Test(expected = IllegalStateException.class) + @Test public void prohibit_obtaining_the_other_value_A() { + thrown.expect(IllegalStateException.class); eitherWithB.getA(); } diff --git a/server/src/test/java/io/spine/server/tuple/PairShould.java b/server/src/test/java/io/spine/server/tuple/PairShould.java index cafe079a837..34b93f8065c 100644 --- a/server/src/test/java/io/spine/server/tuple/PairShould.java +++ b/server/src/test/java/io/spine/server/tuple/PairShould.java @@ -29,7 +29,9 @@ import com.google.protobuf.StringValue; import io.spine.base.Time; import io.spine.test.TestValues; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -43,6 +45,9 @@ @SuppressWarnings("LocalVariableNamingConvention") // OK for tuple element values public class PairShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void pass_null_tolerance_check() { new NullPointerTester().setDefault(Message.class, TestValues.newUuidValue()) @@ -64,23 +69,27 @@ public void support_equality() { .testEquals(); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_default_A_value() { + thrown.expect(IllegalArgumentException.class); Pair.of(StringValue.getDefaultInstance(), BoolValue.of(true)); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_default_B_value() { + thrown.expect(IllegalArgumentException.class); Pair.of(BoolValue.of(false), TestValues.newUuidValue()); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_Empty_A() { + thrown.expect(IllegalArgumentException.class); Pair.of(Empty.getDefaultInstance(), BoolValue.of(true)); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_Empty_B() { + thrown.expect(IllegalArgumentException.class); Pair.of(BoolValue.of(true), Empty.getDefaultInstance()); } diff --git a/server/src/test/java/io/spine/server/tuple/TripletShould.java b/server/src/test/java/io/spine/server/tuple/TripletShould.java index a6c131201b8..e7391f04f56 100644 --- a/server/src/test/java/io/spine/server/tuple/TripletShould.java +++ b/server/src/test/java/io/spine/server/tuple/TripletShould.java @@ -31,7 +31,9 @@ import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; @@ -53,6 +55,9 @@ public class TripletShould { private Triplet triplet; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { triplet = Triplet.of(a, b, c); @@ -79,18 +84,21 @@ public void support_equality() { .testEquals(); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_default_A_value() { + thrown.expect(IllegalArgumentException.class); Triplet.of(StringValue.getDefaultInstance(), b, c); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_default_B_value() { + thrown.expect(IllegalArgumentException.class); Triplet.of(a, StringValue.getDefaultInstance(), c); } - @Test(expected = IllegalArgumentException.class) + @Test public void prohibit_default_C_value() { + thrown.expect(IllegalArgumentException.class); Triplet.of(a, b, StringValue.getDefaultInstance()); } From 16921800c3f5972390ba4614f7fa4acafe4b652b Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Sun, 27 May 2018 01:09:13 +0300 Subject: [PATCH 11/53] Handle ignored return values --- .../server/entity/EntityClassShould.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/test/java/io/spine/server/entity/EntityClassShould.java b/server/src/test/java/io/spine/server/entity/EntityClassShould.java index 2f2018bcc9a..c2d6910f46e 100644 --- a/server/src/test/java/io/spine/server/entity/EntityClassShould.java +++ b/server/src/test/java/io/spine/server/entity/EntityClassShould.java @@ -27,7 +27,9 @@ import io.spine.test.TimeTests; import io.spine.time.Interval; import io.spine.time.Intervals; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.lang.reflect.Constructor; @@ -41,35 +43,38 @@ */ public class EntityClassShould { - private final EntityClass entityClass = new EntityClass<>( - (Class) NanoEntity.class); + private final EntityClass entityClass = + new EntityClass<>((Class) NanoEntity.class); + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void return_id_class() { @SuppressWarnings("unchecked") // - final Class actual = (Class) entityClass.getIdClass(); + Class actual = (Class) entityClass.getIdClass(); assertEquals(Long.class, actual); } @Test public void obtain_entity_constructor() { - final Constructor ctor = entityClass.getConstructor(); + Constructor ctor = entityClass.getConstructor(); assertNotNull(ctor); } @Test public void create_and_initialize_entity_instance() { - final Long id = 100L; - final Timestamp before = TimeTests.Past.secondsAgo(1); + Long id = 100L; + Timestamp before = TimeTests.Past.secondsAgo(1); // Create and init the entity. - final EntityClass entityClass = new EntityClass<>(NanoEntity.class); - final AbstractVersionableEntity entity = entityClass.createEntity(id); + EntityClass entityClass = new EntityClass<>(NanoEntity.class); + AbstractVersionableEntity entity = entityClass.createEntity(id); - final Timestamp after = Time.getCurrentTime(); + Timestamp after = Time.getCurrentTime(); // The interval with a much earlier start to allow non-zero interval on faster computers. - final Interval whileWeCreate = Intervals.between(before, after); + Interval whileWeCreate = Intervals.between(before, after); assertEquals(id, entity.getId()); assertEquals(0, entity.getVersion() @@ -80,8 +85,9 @@ public void create_and_initialize_entity_instance() { assertFalse(entity.isDeleted()); } - @Test(expected = ModelError.class) + @Test public void complain_when_there_is_no_one_arg_constructor_for_entity_class() { + thrown.expect(ModelError.class); new EntityClass<>(NoArgEntity.class).getConstructor(); } From 0980153c4d102f4526fb6e27f365aff008199ec8 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Sun, 27 May 2018 18:19:36 +0300 Subject: [PATCH 12/53] Handle ignored return values --- .../server/aggregate/AggregateRepository.java | 71 ++- .../AggregateCommandEndpointShould.java | 22 +- .../aggregate/AggregatePartClassShould.java | 14 +- .../AggregatePartRepositoryLookupShould.java | 64 ++- .../server/aggregate/AggregatePartShould.java | 48 ++- .../aggregate/AggregateRepositoryShould.java | 226 +++++----- .../server/aggregate/AggregateShould.java | 325 +++++++------- .../aggregate/AggregateStorageShould.java | 406 +++++++++--------- .../aggregate/AggregateTransactionShould.java | 16 +- .../AggregateCommandEndpointTestEnv.java | 8 +- .../spine/server/command/CommandHistory.java | 14 +- .../enrich/EnrichmentFunctionShould.java | 62 +-- .../enrich/ReferenceValidatorShould.java | 74 ++-- .../enrich/given/EnricherBuilderTestEnv.java | 94 +--- .../given/EventMessageEnricherTestEnv.java | 134 ++---- .../given/ReferenceValidatorTestEnv.java | 138 ++---- .../enrich/given/StringToPersonName.java | 70 +++ .../enrich/given/StringToZoneOffset.java | 45 ++ .../server/storage/AbstractStorageShould.java | 88 ++-- .../aggregate/AggregateMessageDispatcher.java | 15 +- .../io/spine/server/entity/EntityBuilder.java | 16 +- .../io/spine/server/entity/given/Given.java | 38 +- 22 files changed, 1016 insertions(+), 972 deletions(-) create mode 100644 server/src/test/java/io/spine/server/outbus/enrich/given/StringToPersonName.java create mode 100644 server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java diff --git a/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java b/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java index 21a2be41589..75107313d38 100644 --- a/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java +++ b/server/src/main/java/io/spine/server/aggregate/AggregateRepository.java @@ -104,40 +104,31 @@ public abstract class AggregateRepository> /** The routing schema for events to which aggregates react. */ private final EventRouting eventRouting = - EventRouting.withDefault(EventProducers.fromContext()); + EventRouting.withDefault(EventProducers.fromContext()); /** The routing schema for rejections to which aggregates react. */ private final RejectionRouting rejectionRouting = - RejectionRouting.withDefault(RejectionProducers.fromContext()); + RejectionRouting.withDefault(RejectionProducers.fromContext()); private final Supplier> commandDeliverySupplier = - memoize(new Supplier>() { - @Override - public AggregateCommandDelivery get() { - final AggregateCommandDelivery result = - new AggregateCommandDelivery<>(AggregateRepository.this); - return result; - } - }); + memoize(() -> { + final AggregateCommandDelivery result = + new AggregateCommandDelivery<>(this); + return result; + }); private final Supplier> eventDeliverySupplier = - memoize(new Supplier>() { - @Override - public AggregateEventDelivery get() { - final AggregateEventDelivery result = - new AggregateEventDelivery<>(AggregateRepository.this); - return result; - } - }); + memoize(() -> { + final AggregateEventDelivery result = + new AggregateEventDelivery<>(this); + return result; + }); private final Supplier> rejectionDeliverySupplier = - memoize(new Supplier>() { - @Override - public AggregateRejectionDelivery get() { - final AggregateRejectionDelivery result = - new AggregateRejectionDelivery<>(AggregateRepository.this); - return result; - } + memoize(() -> { + final AggregateRejectionDelivery result = + new AggregateRejectionDelivery<>(this); + return result; }); /** @@ -328,7 +319,7 @@ public Set getMessageClasses() { * @param envelope the envelope of the command to dispatch */ @Override - public I dispatch(final CommandEnvelope envelope) { + public I dispatch(CommandEnvelope envelope) { checkNotNull(envelope); return AggregateCommandEndpoint.handle(this, envelope); } @@ -463,7 +454,7 @@ protected void setSnapshotTrigger(int snapshotTrigger) { */ protected AggregateStorage aggregateStorage() { @SuppressWarnings("unchecked") // We check the type on initialization. - final AggregateStorage result = (AggregateStorage) getStorage(); + AggregateStorage result = (AggregateStorage) getStorage(); return result; } @@ -474,13 +465,13 @@ protected AggregateStorage aggregateStorage() { * @return loaded or created aggregate instance */ A loadOrCreate(I id) { - final Optional optional = load(id); + Optional optional = load(id); if (optional.isPresent()) { return optional.get(); } - final A result = create(id); + A result = create(id); return result; } @@ -497,9 +488,9 @@ A loadOrCreate(I id) { * with the ID */ private Optional load(I id) { - final Optional eventsFromStorage = fetchHistory(id); + Optional eventsFromStorage = fetchHistory(id); if (eventsFromStorage.isPresent()) { - final A result = play(id, eventsFromStorage.get()); + A result = play(id, eventsFromStorage.get()); return Optional.of(result); } return Optional.absent(); @@ -517,8 +508,8 @@ private Optional load(I id) { * {@code Optional.absent()} if there is no record with the ID */ protected Optional fetchHistory(I id) { - final AggregateReadRequest request = new AggregateReadRequest<>(id, snapshotTrigger); - final Optional eventsFromStorage = aggregateStorage().read(request); + AggregateReadRequest request = new AggregateReadRequest<>(id, snapshotTrigger); + Optional eventsFromStorage = aggregateStorage().read(request); return eventsFromStorage; } @@ -531,8 +522,8 @@ protected Optional fetchHistory(I id) { * @return an instance of {@link Aggregate} */ protected A play(I id, AggregateStateRecord history) { - final A result = create(id); - final AggregateTransaction tx = AggregateTransaction.start(result); + A result = create(id); + AggregateTransaction tx = AggregateTransaction.start(result); result.play(history); tx.commit(); return result; @@ -545,7 +536,7 @@ protected A play(I id, AggregateStateRecord history) { * @param aggregate the updated aggregate */ void onModifiedAggregate(TenantId tenantId, A aggregate) { - final List events = aggregate.getUncommittedEvents(); + List events = aggregate.getUncommittedEvents(); store(aggregate); updateStand(tenantId, aggregate); postEvents(events); @@ -569,7 +560,7 @@ void onModifiedAggregate(TenantId tenantId, A aggregate) { */ @Override public Optional find(I id) throws IllegalStateException { - final Optional result = load(id); + Optional result = load(id); return result; } @@ -638,8 +629,8 @@ public ShardingStrategy getShardingStrategy() { @Override public Iterable> getMessageConsumers() { - final Iterable> result = - ImmutableList.>of( + Iterable> result = + ImmutableList.of( getCommandEndpointDelivery().getConsumer(), getEventEndpointDelivery().getConsumer(), getRejectionEndpointDelivery().getConsumer() @@ -649,7 +640,7 @@ public ShardingStrategy getShardingStrategy() { @Override public BoundedContextName getBoundedContextName() { - final BoundedContextName name = getBoundedContext().getName(); + BoundedContextName name = getBoundedContext().getName(); return name; } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateCommandEndpointShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateCommandEndpointShould.java index 888cf6362ef..843616ab2b1 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateCommandEndpointShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateCommandEndpointShould.java @@ -78,25 +78,27 @@ public void tearDown() throws Exception { @Test public void post_events_on_command_dispatching() { - final CommandEnvelope cmd = CommandEnvelope.of(createProject(projectId)); + CommandEnvelope cmd = CommandEnvelope.of(createProject(projectId)); - repository.dispatch(cmd); + ProjectId id = repository.dispatch(cmd); + assertEquals(projectId, id); - final AggProjectCreated msg = subscriber.remembered; + AggProjectCreated msg = subscriber.remembered; assertEquals(projectId, msg.getProjectId()); } @Test public void store_aggregate_on_command_dispatching() { - final CommandEnvelope cmd = CommandEnvelope.of(createProject(projectId)); - final AggCreateProject msg = (AggCreateProject) cmd.getMessage(); + CommandEnvelope cmd = CommandEnvelope.of(createProject(projectId)); + AggCreateProject msg = (AggCreateProject) cmd.getMessage(); - repository.dispatch(cmd); + ProjectId id = repository.dispatch(cmd); + assertEquals(projectId, id); - final Optional optional = repository.find(projectId); + Optional optional = repository.find(projectId); assertTrue(optional.isPresent()); - final ProjectAggregate aggregate = optional.get(); + ProjectAggregate aggregate = optional.get(); assertEquals(projectId, aggregate.getId()); assertEquals(msg.getName(), aggregate.getState() @@ -119,8 +121,10 @@ public void dispatch_several_commands() { * Utility methods. ****************************/ + @SuppressWarnings("CheckReturnValue") + // ignore ID of the aggregate returned by the repository private void assertDispatches(Command cmd) { - final CommandEnvelope envelope = CommandEnvelope.of(cmd); + CommandEnvelope envelope = CommandEnvelope.of(cmd); repository.dispatch(envelope); ProjectAggregate.assertHandled(cmd); } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregatePartClassShould.java b/server/src/test/java/io/spine/server/aggregate/AggregatePartClassShould.java index a9fb803f773..7339ab7584d 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregatePartClassShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregatePartClassShould.java @@ -27,7 +27,9 @@ import io.spine.server.model.ModelError; import io.spine.server.model.ModelTests; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.base.Identifier.newUuid; import static org.junit.Assert.assertEquals; @@ -42,11 +44,14 @@ public class AggregatePartClassShould { new AggregatePartClass<>(AnAggregatePart.class); private AnAggregateRoot root; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { ModelTests.clearModel(); - final BoundedContext boundedContext = BoundedContext.newBuilder() - .build(); + BoundedContext boundedContext = BoundedContext.newBuilder() + .build(); root = new AnAggregateRoot(boundedContext, newUuid()); } @@ -55,13 +60,14 @@ public void obtain_aggregate_part_constructor() { assertNotNull(partClass.getConstructor()); } - @Test(expected = ModelError.class) + @Test public void throw_exception_when_aggregate_part_does_not_have_appropriate_constructor() { + thrown.expect(ModelError.class); new AggregatePartClass<>(WrongAggregatePart.class).getConstructor(); } @Test - public void create_aggregate_part_entity() throws NoSuchMethodException { + public void create_aggregate_part_entity() { final AnAggregatePart part = partClass.createEntity(root); assertNotNull(part); diff --git a/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java b/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java index d1f344ad3ed..d8f0eb5db39 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java @@ -37,9 +37,10 @@ import io.spine.test.aggregate.event.AggProjectCreated; import io.spine.test.aggregate.event.AggTaskAdded; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; -import static io.spine.base.Identifier.newUuid; import static io.spine.server.aggregate.AggregatePartRepositoryLookup.createLookup; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -48,50 +49,49 @@ public class AggregatePartRepositoryLookupShould { private BoundedContext boundedContext; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { ModelTests.clearModel(); boundedContext = BoundedContext.newBuilder() .build(); - final ProjectId id = ProjectId.newBuilder() - .setId(newUuid()) - .build(); - boundedContext.register(new ProjectPartRepository(boundedContext)); - boundedContext.register(new TaskAggregateRepository(boundedContext)); + boundedContext.register(new ProjectPartRepository()); + boundedContext.register(new TaskAggregateRepository()); } @Test public void find_a_repository() { - AggregatePartRepositoryLookup lookup = createLookup(boundedContext, - ProjectId.class, - Project.class); + AggregatePartRepositoryLookup lookup = + createLookup(boundedContext, ProjectId.class, Project.class); - final AggregatePartRepository repository = lookup.find(); + AggregatePartRepository repository = lookup.find(); assertNotNull(repository); assertTrue(repository instanceof ProjectPartRepository); } - @Test(expected = IllegalStateException.class) + @Test public void throw_if_repository_is_not_AggregatePartRepository() { - final AggregatePartRepositoryLookup lookup = createLookup(boundedContext, - TaskId.class, - Task.class); + AggregatePartRepositoryLookup lookup = + createLookup(boundedContext, TaskId.class, Task.class); + thrown.expect(IllegalStateException.class); lookup.find(); } - @Test(expected = IllegalStateException.class) + @Test public void throw_if_repository_not_found() { - AggregatePartRepositoryLookup lookup = createLookup(boundedContext, - Timestamp.class, - StringValue.class); + AggregatePartRepositoryLookup lookup = + createLookup(boundedContext, Timestamp.class, StringValue.class); + thrown.expect(IllegalStateException.class); lookup.find(); } - @Test(expected = IllegalStateException.class) + @Test public void throw_if_id_class_does_not_match() { - AggregatePartRepositoryLookup lookup = createLookup(boundedContext, - TaskId.class, - Project.class); + AggregatePartRepositoryLookup lookup = + createLookup(boundedContext, TaskId.class, Project.class); + thrown.expect(IllegalStateException.class); lookup.find(); } @@ -137,7 +137,7 @@ void apply(AggProjectCreated event) { private static class ProjectPartRepository extends AggregatePartRepository { - private ProjectPartRepository(BoundedContext boundedContext) { + private ProjectPartRepository() { super(); } } @@ -155,10 +155,9 @@ protected TaskRoot(BoundedContext boundedContext, TaskId id) { } } - private static class TaskAggregatePart extends AggregatePart { + private static class TaskAggregatePart + extends AggregatePart { + private TaskAggregatePart(TaskRoot root) { super(root); } @@ -172,16 +171,15 @@ public AggTaskAdded handle(AggAddTask cmd) { @Apply public void apply(AggTaskAdded event) { - final Task task = event.getTask(); + Task task = event.getTask(); getBuilder().setTitle(task.getTitle()) - .setDescription(task.getDescription()) - .build(); + .setDescription(task.getDescription()); } } - private static class TaskAggregateRepository extends AggregateRepository { - private TaskAggregateRepository(BoundedContext boundedContext) { + private static class TaskAggregateRepository + extends AggregateRepository { + private TaskAggregateRepository() { super(); } } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregatePartShould.java b/server/src/test/java/io/spine/server/aggregate/AggregatePartShould.java index 4ad7e2da255..6002cf589ca 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregatePartShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregatePartShould.java @@ -113,38 +113,44 @@ public void throw_InvalidEntityStateException_if_state_is_invalid() { .setLastName("|") .build(); try { - aggregatePartOfClass(AnAggregatePart.class).withRoot(root) - .withId(getClass().getName()) - .withVersion(1) - .withState(user) - .build(); + aggregatePartOfClass(AnAggregatePart.class) + .withRoot(root) + .withId(getClass().getName()) + .withVersion(1) + .withState(user) + .build(); fail(); } catch (InvalidEntityStateException e) { - final List violations = e.getError() - .getValidationError() - .getConstraintViolationList(); - assertSize(user.getAllFields().size(), violations); + List violations = + e.getError() + .getValidationError() + .getConstraintViolationList(); + assertSize(user.getAllFields() + .size(), violations); } } @Test public void update_valid_entity_state() { - final User user = User.newBuilder() - .setFirstName("Firstname") - .setLastName("Lastname") - .build(); - aggregatePartOfClass(AnAggregatePart.class).withRoot(root) - .withId(getClass().getName()) - .withVersion(1) - .withState(user) - .build(); + User user = User.newBuilder() + .setFirstName("Firstname") + .setLastName("Lastname") + .build(); + AnAggregatePart part = aggregatePartOfClass(AnAggregatePart.class) + .withRoot(root) + .withId(getClass().getName()) + .withVersion(1) + .withState(user) + .build(); + + assertEquals(user, part.getState()); } private NullPointerTester createNullPointerTester() throws NoSuchMethodException { - final Constructor constructor = + Constructor constructor = AnAggregateRoot.class .getDeclaredConstructor(BoundedContext.class, String.class); - final NullPointerTester tester = new NullPointerTester(); + NullPointerTester tester = new NullPointerTester(); tester.setDefault(Constructor.class, constructor) .setDefault(BoundedContext.class, boundedContext) .setDefault(AggregateRoot.class, root); @@ -152,7 +158,7 @@ private NullPointerTester createNullPointerTester() throws NoSuchMethodException } private void prepareAggregatePart() { - final AggAddTask addTask = + AggAddTask addTask = ((AggAddTask.Builder) Sample.builderForType(AggAddTask.class)) .setProjectId(ProjectId.newBuilder() .setId("agg-part-ID")) diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateRepositoryShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateRepositoryShould.java index dd45b335ce0..1fe2920c84d 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateRepositoryShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateRepositoryShould.java @@ -63,7 +63,9 @@ import io.spine.testdata.Sample; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import java.util.Iterator; @@ -91,6 +93,15 @@ public class AggregateRepositoryShould { private BoundedContext boundedContext; private AggregateRepository repository; + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static ProjectId givenAggregateId(String id) { + return ProjectId.newBuilder() + .setId(id) + .build(); + } + @Before public void setUp() { ModelTests.clearModel(); @@ -108,35 +119,39 @@ public void tearDown() throws Exception { @Test public void do_not_create_new_aggregates_on_find() { - final ProjectId newId = Sample.messageOfType(ProjectId.class); - final Optional optional = repository.find(newId); + ProjectId newId = Sample.messageOfType(ProjectId.class); + Optional optional = repository.find(newId); assertFalse(optional.isPresent()); } @Test public void store_and_load_aggregate() { - final ProjectId id = Sample.messageOfType(ProjectId.class); - final ProjectAggregate expected = GivenAggregate.withUncommittedEvents(id); + ProjectId id = Sample.messageOfType(ProjectId.class); + ProjectAggregate expected = GivenAggregate.withUncommittedEvents(id); repository.store(expected); - final ProjectAggregate actual = repository.find(id) - .get(); + ProjectAggregate actual = assertFound(id); assertTrue(isNotDefault(actual.getState())); assertEquals(expected.getId(), actual.getId()); assertEquals(expected.getState(), actual.getState()); } + private ProjectAggregate assertFound(ProjectId id) { + Optional optional = repository.find(id); + assertTrue(optional.isPresent()); + return optional.get(); + } + @Test public void restore_aggregate_using_snapshot() { - final ProjectId id = Sample.messageOfType(ProjectId.class); - final ProjectAggregate expected = GivenAggregate.withUncommittedEvents(id); + ProjectId id = Sample.messageOfType(ProjectId.class); + ProjectAggregate expected = GivenAggregate.withUncommittedEvents(id); repository.setSnapshotTrigger(expected.uncommittedEventsCount()); repository.store(expected); - final ProjectAggregate actual = repository.find(id) - .get(); + ProjectAggregate actual = assertFound(id); assertEquals(expected.getId(), actual.getId()); assertEquals(expected.getState(), actual.getState()); @@ -144,12 +159,12 @@ public void restore_aggregate_using_snapshot() { @Test public void store_snapshot_and_set_event_count_to_zero_if_needed() { - final ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(); + ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(); // This should make the repository write the snapshot. repository.setSnapshotTrigger(aggregate.uncommittedEventsCount()); repository.store(aggregate); - final AggregateStateRecord record = readRecord(aggregate); + AggregateStateRecord record = readRecord(aggregate); assertTrue(record.hasSnapshot()); assertEquals(0, repository.aggregateStorage() .readEventCountAfterLastSnapshot(aggregate.getId())); @@ -157,49 +172,51 @@ public void store_snapshot_and_set_event_count_to_zero_if_needed() { @Test public void not_store_snapshot_if_not_needed() { - final ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(); + ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(); repository.store(aggregate); - final AggregateStateRecord record = readRecord(aggregate); + AggregateStateRecord record = readRecord(aggregate); assertFalse(record.hasSnapshot()); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "CheckReturnValue" /* calling mock */}) @Test public void pass_initial_snapshot_trigger_to_AggregateReadRequest() { - final AggregateRepository repositorySpy = spy(repository); - final AggregateStorage storageSpy = spy(repositorySpy.aggregateStorage()); - doReturn(storageSpy).when(repositorySpy).aggregateStorage(); + AggregateRepository repositorySpy = spy(repository); + AggregateStorage storageSpy = spy(repositorySpy.aggregateStorage()); + doReturn(storageSpy).when(repositorySpy) + .aggregateStorage(); - final ProjectId id = Sample.messageOfType(ProjectId.class); + ProjectId id = Sample.messageOfType(ProjectId.class); repositorySpy.loadOrCreate(id); - final ArgumentCaptor> requestCaptor = + ArgumentCaptor> requestCaptor = ArgumentCaptor.forClass(AggregateReadRequest.class); verify(storageSpy).read(requestCaptor.capture()); - final AggregateReadRequest passedRequest = requestCaptor.getValue(); + AggregateReadRequest passedRequest = requestCaptor.getValue(); assertEquals(id, passedRequest.getRecordId()); assertEquals(repositorySpy.getSnapshotTrigger(), passedRequest.getBatchSize()); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "CheckReturnValue" /* calling mock */}) @Test public void pass_updated_snapshot_trigger_to_AggregateReadRequest() { - final AggregateRepository repositorySpy = spy(repository); - final AggregateStorage storageSpy = spy(repositorySpy.aggregateStorage()); - doReturn(storageSpy).when(repositorySpy).aggregateStorage(); + AggregateRepository repositorySpy = spy(repository); + AggregateStorage storageSpy = spy(repositorySpy.aggregateStorage()); + doReturn(storageSpy).when(repositorySpy) + .aggregateStorage(); - final int nonDefaultSnapshotTrigger = DEFAULT_SNAPSHOT_TRIGGER * 2; + int nonDefaultSnapshotTrigger = DEFAULT_SNAPSHOT_TRIGGER * 2; repositorySpy.setSnapshotTrigger(nonDefaultSnapshotTrigger); - final ProjectId id = Sample.messageOfType(ProjectId.class); + ProjectId id = Sample.messageOfType(ProjectId.class); repositorySpy.loadOrCreate(id); - final ArgumentCaptor> requestCaptor = + ArgumentCaptor> requestCaptor = ArgumentCaptor.forClass(AggregateReadRequest.class); verify(storageSpy).read(requestCaptor.capture()); - final AggregateReadRequest passedRequest = requestCaptor.getValue(); + AggregateReadRequest passedRequest = requestCaptor.getValue(); assertEquals(id, passedRequest.getRecordId()); assertEquals(nonDefaultSnapshotTrigger, passedRequest.getBatchSize()); } @@ -226,7 +243,7 @@ public void do_not_accept_zero_snapshot_trigger() { @Test public void allow_to_change_snapshot_trigger() { - final int newSnapshotTrigger = 1000; + int newSnapshotTrigger = 1000; repository.setSnapshotTrigger(newSnapshotTrigger); @@ -235,49 +252,50 @@ public void allow_to_change_snapshot_trigger() { @Test public void expose_classes_of_commands_of_its_aggregate() { - final Set aggregateCommands = + Set aggregateCommands = Model.getInstance() .asAggregateClass(ProjectAggregate.class) .getCommands(); - final Set exposedByRepository = repository.getMessageClasses(); + Set exposedByRepository = repository.getMessageClasses(); assertTrue(exposedByRepository.containsAll(aggregateCommands)); } @Test public void find_archived_aggregates() { - final ProjectAggregate aggregate = givenStoredAggregate(); + ProjectAggregate aggregate = givenStoredAggregate(); - final AggregateTransaction tx = AggregateTransaction.start(aggregate); + AggregateTransaction tx = AggregateTransaction.start(aggregate); aggregate.setArchived(true); tx.commit(); repository.store(aggregate); assertTrue(repository.find(aggregate.getId()) - .isPresent()); + .isPresent()); } @Test public void find_deleted_aggregates() { - final ProjectAggregate aggregate = givenStoredAggregate(); + ProjectAggregate aggregate = givenStoredAggregate(); - final AggregateTransaction tx = AggregateTransaction.start(aggregate); + AggregateTransaction tx = AggregateTransaction.start(aggregate); aggregate.setDeleted(true); tx.commit(); repository.store(aggregate); assertTrue(repository.find(aggregate.getId()) - .isPresent()); + .isPresent()); } - @Test(expected = IllegalStateException.class) + @SuppressWarnings("CheckReturnValue") // The returned value is not used in this test. + @Test public void throw_ISE_if_unable_to_load_entity_by_id_from_storage_index() { // Store a valid aggregate. givenStoredAggregate(); // Store a troublesome entity, which cannot be loaded. - final TenantAwareOperation op = new TenantAwareOperation(newUuid()) { + TenantAwareOperation op = new TenantAwareOperation(newUuid()) { @Override public void run() { givenStoredAggregateWithId(ProjectAggregateRepository.troublesome.getId()); @@ -285,48 +303,49 @@ public void run() { }; op.execute(); - final Iterator iterator = - repository.iterator(Predicates.alwaysTrue()); + Iterator iterator = + repository.iterator(Predicates.alwaysTrue()); + thrown.expect(IllegalStateException.class); // This should iterate through all and fail. Lists.newArrayList(iterator); } @Test public void expose_event_classes_on_which_aggregates_react() { - final Set eventClasses = repository.getEventClasses(); + Set eventClasses = repository.getEventClasses(); assertTrue(eventClasses.contains(EventClass.of(AggProjectArchived.class))); assertTrue(eventClasses.contains(EventClass.of(AggProjectDeleted.class))); } @Test public void route_events_to_aggregates() { - final ProjectAggregate parent = givenStoredAggregate(); - final ProjectAggregate child = givenStoredAggregate(); + ProjectAggregate parent = givenStoredAggregate(); + ProjectAggregate child = givenStoredAggregate(); assertTrue(repository.find(parent.getId()) .isPresent()); assertTrue(repository.find(child.getId()) .isPresent()); - final TestEventFactory factory = TestEventFactory.newInstance(getClass()); - final AggProjectArchived msg = AggProjectArchived.newBuilder() - .setProjectId(parent.getId()) - .addChildProjectId(child.getId()) - .build(); - final Event event = factory.createEvent(msg); + TestEventFactory factory = TestEventFactory.newInstance(getClass()); + AggProjectArchived msg = AggProjectArchived.newBuilder() + .setProjectId(parent.getId()) + .addChildProjectId(child.getId()) + .build(); + Event event = factory.createEvent(msg); boundedContext.getEventBus() .post(event); // Check that the child aggregate was archived. - final Optional childAfterArchive = repository.find(child.getId()); + Optional childAfterArchive = repository.find(child.getId()); assertTrue(childAfterArchive.isPresent()); assertTrue(childAfterArchive.get() .isArchived()); // The parent should not be archived since the dispatch route uses only // child aggregates from the `ProjectArchived` event. - final Optional parentAfterArchive = repository.find(parent.getId()); + Optional parentAfterArchive = repository.find(parent.getId()); assertTrue(parentAfterArchive.isPresent()); assertFalse(parentAfterArchive.get() .isArchived()); @@ -334,13 +353,13 @@ public void route_events_to_aggregates() { @Test public void log_error_when_event_reaction_fails() { - final FailingAggregateRepository repository = new FailingAggregateRepository(); + FailingAggregateRepository repository = new FailingAggregateRepository(); boundedContext.register(repository); - final TestEventFactory factory = TestEventFactory.newInstance(getClass()); + TestEventFactory factory = TestEventFactory.newInstance(getClass()); // Passing negative float value should cause an exception. - final EventEnvelope envelope = + EventEnvelope envelope = EventEnvelope.of(factory.createEvent(FloatValue.newBuilder() .setValue(-412.0f) .build())); @@ -348,16 +367,16 @@ public void log_error_when_event_reaction_fails() { .post(envelope.getOuterObject()); assertTrue(repository.isErrorLogged()); - final RuntimeException lastException = repository.getLastException(); + RuntimeException lastException = repository.getLastException(); assertTrue(lastException instanceof HandlerMethodFailedException); - final HandlerMethodFailedException methodFailedException = + HandlerMethodFailedException methodFailedException = (HandlerMethodFailedException) lastException; assertEquals(envelope.getMessage(), methodFailedException.getDispatchedMessage()); assertEquals(envelope.getEventContext(), methodFailedException.getMessageContext()); - final MessageEnvelope lastErrorEnvelope = repository.getLastErrorEnvelope(); + MessageEnvelope lastErrorEnvelope = repository.getLastErrorEnvelope(); assertNotNull(lastErrorEnvelope); assertTrue(lastErrorEnvelope instanceof EventEnvelope); assertEquals(envelope.getMessage(), lastErrorEnvelope.getMessage()); @@ -365,14 +384,14 @@ public void log_error_when_event_reaction_fails() { @Test public void not_pass_command_rejection_to_onError() { - final FailingAggregateRepository repository = new FailingAggregateRepository(); + FailingAggregateRepository repository = new FailingAggregateRepository(); boundedContext.register(repository); - final TestActorRequestFactory requestFactory = + TestActorRequestFactory requestFactory = TestActorRequestFactory.newInstance(getClass()); // Passing negative long value to `FailingAggregate` should cause a rejection. - final CommandEnvelope ce = CommandEnvelope.of( + CommandEnvelope ce = CommandEnvelope.of( requestFactory.createCommand(UInt64Value.newBuilder() .setValue(-100_000_000L) .build())); @@ -389,24 +408,24 @@ public void now_allow_anemic_aggregates() { @Test public void allow_aggregates_react_on_events() { - final ReactingRepository repository = new ReactingRepository(); + ReactingRepository repository = new ReactingRepository(); boundedContext.register(repository); - final ProjectId parentId = givenAggregateId("parent"); - final ProjectId childId = givenAggregateId("child"); + ProjectId parentId = givenAggregateId("parent"); + ProjectId childId = givenAggregateId("child"); /** * Create event factory for which producer ID would be the `parentId`. * Custom routing set by {@linkplain ReactingRepository()} would use * child IDs from the event. */ - final TestEventFactory factory = TestEventFactory.newInstance(Identifier.pack(parentId), - getClass()); - final AggProjectArchived msg = AggProjectArchived.newBuilder() - .setProjectId(parentId) - .addChildProjectId(childId) - .build(); - final Event event = factory.createEvent(msg); + TestEventFactory factory = TestEventFactory.newInstance(Identifier.pack(parentId), + getClass()); + AggProjectArchived msg = AggProjectArchived.newBuilder() + .setProjectId(parentId) + .addChildProjectId(childId) + .build(); + Event event = factory.createEvent(msg); // Posting this event should archive the aggregate. boundedContext.getEventBus() @@ -414,7 +433,7 @@ public void allow_aggregates_react_on_events() { // Check that the aggregate marked itself as `archived`, and therefore became invisible // to regular queries. - final Optional optional = repository.find(childId); + Optional optional = repository.find(childId); // The aggregate was created because of dispatching. assertTrue(optional.isPresent()); @@ -426,23 +445,28 @@ public void allow_aggregates_react_on_events() { .getValue()); } + /* + * Test environment methods that use internals of this test suite + * (and because of that are not moved to the test environment outside of this class). + **************************************************************************************/ + @Test public void allow_aggregates_react_on_rejections() { boundedContext.register(new RejectingRepository()); - final RejectionReactingRepository repository = new RejectionReactingRepository(); + RejectionReactingRepository repository = new RejectionReactingRepository(); boundedContext.register(repository); - final ProjectId parentId = givenAggregateId("rejectingParent"); - final ProjectId childId1 = givenAggregateId("acceptingChild-1"); - final ProjectId childId2 = givenAggregateId("acceptingChild-2"); - final ProjectId childId3 = givenAggregateId("acceptingChild-3"); + ProjectId parentId = givenAggregateId("rejectingParent"); + ProjectId childId1 = givenAggregateId("acceptingChild-1"); + ProjectId childId2 = givenAggregateId("acceptingChild-2"); + ProjectId childId3 = givenAggregateId("acceptingChild-3"); - final StreamObserver observer = StreamObservers.noOpObserver(); - final CommandBus commandBus = boundedContext.getCommandBus(); + StreamObserver observer = StreamObservers.noOpObserver(); + CommandBus commandBus = boundedContext.getCommandBus(); // Create the parent project. - final ImmutableSet childProjects = ImmutableSet.of(childId1, childId2, childId3); - final Command createParent = requestFactory.createCommand( + ImmutableSet childProjects = ImmutableSet.of(childId1, childId2, childId3); + Command createParent = requestFactory.createCommand( AggCreateProjectWithChildren.newBuilder() .setProjectId(parentId) .addAllChildProjectId(childProjects) @@ -451,7 +475,7 @@ public void allow_aggregates_react_on_rejections() { commandBus.post(createParent, observer); // Fire a command which would cause rejection. - final Command startProject = requestFactory.createCommand( + Command startProject = requestFactory.createCommand( AggStartProjectWithChildren.newBuilder() .setProjectId(parentId) .build() @@ -459,51 +483,41 @@ public void allow_aggregates_react_on_rejections() { commandBus.post(startProject, observer); for (ProjectId childProject : childProjects) { - final Optional optional = repository.find(childProject); + Optional optional = repository.find(childProject); assertTrue(optional.isPresent()); // Check that all the aggregates: // 1. got Rejections.AggCannotStartArchivedProject; // 2. produced the state the event; // 3. applied the event. - final String value = optional.get() - .getState() - .getValue(); + String value = optional.get() + .getState() + .getValue(); assertEquals(RejectionReactingAggregate.PARENT_ARCHIVED, value); } } - /* - * Test environment methods that use internals of this test suite - * (and because of that are not moved to the test environment outside of this class). - **************************************************************************************/ - private ProjectAggregate givenStoredAggregate() { - final ProjectId id = Sample.messageOfType(ProjectId.class); - final ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(id); + ProjectId id = Sample.messageOfType(ProjectId.class); + ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(id); repository.store(aggregate); return aggregate; } private void givenStoredAggregateWithId(String id) { - final ProjectId projectId = givenAggregateId(id); - final ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(projectId); + ProjectId projectId = givenAggregateId(id); + ProjectAggregate aggregate = GivenAggregate.withUncommittedEvents(projectId); repository.store(aggregate); } - private static ProjectId givenAggregateId(String id) { - return ProjectId.newBuilder() - .setId(id) - .build(); - } - private AggregateStateRecord readRecord(ProjectAggregate aggregate) { - final AggregateReadRequest request = + AggregateReadRequest request = new AggregateReadRequest<>(aggregate.getId(), DEFAULT_SNAPSHOT_TRIGGER); - return repository.aggregateStorage() - .read(request) - .get(); + Optional optional = repository.aggregateStorage() + .read(request); + assertTrue(optional.isPresent()); + return optional.get(); } } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateShould.java index f7acc6f7b65..325e2f11193 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateShould.java @@ -73,7 +73,9 @@ import io.spine.validate.ConstraintViolation; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; import java.util.List; @@ -136,14 +138,17 @@ public class AggregateShould { private BoundedContext boundedContext; private TestAggregateRepository repository; + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static TestAggregate newAggregate(ProjectId id) { - final TestAggregate result = new TestAggregate(id); + TestAggregate result = new TestAggregate(id); result.init(); return result; } private static AmishAggregate newAmishAggregate(ProjectId id) { - final AmishAggregate result = new AmishAggregate(id); + AmishAggregate result = new AmishAggregate(id); result.init(); return result; } @@ -152,17 +157,9 @@ private static void failNotThrows() { fail("Should have thrown RuntimeException."); } - /** - * Casts {@linkplain TestAggregate the aggregate under the test} to {@link Aggregate}, - * class, which is in the same package with this test, so that we call package-access methods. - */ - private Aggregate aggregate() { - return aggregate; - } - private static List generateProjectEvents() { - final String projectName = AggregateShould.class.getSimpleName(); - final List events = ImmutableList.builder() + String projectName = AggregateShould.class.getSimpleName(); + List events = ImmutableList.builder() .add(event(projectCreated(ID, projectName), 1)) .add(event(taskAdded(ID), 3)) .add(event(projectStarted(ID), 4)) @@ -170,6 +167,31 @@ private static List generateProjectEvents() { return events; } + /** + * A convenience method for closing the bounded context. + * + *

Instead of a checked {@link java.io.IOException IOException}, wraps any issues + * that may occur while closing, into an {@link IllegalStateException}. + * + * @param boundedContext a bounded context to close + */ + private static void closeContext(BoundedContext boundedContext) { + checkNotNull(boundedContext); + try { + boundedContext.close(); + } catch (Exception e) { + throw Exceptions.illegalStateWithCauseOf(e); + } + } + + /** + * Casts {@linkplain TestAggregate the aggregate under the test} to {@link Aggregate}, + * class, which is in the same package with this test, so that we call package-access methods. + */ + private Aggregate aggregate() { + return aggregate; + } + @Before public void setUp() { ModelTests.clearModel(); @@ -198,7 +220,7 @@ public void handle_one_command_and_apply_appropriate_event() { @Test public void advances_the_version_by_one_upon_handling_command_with_one_event() { - final int version = aggregate.versionNumber(); + int version = aggregate.versionNumber(); dispatchCommand(aggregate, env(createProject)); @@ -210,9 +232,9 @@ public void advances_the_version_by_one_upon_handling_command_with_one_event() { */ @Test public void advances_the_version_by_one_with_single_event_and_with_empty_event_applier() { - final int version = amishAggregate.versionNumber(); + int version = amishAggregate.versionNumber(); - final List messages = dispatchCommand(amishAggregate, env(pauseProject)); + List messages = dispatchCommand(amishAggregate, env(pauseProject)); assertEquals(1, messages.size()); assertEquals(version + 1, amishAggregate.versionNumber()); @@ -223,9 +245,9 @@ public void advances_the_version_by_one_with_single_event_and_with_empty_event_a */ @Test public void advances_the_version_by_number_of_events_with_several_events_and_empty_appliers() { - final int version = amishAggregate.versionNumber(); + int version = amishAggregate.versionNumber(); - final List eventMessages = + List eventMessages = dispatchCommand(amishAggregate, env(cancelProject)); // Expecting to return more than one to differ from other testing scenarios. assertTrue(eventMessages.size() > 1); @@ -238,9 +260,9 @@ public void write_its_version_into_event_context() { dispatchCommand(aggregate, env(createProject)); // Get the first event since the command handler produces only one event message. - final Aggregate agg = this.aggregate; - final List uncommittedEvents = agg.getUncommittedEvents(); - final Event event = uncommittedEvents.get(0); + Aggregate agg = this.aggregate; + List uncommittedEvents = agg.getUncommittedEvents(); + Event event = uncommittedEvents.get(0); assertEquals(this.aggregate.getVersion(), event.getContext() .getVersion()); @@ -292,7 +314,7 @@ public void react_on_rejection_by_rejection_and_command_message() { @Test(expected = IllegalStateException.class) public void throw_exception_if_missing_command_handler() { ModelTests.clearModel(); - final AggregateWithMissingApplier aggregate = new AggregateWithMissingApplier(ID); + AggregateWithMissingApplier aggregate = new AggregateWithMissingApplier(ID); // Pass a command for which the target aggregate does not have a handling method. dispatchCommand(aggregate, env(addTask)); @@ -301,7 +323,7 @@ public void throw_exception_if_missing_command_handler() { @Test(expected = IllegalStateException.class) public void throw_exception_if_missing_event_applier_for_non_state_neutral_event() { ModelTests.clearModel(); - final AggregateWithMissingApplier aggregate = + AggregateWithMissingApplier aggregate = new AggregateWithMissingApplier(ID); try { dispatchCommand(aggregate, env(createProject)); @@ -313,12 +335,12 @@ public void throw_exception_if_missing_event_applier_for_non_state_neutral_event @Test public void return_command_classes_which_are_handled_by_aggregate() { - final Set commandClasses = + Set commandClasses = Model.getInstance() .asAggregateClass(TestAggregate.class) .getCommands(); - assertTrue(commandClasses.size() == 4); + assertEquals(4, commandClasses.size()); assertContains(commandClasses, AggCreateProject.class, @@ -329,7 +351,7 @@ public void return_command_classes_which_are_handled_by_aggregate() { @Test public void return_default_state_by_default() { - final Project state = aggregate.getState(); + Project state = aggregate.getState(); assertEquals(aggregate.getDefaultState(), state); } @@ -338,7 +360,7 @@ public void return_default_state_by_default() { public void update_state_when_the_command_is_handled() { dispatchCommand(aggregate, env(createProject)); - final Project state = aggregate.getState(); + Project state = aggregate.getState(); assertEquals(ID, state.getId()); assertEquals(Status.CREATED, state.getStatus()); @@ -357,14 +379,14 @@ public void return_current_state_after_several_dispatches() { @Test public void return_non_null_time_when_was_last_modified() { - final Timestamp creationTime = new TestAggregate(ID).whenModified(); + Timestamp creationTime = new TestAggregate(ID).whenModified(); assertNotNull(creationTime); } @Test public void record_modification_time_when_command_handled() { try { - final Timestamp frozenTime = Time.getCurrentTime(); + Timestamp frozenTime = Time.getCurrentTime(); Time.setProvider(new TimeTests.FrozenMadHatterParty(frozenTime)); dispatchCommand(aggregate, env(createProject)); @@ -377,7 +399,7 @@ public void record_modification_time_when_command_handled() { @Test public void advance_version_on_command_handled() { - final int version = aggregate.versionNumber(); + int version = aggregate.versionNumber(); dispatchCommand(aggregate, env(createProject)); dispatchCommand(aggregate, env(startProject)); @@ -388,13 +410,13 @@ public void advance_version_on_command_handled() { @Test public void play_events() { - final List events = generateProjectEvents(); - final AggregateStateRecord aggregateStateRecord = + List events = generateProjectEvents(); + AggregateStateRecord aggregateStateRecord = AggregateStateRecord.newBuilder() .addAllEvent(events) .build(); - final AggregateTransaction tx = AggregateTransaction.start(aggregate); + AggregateTransaction tx = AggregateTransaction.start(aggregate); aggregate().play(aggregateStateRecord); tx.commit(); @@ -407,11 +429,11 @@ public void play_events() { public void restore_snapshot_during_play() { dispatchCommand(aggregate, env(createProject)); - final Snapshot snapshot = aggregate().toShapshot(); + Snapshot snapshot = aggregate().toShapshot(); - final Aggregate anotherAggregate = newAggregate(aggregate.getId()); + Aggregate anotherAggregate = newAggregate(aggregate.getId()); - final AggregateTransaction tx = AggregateTransaction.start(anotherAggregate); + AggregateTransaction tx = AggregateTransaction.start(anotherAggregate); anotherAggregate.play(AggregateStateRecord.newBuilder() .setSnapshot(snapshot) .build()); @@ -422,7 +444,7 @@ public void restore_snapshot_during_play() { @Test public void not_return_any_uncommitted_event_records_by_default() { - final List events = aggregate().getUncommittedEvents(); + List events = aggregate().getUncommittedEvents(); assertTrue(events.isEmpty()); } @@ -433,7 +455,7 @@ public void return_uncommitted_event_records_after_dispatch() { command(addTask), command(startProject)); - final List events = aggregate().getUncommittedEvents(); + List events = aggregate().getUncommittedEvents(); assertContains(getEventClasses(events), AggProjectCreated.class, AggTaskAdded.class, AggProjectStarted.class); @@ -441,7 +463,7 @@ public void return_uncommitted_event_records_after_dispatch() { @Test public void not_return_any_event_records_when_commit_by_default() { - final List events = aggregate().commitEvents(); + List events = aggregate().commitEvents(); assertTrue(events.isEmpty()); } @@ -452,7 +474,7 @@ public void return_events_when_commit_after_dispatch() { command(addTask), command(startProject)); - final List events = aggregate().commitEvents(); + List events = aggregate().commitEvents(); assertContains(getEventClasses(events), AggProjectCreated.class, AggTaskAdded.class, AggProjectStarted.class); @@ -464,10 +486,10 @@ public void clear_event_records_when_commit_after_dispatch() { command(addTask), command(startProject)); - final List events = aggregate().commitEvents(); + List events = aggregate().commitEvents(); assertFalse(events.isEmpty()); - final List emptyList = aggregate().commitEvents(); + List emptyList = aggregate().commitEvents(); assertTrue(emptyList.isEmpty()); } @@ -476,8 +498,8 @@ public void transform_current_state_to_snapshot_event() { dispatchCommand(aggregate, env(createProject)); - final Snapshot snapshot = aggregate().toShapshot(); - final Project state = unpack(snapshot.getState()); + Snapshot snapshot = aggregate().toShapshot(); + Project state = unpack(snapshot.getState()); assertEquals(ID, state.getId()); assertEquals(Status.CREATED, state.getStatus()); @@ -488,11 +510,11 @@ public void restore_state_from_snapshot() { dispatchCommand(aggregate, env(createProject)); - final Snapshot snapshotNewProject = aggregate().toShapshot(); + Snapshot snapshotNewProject = aggregate().toShapshot(); - final Aggregate anotherAggregate = newAggregate(aggregate.getId()); + Aggregate anotherAggregate = newAggregate(aggregate.getId()); - final AggregateTransaction tx = AggregateTransaction.start(anotherAggregate); + AggregateTransaction tx = AggregateTransaction.start(anotherAggregate); anotherAggregate.restore(snapshotNewProject); tx.commit(); @@ -503,9 +525,9 @@ public void restore_state_from_snapshot() { @Test public void import_events() { - final String projectName = getClass().getSimpleName(); - final ProjectId id = aggregate.getId(); - final ImportEvents importCmd = + String projectName = getClass().getSimpleName(); + ProjectId id = aggregate.getId(); + ImportEvents importCmd = ImportEvents.newBuilder() .setProjectId(id) .addEvent(event(projectCreated(id, projectName), 1)) @@ -519,8 +541,8 @@ public void import_events() { @Test public void increment_version_when_applying_state_changing_event() { - final int version = aggregate.getVersion() - .getNumber(); + int version = aggregate.getVersion() + .getNumber(); // Dispatch two commands that cause events that modify aggregate state. aggregate.dispatchCommands(command(createProject), command(startProject)); @@ -531,7 +553,7 @@ public void increment_version_when_applying_state_changing_event() { @Test public void record_modification_timestamp() { try { - final TimeTests.BackToTheFuture provider = new TimeTests.BackToTheFuture(); + TimeTests.BackToTheFuture provider = new TimeTests.BackToTheFuture(); Time.setProvider(provider); Timestamp currentTime = Time.getCurrentTime(); @@ -553,15 +575,15 @@ public void record_modification_timestamp() { @Test public void propagate_RuntimeException_when_handler_throws() { ModelTests.clearModel(); - final FaultyAggregate faultyAggregate = new FaultyAggregate(ID, true, false); + FaultyAggregate faultyAggregate = new FaultyAggregate(ID, true, false); - final Command command = Given.ACommand.createProject(); + Command command = Given.ACommand.createProject(); try { dispatchCommand(faultyAggregate, env(command.getMessage())); failNotThrows(); } catch (RuntimeException e) { @SuppressWarnings("ThrowableResultOfMethodCallIgnored") // We need it for checking. - final Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_HANDLER, cause.getMessage()); } @@ -570,17 +592,17 @@ public void propagate_RuntimeException_when_handler_throws() { @Test public void propagate_RuntimeException_when_applier_throws() { ModelTests.clearModel(); - final FaultyAggregate faultyAggregate = + FaultyAggregate faultyAggregate = new FaultyAggregate(ID, false, true); - final Command command = Given.ACommand.createProject(); + Command command = Given.ACommand.createProject(); try { dispatchCommand(faultyAggregate, env(command.getMessage())); failNotThrows(); } catch (RuntimeException e) { @SuppressWarnings("ThrowableResultOfMethodCallIgnored") // because we need it for checking. - final Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_APPLIER, cause.getMessage()); } @@ -589,12 +611,12 @@ public void propagate_RuntimeException_when_applier_throws() { @Test public void propagate_RuntimeException_when_play_raises_exception() { ModelTests.clearModel(); - final FaultyAggregate faultyAggregate = + FaultyAggregate faultyAggregate = new FaultyAggregate(ID, false, true); try { - final Event event = event(projectCreated(ID, getClass().getSimpleName()), 1); + Event event = event(projectCreated(ID, getClass().getSimpleName()), 1); - final AggregateTransaction tx = AggregateTransaction.start(faultyAggregate); + AggregateTransaction tx = AggregateTransaction.start(faultyAggregate); ((Aggregate) faultyAggregate).play(AggregateStateRecord.newBuilder() .addEvent(event) .build()); @@ -603,23 +625,24 @@ public void propagate_RuntimeException_when_play_raises_exception() { } catch (RuntimeException e) { @SuppressWarnings("ThrowableResultOfMethodCallIgnored") // because we need it for checking. - final Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_APPLIER, cause.getMessage()); } } - @Test(expected = IllegalStateException.class) + @Test public void do_not_allow_getting_state_builder_from_outside_the_event_applier() { + thrown.expect(IllegalStateException.class); new IntAggregate(100).getBuilder(); } @Test public void throw_InvalidEntityStateException_if_state_is_invalid() { - final User user = User.newBuilder() - .setFirstName("|") - .setLastName("|") - .build(); + User user = User.newBuilder() + .setFirstName("|") + .setLastName("|") + .build(); try { aggregateOfClass(UserAggregate.class).withId(getClass().getName()) .withVersion(1) @@ -627,9 +650,9 @@ public void throw_InvalidEntityStateException_if_state_is_invalid() { .build(); fail(); } catch (InvalidEntityStateException e) { - final List violations = e.getError() - .getValidationError() - .getConstraintViolationList(); + List violations = e.getError() + .getValidationError() + .getConstraintViolationList(); assertSize(user.getAllFields() .size(), violations); } @@ -637,33 +660,36 @@ public void throw_InvalidEntityStateException_if_state_is_invalid() { @Test public void update_valid_entity_state() { - final User user = User.newBuilder() - .setFirstName("Fname") - .setLastName("Lname") - .build(); - aggregateOfClass(UserAggregate.class).withId(getClass().getName()) - .withVersion(1) - .withState(user) - .build(); + User user = User.newBuilder() + .setFirstName("Fname") + .setLastName("Lname") + .build(); + UserAggregate aggregate = aggregateOfClass(UserAggregate.class) + .withId(getClass().getName()) + .withVersion(1) + .withState(user) + .build(); + + assertEquals(user, aggregate.getState()); } @Test public void traverse_the_history_iterating_through_newest_events_first() { - final TenantId tenantId = newTenantId(); - final Command createCommand = command(createProject, tenantId); - final Command startCommand = command(startProject, tenantId); - final Command addTaskCommand = command(addTask, tenantId); - final Command addTaskCommand2 = command(addTask, tenantId); - - final CommandBus commandBus = boundedContext.getCommandBus(); - final StreamObserver noOpObserver = noOpObserver(); + TenantId tenantId = newTenantId(); + Command createCommand = command(createProject, tenantId); + Command startCommand = command(startProject, tenantId); + Command addTaskCommand = command(addTask, tenantId); + Command addTaskCommand2 = command(addTask, tenantId); + + CommandBus commandBus = boundedContext.getCommandBus(); + StreamObserver noOpObserver = noOpObserver(); commandBus.post(createCommand, noOpObserver); commandBus.post(addTaskCommand, noOpObserver); commandBus.post(newArrayList(addTaskCommand2, startCommand), noOpObserver); - final TestAggregate aggregate = repository.loadAggregate(tenantId, ID); + TestAggregate aggregate = repository.loadAggregate(tenantId, ID); - final Iterator history = aggregate.historyBackward(); + Iterator history = aggregate.historyBackward(); assertEquals(startCommand.getId(), getRootCommandId(history.next())); assertEquals(addTaskCommand2.getId(), getRootCommandId(history.next())); @@ -676,21 +702,21 @@ public void traverse_the_history_iterating_through_newest_events_first() { public void traverse_the_history_up_to_the_latest_snapshot() { repository.setSnapshotTrigger(3); - final TenantId tenantId = newTenantId(); - final Command createCommand = command(createProject, tenantId); - final Command startCommand = command(startProject, tenantId); - final Command addTaskCommand = command(addTask, tenantId); - final Command addTaskCommand2 = command(addTask, tenantId); + TenantId tenantId = newTenantId(); + Command createCommand = command(createProject, tenantId); + Command startCommand = command(startProject, tenantId); + Command addTaskCommand = command(addTask, tenantId); + Command addTaskCommand2 = command(addTask, tenantId); - final CommandBus commandBus = boundedContext.getCommandBus(); - final StreamObserver noOpObserver = noOpObserver(); + CommandBus commandBus = boundedContext.getCommandBus(); + StreamObserver noOpObserver = noOpObserver(); commandBus.post(createCommand, noOpObserver); commandBus.post(startCommand, noOpObserver); commandBus.post(newArrayList(addTaskCommand, addTaskCommand2), noOpObserver); - final TestAggregate aggregate = repository.loadAggregate(tenantId, ID); + TestAggregate aggregate = repository.loadAggregate(tenantId, ID); - final Iterator history = aggregate.historyBackward(); + Iterator history = aggregate.historyBackward(); assertEquals(addTaskCommand2.getId(), getRootCommandId(history.next())); assertFalse(history.hasNext()); @@ -698,21 +724,21 @@ public void traverse_the_history_up_to_the_latest_snapshot() { @Test public void acknowledge_DuplicateCommandException_when_the_command_was_handled_since_last_snapshot() { - final TenantId tenantId = newTenantId(); - final Command createCommand = command(createProject, tenantId); + TenantId tenantId = newTenantId(); + Command createCommand = command(createProject, tenantId); - final CommandBus commandBus = boundedContext.getCommandBus(); - final StreamObserver noOpObserver = noOpObserver(); - final MemoizingObserver memoizingObserver = memoizingObserver(); + CommandBus commandBus = boundedContext.getCommandBus(); + StreamObserver noOpObserver = noOpObserver(); + MemoizingObserver memoizingObserver = memoizingObserver(); commandBus.post(createCommand, noOpObserver); commandBus.post(createCommand, memoizingObserver); - final List responses = memoizingObserver.responses(); - final Ack ack = responses.get(0); + List responses = memoizingObserver.responses(); + Ack ack = responses.get(0); assertTrue(ack.getStatus() .hasError()); - final String errorType = DuplicateCommandException.class.getCanonicalName(); + String errorType = DuplicateCommandException.class.getCanonicalName(); assertEquals(errorType, ack.getStatus() .getError() .getType()); @@ -728,29 +754,29 @@ public void acknowledge_DuplicateCommandException_when_the_command_was_handled_s */ @Test public void create_single_event_for_a_pair_of_events_with_empty_for_a_command_dispatch() { - final BoundedContext boundedContext = newTaskBoundedContext(); + BoundedContext boundedContext = newTaskBoundedContext(); - final TenantId tenantId = newTenantId(); - final Command command = command(createTask(), tenantId); - final MemoizingObserver observer = memoizingObserver(); + TenantId tenantId = newTenantId(); + Command command = command(createTask(), tenantId); + MemoizingObserver observer = memoizingObserver(); boundedContext.getCommandBus() .post(command, observer); assertNull(observer.getError()); - final List responses = observer.responses(); + List responses = observer.responses(); assertSize(1, responses); - final Ack response = responses.get(0); - final io.spine.core.Status status = response.getStatus(); - final Error emptyError = Error.getDefaultInstance(); + Ack response = responses.get(0); + io.spine.core.Status status = response.getStatus(); + Error emptyError = Error.getDefaultInstance(); assertEquals(emptyError, status.getError()); - final Rejection emptyRejection = Rejection.getDefaultInstance(); + Rejection emptyRejection = Rejection.getDefaultInstance(); assertEquals(emptyRejection, status.getRejection()); - final List events = readAllEvents(boundedContext, tenantId); + List events = readAllEvents(boundedContext, tenantId); assertSize(1, events); closeContext(boundedContext); } @@ -766,37 +792,37 @@ public void create_single_event_for_a_pair_of_events_with_empty_for_a_command_di */ @Test public void create_single_event_for_a_pair_of_events_with_empty_for_an_event_react() { - final BoundedContext boundedContext = newTaskBoundedContext(); + BoundedContext boundedContext = newTaskBoundedContext(); - final TenantId tenantId = newTenantId(); - final Command command = command(assignTask(), tenantId); - final MemoizingObserver observer = memoizingObserver(); + TenantId tenantId = newTenantId(); + Command command = command(assignTask(), tenantId); + MemoizingObserver observer = memoizingObserver(); boundedContext.getCommandBus() .post(command, observer); assertNull(observer.getError()); - final List responses = observer.responses(); + List responses = observer.responses(); assertSize(1, responses); - final Ack response = responses.get(0); - final io.spine.core.Status status = response.getStatus(); - final Error emptyError = Error.getDefaultInstance(); + Ack response = responses.get(0); + io.spine.core.Status status = response.getStatus(); + Error emptyError = Error.getDefaultInstance(); assertEquals(emptyError, status.getError()); - final Rejection emptyRejection = Rejection.getDefaultInstance(); + Rejection emptyRejection = Rejection.getDefaultInstance(); assertEquals(emptyRejection, status.getRejection()); - final List events = readAllEvents(boundedContext, tenantId); + List events = readAllEvents(boundedContext, tenantId); assertSize(2, events); - final Event sourceEvent = events.get(0); - final TypeUrl taskAssignedType = TypeUrl.from(AggTaskAssigned.getDescriptor()); + Event sourceEvent = events.get(0); + TypeUrl taskAssignedType = TypeUrl.from(AggTaskAssigned.getDescriptor()); assertEquals(typeUrlOf(sourceEvent), taskAssignedType); - final Event reactionEvent = events.get(1); - final TypeUrl userNotifiedType = TypeUrl.from(AggUserNotified.getDescriptor()); + Event reactionEvent = events.get(1); + TypeUrl userNotifiedType = TypeUrl.from(AggUserNotified.getDescriptor()); assertEquals(typeUrlOf(reactionEvent), userNotifiedType); closeContext(boundedContext); @@ -813,52 +839,35 @@ public void create_single_event_for_a_pair_of_events_with_empty_for_an_event_rea */ @Test public void create_single_event_for_a_pair_of_events_with_empty_for_a_rejection_react() { - final BoundedContext boundedContext = newTaskBoundedContext(); + BoundedContext boundedContext = newTaskBoundedContext(); - final TenantId tenantId = newTenantId(); - final Command command = command(reassignTask(), tenantId); - final MemoizingObserver observer = memoizingObserver(); + TenantId tenantId = newTenantId(); + Command command = command(reassignTask(), tenantId); + MemoizingObserver observer = memoizingObserver(); boundedContext.getCommandBus() .post(command, observer); assertNull(observer.getError()); - final List responses = observer.responses(); + List responses = observer.responses(); assertSize(1, responses); - final Ack response = responses.get(0); - final io.spine.core.Status status = response.getStatus(); - final Error emptyError = Error.getDefaultInstance(); + Ack response = responses.get(0); + io.spine.core.Status status = response.getStatus(); + Error emptyError = Error.getDefaultInstance(); assertEquals(emptyError, status.getError()); - final Rejection emptyRejection = Rejection.getDefaultInstance(); + Rejection emptyRejection = Rejection.getDefaultInstance(); assertEquals(emptyRejection, status.getRejection()); - final List events = readAllEvents(boundedContext, tenantId); + List events = readAllEvents(boundedContext, tenantId); assertSize(1, events); - final Event reactionEvent = events.get(0); - final TypeUrl userNotifiedType = TypeUrl.from(AggUserNotified.getDescriptor()); + Event reactionEvent = events.get(0); + TypeUrl userNotifiedType = TypeUrl.from(AggUserNotified.getDescriptor()); assertEquals(typeUrlOf(reactionEvent), userNotifiedType); closeContext(boundedContext); } - - /** - * A convenience method for closing the bounded context. - * - *

Instead of a checked {@link java.io.IOException IOException}, wraps any issues - * that may occur while closing, into an {@link IllegalStateException}. - * - * @param boundedContext a bounded context to close - */ - private static void closeContext(BoundedContext boundedContext) { - checkNotNull(boundedContext); - try { - boundedContext.close(); - } catch (Exception e) { - throw Exceptions.illegalStateWithCauseOf(e); - } - } } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java index 19a5a9568a8..80f3bd93737 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java @@ -41,9 +41,9 @@ import io.spine.test.aggregate.ProjectId; import io.spine.test.aggregate.ProjectVBuilder; import io.spine.testdata.Sample; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Iterator; import java.util.List; @@ -70,45 +70,48 @@ * @author Alexander Litus */ public abstract class AggregateStorageShould - extends AbstractStorageShould, - AggregateStorage> { + extends AbstractStorageShould< + ProjectId, + AggregateStateRecord, + AggregateReadRequest, + AggregateStorage + > { + protected static final Function TO_EVENT = + new Function() { + @Override // return null because an exception won't be propagated in this case + public @Nullable Event apply(@Nullable AggregateEventRecord input) { + return (input == null) ? null : input.getEvent(); + } + }; private final ProjectId id = Sample.messageOfType(ProjectId.class); private final TestEventFactory eventFactory = newInstance(AggregateStorageShould.class); - private AggregateStorage storage; + private static Snapshot newSnapshot(Timestamp time) { + return Snapshot.newBuilder() + .setState(Any.getDefaultInstance()) + .setTimestamp(time) + .build(); + } + + private static EventId newEventId() { + return EventId.newBuilder() + .setValue(newUuid()) + .build(); + } + @Override public void setUpAbstractStorageTest() { super.setUpAbstractStorageTest(); storage = getStorage(); } - @Override - protected Class getTestEntityClass() { - return TestAggregate.class; - } - - /** - * Creates the storage for the specified ID and aggregate class. - * - *

The created storage should be closed manually. - * - * @param idClass the class of aggregate ID - * @param aggregateClass the aggregate class - * @param the type of aggregate IDs - * @return a new storage instance - */ - protected abstract AggregateStorage newStorage(Class idClass, - Class> aggregateClass); - @Override protected AggregateStateRecord newStorageRecord() { - final List records = sequenceFor(id); - final List expectedEvents = transform(records, TO_EVENT); - final AggregateStateRecord aggregateStateRecord = + List records = sequenceFor(id); + List expectedEvents = transform(records, TO_EVENT); + AggregateStateRecord aggregateStateRecord = AggregateStateRecord.newBuilder() .addAllEvent(expectedEvents) .build(); @@ -125,44 +128,77 @@ protected AggregateReadRequest newReadRequest(ProjectId id) { return new AggregateReadRequest<>(id, MAX_VALUE); } + @Override + protected Class getTestEntityClass() { + return TestAggregate.class; + } + + // Ignore this test because several records can be stored by an aggregate ID. + @Override + @SuppressWarnings({ + "NoopMethodInAbstractClass", + "RefusedBequest", + "MethodDoesntCallSuperMethod" + }) + public void rewrite_record_if_write_by_the_same_id() { + } + + /** + * Creates the storage for the specified ID and aggregate class. + * + *

The created storage should be closed manually. + * + * @param idClass the class of aggregate ID + * @param aggregateClass the aggregate class + * @param the type of aggregate IDs + * @return a new storage instance + */ + protected abstract AggregateStorage + newStorage(Class idClass, Class> aggregateClass); + @Test public void return_iterator_over_empty_collection_if_read_history_from_empty_storage() { - final Iterator iterator = historyBackward(); + Iterator iterator = historyBackward(); assertFalse(iterator.hasNext()); } @Test public void return_absent_AggregateStateRecord_if_read_history_from_empty_storage() { - final AggregateReadRequest readRequest = newReadRequest(id); - final Optional aggregateStateRecord = storage.read(readRequest); + AggregateReadRequest readRequest = newReadRequest(id); + Optional aggregateStateRecord = storage.read(readRequest); assertFalse(aggregateStateRecord.isPresent()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_read_history_by_null_id() { - storage.historyBackward(Tests.>nullRef()); + thrown.expect(NullPointerException.class); + storage.historyBackward(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_write_null_event() { - storage.writeEvent(id, Tests.nullRef()); + thrown.expect(NullPointerException.class); + storage.writeEvent(id, Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_write_event_by_null_id() { - storage.writeEvent(Tests.nullRef(), Event.getDefaultInstance()); + thrown.expect(NullPointerException.class); + storage.writeEvent(Tests.nullRef(), Event.getDefaultInstance()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_write_null_snapshot() { - storage.write(id, Tests.nullRef()); + thrown.expect(NullPointerException.class); + storage.write(id, Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_write_snapshot_by_null_id() { - storage.writeSnapshot(Tests.nullRef(), Snapshot.getDefaultInstance()); + thrown.expect(NullPointerException.class); + storage.writeSnapshot(Tests.nullRef(), Snapshot.getDefaultInstance()); } @Test @@ -172,64 +208,64 @@ public void write_read_and_one_event_by_Message_id() { @Test public void write_and_read_event_by_String_id() { - final AggregateStorage storage = newStorage(String.class, - TestAggregateWithIdString.class); - final String id = newUuid(); + AggregateStorage storage = newStorage(String.class, + TestAggregateWithIdString.class); + String id = newUuid(); writeAndReadEventTest(id, storage); } @Test public void write_and_read_event_by_Long_id() { - final AggregateStorage storage = newStorage(Long.class, - TestAggregateWithIdLong.class); - final long id = 10L; + AggregateStorage storage = newStorage(Long.class, + TestAggregateWithIdLong.class); + long id = 10L; writeAndReadEventTest(id, storage); } @Test public void write_and_read_event_by_Integer_id() { - final AggregateStorage storage = newStorage(Integer.class, - TestAggregateWithIdInteger.class); - final int id = 10; + AggregateStorage storage = newStorage(Integer.class, + TestAggregateWithIdInteger.class); + int id = 10; writeAndReadEventTest(id, storage); } @Test public void write_and_read_one_record() { - final AggregateEventRecord expected = StorageRecord.create(getCurrentTime()); + AggregateEventRecord expected = StorageRecord.create(getCurrentTime()); storage.writeRecord(id, expected); - final Iterator iterator = historyBackward(); + Iterator iterator = historyBackward(); assertTrue(iterator.hasNext()); - final AggregateEventRecord actual = iterator.next(); + AggregateEventRecord actual = iterator.next(); assertEquals(expected, actual); assertFalse(iterator.hasNext()); } @Test public void read_history_of_archived_aggregate() { - final LifecycleFlags archivedRecordFlags = LifecycleFlags.newBuilder() - .setArchived(true) - .build(); + LifecycleFlags archivedRecordFlags = LifecycleFlags.newBuilder() + .setArchived(true) + .build(); storage.writeLifecycleFlags(id, archivedRecordFlags); writeAndReadEventTest(id, storage); } @Test public void read_history_of_deleted_aggregate() { - final LifecycleFlags deletedRecordFlags = LifecycleFlags.newBuilder() - .setDeleted(true) - .build(); + LifecycleFlags deletedRecordFlags = LifecycleFlags.newBuilder() + .setDeleted(true) + .build(); storage.writeLifecycleFlags(id, deletedRecordFlags); writeAndReadEventTest(id, storage); } @Test public void index_archived_aggregate() { - final LifecycleFlags archivedRecordFlags = LifecycleFlags.newBuilder() - .setArchived(true) - .build(); + LifecycleFlags archivedRecordFlags = LifecycleFlags.newBuilder() + .setArchived(true) + .build(); storage.writeRecord(id, StorageRecord.create(getCurrentTime())); storage.writeLifecycleFlags(id, archivedRecordFlags); assertTrue(storage.index() @@ -238,9 +274,9 @@ public void index_archived_aggregate() { @Test public void index_deleted_aggregate() { - final LifecycleFlags deletedRecordFlags = LifecycleFlags.newBuilder() - .setDeleted(true) - .build(); + LifecycleFlags deletedRecordFlags = LifecycleFlags.newBuilder() + .setDeleted(true) + .build(); storage.writeRecord(id, StorageRecord.create(getCurrentTime())); storage.writeLifecycleFlags(id, deletedRecordFlags); assertTrue(storage.index() @@ -249,67 +285,67 @@ public void index_deleted_aggregate() { @Test public void write_records_and_return_sorted_by_timestamp_descending() { - final List records = sequenceFor(id); + List records = sequenceFor(id); writeAll(id, records); - final Iterator iterator = historyBackward(); - final List actual = newArrayList(iterator); + Iterator iterator = historyBackward(); + List actual = newArrayList(iterator); reverse(records); // expected records should be in a reverse order assertEquals(records, actual); } @Test public void write_records_and_return_sorted_by_version_descending() { - final int eventsNumber = 5; - final List records = newLinkedList(); - final Timestamp timestamp = getCurrentTime(); + int eventsNumber = 5; + List records = newLinkedList(); + Timestamp timestamp = getCurrentTime(); Version currentVersion = zero(); for (int i = 0; i < eventsNumber; i++) { - final Project state = Project.getDefaultInstance(); - final Event event = eventFactory.createEvent(state, currentVersion, timestamp); - final AggregateEventRecord record = StorageRecord.create(timestamp, event); + Project state = Project.getDefaultInstance(); + Event event = eventFactory.createEvent(state, currentVersion, timestamp); + AggregateEventRecord record = StorageRecord.create(timestamp, event); records.add(record); currentVersion = increment(currentVersion); } writeAll(id, records); - final Iterator iterator = historyBackward(); - final List actual = newArrayList(iterator); + Iterator iterator = historyBackward(); + List actual = newArrayList(iterator); reverse(records); // expected records should be in a reverse order assertEquals(records, actual); } @Test public void sort_by_version_rather_then_by_timestamp() { - final Project state = Project.getDefaultInstance(); - final Version minVersion = zero(); - final Version maxVersion = increment(minVersion); - final Timestamp minTimestamp = Timestamps.MIN_VALUE; - final Timestamp maxTimestamp = Timestamps.MAX_VALUE; + Project state = Project.getDefaultInstance(); + Version minVersion = zero(); + Version maxVersion = increment(minVersion); + Timestamp minTimestamp = Timestamps.MIN_VALUE; + Timestamp maxTimestamp = Timestamps.MAX_VALUE; // The first event is an event, which is the oldest, i.e. with the minimal version. - final Event expectedFirst = eventFactory.createEvent(state, minVersion, maxTimestamp); - final Event expectedSecond = eventFactory.createEvent(state, maxVersion, minTimestamp); + Event expectedFirst = eventFactory.createEvent(state, minVersion, maxTimestamp); + Event expectedSecond = eventFactory.createEvent(state, maxVersion, minTimestamp); storage.writeEvent(id, expectedSecond); storage.writeEvent(id, expectedFirst); - final List events = storage.read(newReadRequest(id)) - .get() - .getEventList(); + List events = storage.read(newReadRequest(id)) + .get() + .getEventList(); assertTrue(events.indexOf(expectedFirst) < events.indexOf(expectedSecond)); } @Test public void write_and_read_snapshot() { - final Snapshot expected = newSnapshot(getCurrentTime()); + Snapshot expected = newSnapshot(getCurrentTime()); storage.writeSnapshot(id, expected); - final Iterator iterator = historyBackward(); + Iterator iterator = historyBackward(); assertTrue(iterator.hasNext()); - final AggregateEventRecord actual = iterator.next(); + AggregateEventRecord actual = iterator.next(); assertEquals(expected, actual.getSnapshot()); assertFalse(iterator.hasNext()); } @@ -321,10 +357,10 @@ public void write_records_and_load_history_if_no_snapshots() { @Test public void write_records_and_load_history_till_last_snapshot() { - final Duration delta = seconds(10); - final Timestamp time1 = getCurrentTime(); - final Timestamp time2 = add(time1, delta); - final Timestamp time3 = add(time2, delta); + Duration delta = seconds(10); + Timestamp time1 = getCurrentTime(); + Timestamp time2 = add(time1, delta); + Timestamp time3 = add(time2, delta); storage.writeRecord(id, StorageRecord.create(time1)); storage.writeSnapshot(id, newSnapshot(time2)); @@ -339,22 +375,22 @@ public void return_zero_event_count_after_last_snapshot_by_default() { @Test public void write_and_read_event_count_after_last_snapshot() { - final int expectedCount = 32; + int expectedCount = 32; storage.writeEventCountAfterLastSnapshot(id, expectedCount); - final int actualCount = storage.readEventCountAfterLastSnapshot(id); + int actualCount = storage.readEventCountAfterLastSnapshot(id); assertEquals(expectedCount, actualCount); } @Test public void rewrite_event_count_after_last_snapshot() { - final int primaryValue = 16; + int primaryValue = 16; storage.writeEventCountAfterLastSnapshot(id, primaryValue); - final int expectedValue = 32; + int expectedValue = 32; storage.writeEventCountAfterLastSnapshot(id, expectedValue); - final int actualCount = storage.readEventCountAfterLastSnapshot(id); + int actualCount = storage.readEventCountAfterLastSnapshot(id); assertEquals(expectedValue, actualCount); } @@ -362,88 +398,88 @@ public void rewrite_event_count_after_last_snapshot() { @Test public void continue_history_reading_if_snapshot_was_not_found_in_first_batch() { Version currentVersion = zero(); - final Snapshot snapshot = Snapshot.newBuilder() - .setVersion(currentVersion) - .build(); + Snapshot snapshot = Snapshot.newBuilder() + .setVersion(currentVersion) + .build(); storage.writeSnapshot(id, snapshot); - final int eventCountAfterSnapshot = 10; + int eventCountAfterSnapshot = 10; for (int i = 0; i < eventCountAfterSnapshot; i++) { currentVersion = increment(currentVersion); - final Project state = Project.getDefaultInstance(); - final Event event = eventFactory.createEvent(state, currentVersion); + Project state = Project.getDefaultInstance(); + Event event = eventFactory.createEvent(state, currentVersion); storage.writeEvent(id, event); } - final int batchSize = 1; - final AggregateReadRequest request = new AggregateReadRequest<>(id, batchSize); - final Optional optionalStateRecord = storage.read(request); + int batchSize = 1; + AggregateReadRequest request = new AggregateReadRequest<>(id, batchSize); + Optional optionalStateRecord = storage.read(request); assertTrue(optionalStateRecord.isPresent()); - final AggregateStateRecord stateRecord = optionalStateRecord.get(); + AggregateStateRecord stateRecord = optionalStateRecord.get(); assertEquals(snapshot, stateRecord.getSnapshot()); assertEquals(eventCountAfterSnapshot, stateRecord.getEventCount()); } @Test public void not_store_enrichment_for_EventContext() { - final EventContext enrichedContext = EventContext.newBuilder() - .setEnrichment(withOneAttribute()) - .build(); - final Event event = Event.newBuilder() - .setId(newEventId()) - .setContext(enrichedContext) - .setMessage(Any.getDefaultInstance()) - .build(); + EventContext enrichedContext = EventContext.newBuilder() + .setEnrichment(withOneAttribute()) + .build(); + Event event = Event.newBuilder() + .setId(newEventId()) + .setContext(enrichedContext) + .setMessage(Any.getDefaultInstance()) + .build(); storage.writeEvent(id, event); - final EventContext loadedContext = storage.read(newReadRequest(id)) - .get() - .getEvent(0) - .getContext(); + EventContext loadedContext = storage.read(newReadRequest(id)) + .get() + .getEvent(0) + .getContext(); assertTrue(isDefault(loadedContext.getEnrichment())); } @Test public void not_store_enrichment_for_origin_of_RejectionContext_type() { - final RejectionContext origin = RejectionContext.newBuilder() - .setEnrichment(withOneAttribute()) - .build(); - final EventContext context = EventContext.newBuilder() - .setRejectionContext(origin) - .build(); - final Event event = Event.newBuilder() - .setId(newEventId()) - .setContext(context) - .setMessage(Any.getDefaultInstance()) - .build(); + RejectionContext origin = RejectionContext.newBuilder() + .setEnrichment(withOneAttribute()) + .build(); + EventContext context = EventContext.newBuilder() + .setRejectionContext(origin) + .build(); + Event event = Event.newBuilder() + .setId(newEventId()) + .setContext(context) + .setMessage(Any.getDefaultInstance()) + .build(); storage.writeEvent(id, event); - final RejectionContext loadedOrigin = storage.read(newReadRequest(id)) - .get() - .getEvent(0) - .getContext() - .getRejectionContext(); + RejectionContext loadedOrigin = storage.read(newReadRequest(id)) + .get() + .getEvent(0) + .getContext() + .getRejectionContext(); assertTrue(isDefault(loadedOrigin.getEnrichment())); } @Test public void not_store_enrichment_for_origin_of_EventContext_type() { - final EventContext origin = EventContext.newBuilder() - .setEnrichment(withOneAttribute()) - .build(); - final EventContext context = EventContext.newBuilder() - .setEventContext(origin) - .build(); - final Event event = Event.newBuilder() - .setId(newEventId()) - .setContext(context) - .setMessage(Any.getDefaultInstance()) - .build(); + EventContext origin = EventContext.newBuilder() + .setEnrichment(withOneAttribute()) + .build(); + EventContext context = EventContext.newBuilder() + .setEventContext(origin) + .build(); + Event event = Event.newBuilder() + .setId(newEventId()) + .setContext(context) + .setMessage(Any.getDefaultInstance()) + .build(); storage.writeEvent(id, event); - final EventContext loadedOrigin = storage.read(newReadRequest(id)) - .get() - .getEvent(0) - .getContext() - .getEventContext(); + EventContext loadedOrigin = storage.read(newReadRequest(id)) + .get() + .getEvent(0) + .getContext() + .getEventContext(); assertTrue(isDefault(loadedOrigin.getEnrichment())); } @@ -469,53 +505,49 @@ public void read_archived_and_deleted_records() { .build()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_write_event_count_to_closed_storage() { close(storage); + thrown.expect(IllegalStateException.class); storage.writeEventCountAfterLastSnapshot(id, 5); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_read_event_count_from_closed_storage() { close(storage); + thrown.expect(IllegalStateException.class); storage.readEventCountAfterLastSnapshot(id); } @SuppressWarnings("OptionalGetWithoutIsPresent") // OK as we write right before we get. private void writeAndReadEventTest(I id, AggregateStorage storage) { - final Event expectedEvent = eventFactory.createEvent(Time.getCurrentTime()); + Event expectedEvent = eventFactory.createEvent(Time.getCurrentTime()); storage.writeEvent(id, expectedEvent); - final AggregateReadRequest readRequest = new AggregateReadRequest<>(id, MAX_VALUE); - final AggregateStateRecord events = storage.read(readRequest) - .get(); + AggregateReadRequest readRequest = new AggregateReadRequest<>(id, MAX_VALUE); + AggregateStateRecord events = storage.read(readRequest) + .get(); assertEquals(1, events.getEventCount()); - final Event actualEvent = events.getEvent(0); + Event actualEvent = events.getEvent(0); assertEquals(expectedEvent, actualEvent); close(storage); } - // Ignore this test because several records can be stored by an aggregate ID. - @Override - @SuppressWarnings({"NoopMethodInAbstractClass", "RefusedBequest", "MethodDoesntCallSuperMethod"}) - public void rewrite_record_if_write_by_the_same_id() { - } - @SuppressWarnings({"OptionalGetWithoutIsPresent", "ConstantConditions"}) // OK as we write right before we get. protected void testWriteRecordsAndLoadHistory(Timestamp firstRecordTime) { - final List records = sequenceFor(id, firstRecordTime); + List records = sequenceFor(id, firstRecordTime); writeAll(id, records); - final AggregateStateRecord events = storage.read(newReadRequest(id)) - .get(); - final List expectedEvents = transform(records, TO_EVENT); - final List actualEvents = events.getEventList(); + AggregateStateRecord events = storage.read(newReadRequest(id)) + .get(); + List expectedEvents = transform(records, TO_EVENT); + List actualEvents = events.getEventList(); assertEquals(expectedEvents, actualEvents); } @@ -526,42 +558,20 @@ protected void writeAll(ProjectId id, Iterable records) { } private Iterator historyBackward() { - final AggregateReadRequest readRequest = newReadRequest(id); + AggregateReadRequest readRequest = newReadRequest(id); return storage.historyBackward(readRequest); } private void readRecordsWithLifecycle(LifecycleFlags flags) { - final AggregateStateRecord record = newStorageRecord(); + AggregateStateRecord record = newStorageRecord(); storage.write(id, record); storage.writeLifecycleFlags(id, flags); - final Optional read = storage.read(newReadRequest(id)); + Optional read = storage.read(newReadRequest(id)); assertTrue(read.isPresent()); - final AggregateStateRecord readRecord = read.get(); + AggregateStateRecord readRecord = read.get(); assertEquals(record, readRecord); } - protected static final Function TO_EVENT = - new Function() { - @Nullable // return null because an exception won't be propagated in this case - @Override - public Event apply(@Nullable AggregateEventRecord input) { - return (input == null) ? null : input.getEvent(); - } - }; - - private static Snapshot newSnapshot(Timestamp time) { - return Snapshot.newBuilder() - .setState(Any.getDefaultInstance()) - .setTimestamp(time) - .build(); - } - - private static EventId newEventId() { - return EventId.newBuilder() - .setValue(newUuid()) - .build(); - } - public static class TestAggregate extends Aggregate { protected TestAggregate(ProjectId id) { super(id); @@ -569,21 +579,21 @@ protected TestAggregate(ProjectId id) { } private static class TestAggregateWithIdString - extends Aggregate { + extends Aggregate { private TestAggregateWithIdString(String id) { super(id); } } private static class TestAggregateWithIdInteger - extends Aggregate { + extends Aggregate { private TestAggregateWithIdInteger(Integer id) { super(id); } } private static class TestAggregateWithIdLong - extends Aggregate { + extends Aggregate { private TestAggregateWithIdLong(Long id) { super(id); } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java index c7f5835f732..ec545680848 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java @@ -36,11 +36,11 @@ import io.spine.test.aggregate.event.AggProjectCreated; import io.spine.test.aggregate.event.AggTaskAdded; import io.spine.validate.ConstraintViolation; - import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; -import static com.google.common.collect.Lists.newLinkedList; +import static com.google.common.collect.Lists.newArrayList; import static io.spine.protobuf.AnyPacker.unpack; import static io.spine.server.aggregate.given.Given.EventMessage.projectCreated; import static org.junit.Assert.assertTrue; @@ -142,7 +142,7 @@ protected void breakEntityValidation( static class TestAggregate extends Aggregate { - private final List receivedEvents = newLinkedList(); + private final List receivedEvents = newArrayList(); private final List violations; private TestAggregate(ProjectId id) { @@ -167,13 +167,15 @@ AggProjectCreated handle(AggCreateProject cmd, CommandContext ctx) { return projectCreated(cmd.getProjectId(), cmd.getName()); } + @SuppressWarnings("CheckReturnValue") // calling builder @Apply void event(AggProjectCreated event) { receivedEvents.add(event); - final Project newState = Project.newBuilder(getState()) - .setId(event.getProjectId()) - .setName(event.getName()) - .build(); + Project newState = Project + .newBuilder(getState()) + .setId(event.getProjectId()) + .setName(event.getName()) + .build(); getBuilder().mergeFrom(newState); } diff --git a/server/src/test/java/io/spine/server/aggregate/given/AggregateCommandEndpointTestEnv.java b/server/src/test/java/io/spine/server/aggregate/given/AggregateCommandEndpointTestEnv.java index b0b9aa87396..dd4253c2dca 100644 --- a/server/src/test/java/io/spine/server/aggregate/given/AggregateCommandEndpointTestEnv.java +++ b/server/src/test/java/io/spine/server/aggregate/given/AggregateCommandEndpointTestEnv.java @@ -42,8 +42,8 @@ */ public class AggregateCommandEndpointTestEnv { + /** Prevent instantiation of this utility class. */ private AggregateCommandEndpointTestEnv() { - // Prevent instantiation of this utility class. } public static class ProjectAggregate @@ -68,9 +68,9 @@ public static void clearCommandsHandled() { AggProjectCreated handle(AggCreateProject msg, CommandContext context) { commandsHandled.add(msg, context); return AggProjectCreated.newBuilder() - .setProjectId(msg.getProjectId()) - .setName(msg.getName()) - .build(); + .setProjectId(msg.getProjectId()) + .setName(msg.getName()) + .build(); } @Apply diff --git a/server/src/test/java/io/spine/server/command/CommandHistory.java b/server/src/test/java/io/spine/server/command/CommandHistory.java index 816a8947485..a3cb5e92a6c 100644 --- a/server/src/test/java/io/spine/server/command/CommandHistory.java +++ b/server/src/test/java/io/spine/server/command/CommandHistory.java @@ -47,12 +47,12 @@ public void add(Message message, CommandContext context) { } public boolean contains(Command command) { - final Message message = Commands.getMessage(command); + Message message = Commands.getMessage(command); if (messages.contains(message)) { - final int messageIndex = messages.indexOf(message); - final CommandContext actualContext = command.getContext(); - final CommandContext storedContext = contexts.get(messageIndex); + int messageIndex = messages.indexOf(message); + CommandContext actualContext = command.getContext(); + CommandContext storedContext = contexts.get(messageIndex); return actualContext.equals(storedContext); } @@ -65,9 +65,9 @@ public void clear() { } public void assertHandled(Command expected) { - final String cmdName = Commands.getMessage(expected) - .getClass() - .getName(); + String cmdName = Commands.getMessage(expected) + .getClass() + .getName(); assertTrue("Expected but wasn't handled, command: " + cmdName, contains(expected)); } } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java index d81342a91cf..d9a66a5f034 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java @@ -29,10 +29,11 @@ import io.spine.core.EventContext; import io.spine.server.outbus.enrich.given.EnrichmentFunctionTestEnv.GivenEventMessage; import io.spine.test.event.ProjectCreated; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; - -import org.checkerframework.checker.nullness.qual.Nullable; +import org.junit.rules.ExpectedException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; @@ -44,20 +45,21 @@ public class EnrichmentFunctionShould { private Function function; private FieldEnrichment fieldEnrichment; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { - this.function = new Function() { - @Nullable - @Override - public ProjectCreated.Enrichment apply(@Nullable ProjectCreated input) { - if (input == null) { - return null; - } - final ProjectCreated.Enrichment result = ProjectCreated.Enrichment.newBuilder() - .setProjectName(input.getProjectId().getId()) - .build(); - return result; + this.function = input -> { + if (input == null) { + return null; } + ProjectCreated.Enrichment.Builder result = ProjectCreated.Enrichment + .newBuilder() + .setProjectName( + input.getProjectId() + .getId()); + return result.build(); }; this.fieldEnrichment = FieldEnrichment.of(ProjectCreated.class, ProjectCreated.Enrichment.class, @@ -73,40 +75,41 @@ public void pass_null_tolerance_check() { .testAllPublicStaticMethods(FieldEnrichment.class); } - @Test(expected = IllegalArgumentException.class) + @Test public void do_not_accept_same_source_and_target_class() { - final Function func = new Function() { - @Nullable + Function func = new Function() { @Override - public StringValue apply(@Nullable StringValue input) { + public @Nullable StringValue apply(@Nullable StringValue input) { return null; } }; + + thrown.expect(IllegalArgumentException.class); FieldEnrichment.of(StringValue.class, StringValue.class, func); } @Test - public void return_sourceClass() throws Exception { + public void return_sourceClass() { assertEquals(ProjectCreated.class, fieldEnrichment.getSourceClass()); } @Test - public void return_targetClass() throws Exception { + public void return_targetClass() { assertEquals(ProjectCreated.Enrichment.class, fieldEnrichment.getEnrichmentClass()); } @Test - public void create_custom_instances() throws Exception { + public void create_custom_instances() { assertEquals(fieldEnrichment, FieldEnrichment.of(ProjectCreated.class, ProjectCreated.Enrichment.class, function)); } @Test - public void apply_enrichment() throws Exception { - final ProjectCreated event = GivenEventMessage.projectCreated(); + public void apply_enrichment() { + ProjectCreated event = GivenEventMessage.projectCreated(); - final ProjectCreated.Enrichment enriched = + ProjectCreated.Enrichment enriched = fieldEnrichment.apply(event, EventContext.getDefaultInstance()); assertNotNull(enriched); @@ -115,12 +118,12 @@ public void apply_enrichment() throws Exception { } @Test - public void have_hashCode() throws Exception { + public void have_hashCode() { assertNotEquals(System.identityHashCode(fieldEnrichment), fieldEnrichment.hashCode()); } @Test - public void have_toString() throws Exception { + public void have_toString() { final String str = fieldEnrichment.toString(); assertTrue(str.contains(ProjectCreated.class.getName())); assertTrue(str.contains(ProjectCreated.Enrichment.class.getName())); @@ -128,11 +131,10 @@ public void have_toString() throws Exception { @Test public void have_smart_equals() { - final FieldEnrichment anotherEnricher = - FieldEnrichment.of( - ProjectCreated.class, - ProjectCreated.Enrichment.class, - function); + FieldEnrichment anotherEnricher = + FieldEnrichment.of(ProjectCreated.class, + ProjectCreated.Enrichment.class, + function); new EqualsTester().addEqualityGroup(fieldEnrichment, anotherEnricher) .testEquals(); } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/ReferenceValidatorShould.java b/server/src/test/java/io/spine/server/outbus/enrich/ReferenceValidatorShould.java index f7d12cb5faf..a9c613192ff 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/ReferenceValidatorShould.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/ReferenceValidatorShould.java @@ -32,7 +32,9 @@ import io.spine.test.event.enrichment.GranterEventsEnrichment; import io.spine.test.event.enrichment.ProjectCreatedEnrichmentAnotherPackage; import io.spine.test.event.user.UserDeletedEvent; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.Iterator; @@ -57,9 +59,12 @@ public class ReferenceValidatorShould { private static final String USER_GOOGLE_UID_FIELD = "user_google_uid"; private final Enricher enricher = Enrichment.newEventEnricher(); + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void initialize_with_valid_enricher() { - final ReferenceValidator validator = + ReferenceValidator validator = new ReferenceValidator(enricher, ProjectCreated.class, ProjectCreatedEnrichmentAnotherPackage.class); @@ -68,96 +73,97 @@ public void initialize_with_valid_enricher() { @Test public void store_valid_map_of_enrichment_fields_after_validation() { - final ReferenceValidator validator + ReferenceValidator validator = new ReferenceValidator(enricher, UserDeletedEvent.class, EnrichmentBoundWithMultipleFieldsWithDifferentNames.class); - final ValidationResult result = validator.validate(); - final Multimap fieldMap = result.getFieldMap(); + ValidationResult result = validator.validate(); + Multimap fieldMap = result.getFieldMap(); assertNotNull(fieldMap); assertFalse(fieldMap.isEmpty()); assertSize(1, fieldMap); - final Iterator>> fieldsIterator = + Iterator>> fieldsIterator = fieldMap.asMap() .entrySet() .iterator(); assertTrue(fieldsIterator.hasNext()); - final Map.Entry> entry = fieldsIterator.next(); + Map.Entry> entry = fieldsIterator.next(); @SuppressWarnings("unchecked") - final Map.Entry> fieldEntry + Map.Entry> fieldEntry = (Map.Entry>) entry; - final FieldDescriptor eventField = fieldEntry.getKey(); - final String eventFieldName = eventField.getName(); + FieldDescriptor eventField = fieldEntry.getKey(); + String eventFieldName = eventField.getName(); assertEquals("deleted_uid", eventFieldName); - final Collection enrichmentFields = fieldEntry.getValue(); + Collection enrichmentFields = fieldEntry.getValue(); assertFalse(enrichmentFields.isEmpty()); assertSize(1, enrichmentFields); - final Iterator enrichmentFieldIterator = enrichmentFields.iterator(); + Iterator enrichmentFieldIterator = enrichmentFields.iterator(); assertTrue(enrichmentFieldIterator.hasNext()); - final FieldDescriptor enrichmentField = enrichmentFieldIterator.next(); - final String enrichmentFieldName = enrichmentField.getName(); + FieldDescriptor enrichmentField = enrichmentFieldIterator.next(); + String enrichmentFieldName = enrichmentField.getName(); assertEquals(USER_GOOGLE_UID_FIELD, enrichmentFieldName); } - @Test(expected = IllegalStateException.class) + @Test public void fail_validation_if_enrichment_is_not_declared() { - final ReferenceValidator validator = new ReferenceValidator(enricher, - UserDeletedEvent.class, - GranterEventsEnrichment.class); + ReferenceValidator validator = new ReferenceValidator(enricher, + UserDeletedEvent.class, + GranterEventsEnrichment.class); + thrown.expect(IllegalStateException.class); validator.validate(); } @Test public void skip_mapping_if_no_mapping_function_is_defined() { - final Enricher mockEnricher = mock(Enricher.class); + Enricher mockEnricher = mock(Enricher.class); when(mockEnricher.functionFor(any(Class.class), any(Class.class))) - .thenReturn(Optional.>absent()); - final ReferenceValidator validator + .thenReturn(Optional.absent()); + ReferenceValidator validator = new ReferenceValidator(mockEnricher, UserDeletedEvent.class, EnrichmentBoundWithMultipleFieldsWithDifferentNames.class); - final ValidationResult result = validator.validate(); - final List> functions = result.getFunctions(); + ValidationResult result = validator.validate(); + List> functions = result.getFunctions(); assertTrue(functions.isEmpty()); - final Multimap fields = result.getFieldMap(); + Multimap fields = result.getFieldMap(); assertEmpty(fields); } @Test public void handle_separator_spaces_in_by_argument() { - final ReferenceValidator validator + ReferenceValidator validator = new ReferenceValidator(enricher, TaskAdded.class, EnrichmentBoundWithFieldsSeparatedWithSpaces.class); - final ValidationResult result = validator.validate(); - final Multimap fieldMap = result.getFieldMap(); + ValidationResult result = validator.validate(); + Multimap fieldMap = result.getFieldMap(); assertFalse(fieldMap.isEmpty()); assertSize(1, fieldMap); - final Iterator>> mapIterator = + Iterator>> mapIterator = fieldMap.asMap() .entrySet() .iterator(); assertTrue(mapIterator.hasNext()); - final Map.Entry> singleEntry = + Map.Entry> singleEntry = mapIterator.next(); - final FieldDescriptor boundField = singleEntry.getKey(); + FieldDescriptor boundField = singleEntry.getKey(); - final String boundFieldName = boundField.getName(); + String boundFieldName = boundField.getName(); assertEquals("project_id", boundFieldName); - final Collection targets = singleEntry.getValue(); + Collection targets = singleEntry.getValue(); assertSize(1, targets); - final FieldDescriptor targetField = targets.iterator() - .next(); - final String targetFieldName = targetField.getName(); + FieldDescriptor targetField = targets.iterator() + .next(); + String targetFieldName = targetField.getName(); assertEquals(USER_GOOGLE_UID_FIELD, targetFieldName); } } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java index d62e096d0ba..c9562692ba9 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/EnricherBuilderTestEnv.java @@ -31,9 +31,7 @@ import io.spine.server.event.EventEnricher; import io.spine.server.outbus.enrich.Enricher; import io.spine.test.event.ProjectId; -import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; - import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -51,24 +49,24 @@ private Enrichment() {} /** Creates a new enricher with all required enrichment functions set. */ public static Enricher newEnricher() { - final EventEnricher.Builder builder = EventEnricher.newBuilder(); - builder.add(ProjectId.class, String.class, new GetProjectName()) - .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) - .add(EventId.class, String.class, EVENT_ID_TO_STRING) - .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) - .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) - .add(Any.class, String.class, ANY_TO_STRING) - .add(Integer.class, String.class, VERSION_TO_STRING) - .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) - .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) - .add(String.class, Integer.class, STRING_TO_INT); + EventEnricher.Builder builder = EventEnricher + .newBuilder() + .add(ProjectId.class, String.class, new GetProjectName()) + .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) + .add(EventId.class, String.class, EVENT_ID_TO_STRING) + .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) + .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) + .add(Any.class, String.class, ANY_TO_STRING) + .add(Integer.class, String.class, VERSION_TO_STRING) + .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) + .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) + .add(String.class, Integer.class, STRING_TO_INT); return builder.build(); } public static class GetProjectName implements Function { - @Nullable @Override - public String apply(@Nullable ProjectId id) { + public @Nullable String apply(@Nullable ProjectId id) { if (id == null) { return null; } @@ -78,9 +76,8 @@ public String apply(@Nullable ProjectId id) { } public static class GetProjectOwnerId implements Function { - @Nullable @Override - public UserId apply(@Nullable ProjectId id) { + public @Nullable UserId apply(@Nullable ProjectId id) { if (id == null) { return null; } @@ -90,76 +87,31 @@ public UserId apply(@Nullable ProjectId id) { private static final Function EVENT_ID_TO_STRING = new Function() { - @Nullable @Override - public String apply(@Nullable EventId input) { + public @Nullable String apply(@Nullable EventId input) { return input == null ? "" : input.getValue(); } }; private static final Function TIMESTAMP_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Timestamp input) { - return input == null ? "" : input.toString(); - } - }; + input -> input == null ? "" : input.toString(); private static final Function CMD_CONTEXT_TO_STRING = - new Function() { - @Override - public String apply(@Nullable CommandContext input) { - return input == null ? "" : input.toString(); - } - }; + input -> input == null ? "" : input.toString(); private static final Function ANY_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Any input) { - return input == null ? "" : input.toString(); - } - }; + input -> input == null ? "" : input.toString(); private static final Function VERSION_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Integer input) { - return input == null ? "" : input.toString(); - } - }; + input -> input == null ? "" : input.toString(); private static final Function STRING_TO_ZONE_OFFSET = - new Function() { - @Nullable - @Override - public ZoneOffset apply(@Nullable String input) { - return input == null - ? ZoneOffset.getDefaultInstance() - : ZoneOffset.newBuilder() - .setId(ZoneId.newBuilder() - .setValue(input)) - .build(); - } - }; + new StringToZoneOffset(); private static final Function STRING_TO_PERSON_NAME = - new Function() { - @Nullable - @Override - public PersonName apply(@Nullable String input) { - return input == null - ? PersonName.getDefaultInstance() - : PersonName.newBuilder().setFamilyName(input).build(); - } - }; + new StringToPersonName(); + + private static final Function STRING_TO_INT = Integer::valueOf; - private static final Function STRING_TO_INT = - new Function() { - @Override - public Integer apply(@Nullable String input) { - return 0; - } - }; } } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java index 85bf3afb521..9986161ec22 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java @@ -31,9 +31,7 @@ import io.spine.server.event.EventEnricher; import io.spine.server.outbus.enrich.Enricher; import io.spine.test.event.ProjectId; -import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; - import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -47,28 +45,55 @@ private EventMessageEnricherTestEnv() { public static class Enrichment { - private Enrichment() {} + private static final Function EVENT_ID_TO_STRING = + new Function() { + @Override + public @Nullable String apply(@Nullable EventId input) { + return input == null ? "" : input.getValue(); + } + }; + private static final Function TIMESTAMP_TO_STRING = + input -> input == null ? "" : input.toString(); + private static final Function CMD_CONTEXT_TO_STRING = + new Function() { + @Override + public String apply(@Nullable CommandContext input) { + return input == null ? "" : input.toString(); + } + }; + private static final Function ANY_TO_STRING = + input -> input == null ? "" : input.toString(); + private static final Function VERSION_TO_STRING = + input -> input == null ? "" : input.toString(); + private static final Function STRING_TO_ZONE_OFFSET = + new StringToZoneOffset(); + private static final Function STRING_TO_PERSON_NAME = + new StringToPersonName(); + private static final Function STRING_TO_INT = Integer::valueOf; + + private Enrichment() { + } /** Creates a new enricher with all required enrichment functions set. */ public static Enricher newEventEnricher() { - final EventEnricher.Builder builder = EventEnricher.newBuilder(); - builder.add(ProjectId.class, String.class, new GetProjectName()) - .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) - .add(EventId.class, String.class, EVENT_ID_TO_STRING) - .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) - .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) - .add(Any.class, String.class, ANY_TO_STRING) - .add(Integer.class, String.class, VERSION_TO_STRING) - .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) - .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) - .add(String.class, Integer.class, STRING_TO_INT); + EventEnricher.Builder builder = EventEnricher + .newBuilder() + .add(ProjectId.class, String.class, new GetProjectName()) + .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) + .add(EventId.class, String.class, EVENT_ID_TO_STRING) + .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) + .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) + .add(Any.class, String.class, ANY_TO_STRING) + .add(Integer.class, String.class, VERSION_TO_STRING) + .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) + .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) + .add(String.class, Integer.class, STRING_TO_INT); return builder.build(); } public static class GetProjectName implements Function { - @Nullable @Override - public String apply(@Nullable ProjectId id) { + public @Nullable String apply(@Nullable ProjectId id) { if (id == null) { return null; } @@ -78,88 +103,13 @@ public String apply(@Nullable ProjectId id) { } public static class GetProjectOwnerId implements Function { - @Nullable @Override - public UserId apply(@Nullable ProjectId id) { + public @Nullable UserId apply(@Nullable ProjectId id) { if (id == null) { return null; } return GivenUserId.of("po-" + id.getId()); } } - - private static final Function EVENT_ID_TO_STRING = - new Function() { - @Nullable - @Override - public String apply(@Nullable EventId input) { - return input == null ? "" : input.getValue(); - } - }; - - private static final Function TIMESTAMP_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Timestamp input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function CMD_CONTEXT_TO_STRING = - new Function() { - @Override - public String apply(@Nullable CommandContext input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function ANY_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Any input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function VERSION_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Integer input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function STRING_TO_ZONE_OFFSET = - new Function() { - @Nullable - @Override - public ZoneOffset apply(@Nullable String input) { - return input == null - ? ZoneOffset.getDefaultInstance() - : ZoneOffset.newBuilder() - .setId(ZoneId.newBuilder() - .setValue(input)) - .build(); - } - }; - - private static final Function STRING_TO_PERSON_NAME = - new Function() { - @Nullable - @Override - public PersonName apply(@Nullable String input) { - return input == null - ? PersonName.getDefaultInstance() - : PersonName.newBuilder().setFamilyName(input).build(); - } - }; - - private static final Function STRING_TO_INT = - new Function() { - @Override - public Integer apply(@Nullable String input) { - return 0; - } - }; } } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java index 506e2ca4c0d..47dcf7d7822 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/ReferenceValidatorTestEnv.java @@ -31,9 +31,7 @@ import io.spine.server.event.EventEnricher; import io.spine.server.outbus.enrich.Enricher; import io.spine.test.event.ProjectId; -import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; - import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -41,34 +39,63 @@ */ public class ReferenceValidatorTestEnv { + /** Prevent instantiation of this utility class. */ private ReferenceValidatorTestEnv() { - // Prevent instantiation of this utility class. } public static class Enrichment { - private Enrichment() {} + private static final Function EVENT_ID_TO_STRING = + new Function() { + @Override + public @Nullable String apply(@Nullable EventId input) { + return input == null ? "" : input.getValue(); + } + }; + + private static final Function TIMESTAMP_TO_STRING = + input -> input == null ? "" : input.toString(); + + private static final Function CMD_CONTEXT_TO_STRING = + input -> input == null ? "" : input.toString(); + + private static final Function ANY_TO_STRING = + input -> input == null ? "" : input.toString(); + + private static final Function VERSION_TO_STRING = + input -> input == null ? "" : input.toString(); + + private static final Function STRING_TO_ZONE_OFFSET = + new StringToZoneOffset(); + + private static final Function STRING_TO_PERSON_NAME = + new StringToPersonName(); + + private static final Function STRING_TO_INT = Integer::valueOf; + + private Enrichment() { + } /** Creates a new enricher with all required enrichment functions set. */ public static Enricher newEventEnricher() { - final EventEnricher.Builder builder = EventEnricher.newBuilder(); - builder.add(ProjectId.class, String.class, new GetProjectName()) - .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) - .add(EventId.class, String.class, EVENT_ID_TO_STRING) - .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) - .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) - .add(Any.class, String.class, ANY_TO_STRING) - .add(Integer.class, String.class, VERSION_TO_STRING) - .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) - .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) - .add(String.class, Integer.class, STRING_TO_INT); + EventEnricher.Builder builder = EventEnricher + .newBuilder() + .add(ProjectId.class, String.class, new GetProjectName()) + .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) + .add(EventId.class, String.class, EVENT_ID_TO_STRING) + .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) + .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) + .add(Any.class, String.class, ANY_TO_STRING) + .add(Integer.class, String.class, VERSION_TO_STRING) + .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) + .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) + .add(String.class, Integer.class, STRING_TO_INT); return builder.build(); } public static class GetProjectName implements Function { - @Nullable @Override - public String apply(@Nullable ProjectId id) { + public @Nullable String apply(@Nullable ProjectId id) { if (id == null) { return null; } @@ -78,88 +105,13 @@ public String apply(@Nullable ProjectId id) { } public static class GetProjectOwnerId implements Function { - @Nullable @Override - public UserId apply(@Nullable ProjectId id) { + public @Nullable UserId apply(@Nullable ProjectId id) { if (id == null) { return null; } return GivenUserId.of("prj-owner-" + id.getId()); } } - - private static final Function EVENT_ID_TO_STRING = - new Function() { - @Nullable - @Override - public String apply(@Nullable EventId input) { - return input == null ? "" : input.getValue(); - } - }; - - private static final Function TIMESTAMP_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Timestamp input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function CMD_CONTEXT_TO_STRING = - new Function() { - @Override - public String apply(@Nullable CommandContext input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function ANY_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Any input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function VERSION_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Integer input) { - return input == null ? "" : input.toString(); - } - }; - - private static final Function STRING_TO_ZONE_OFFSET = - new Function() { - @Nullable - @Override - public ZoneOffset apply(@Nullable String input) { - return input == null - ? ZoneOffset.getDefaultInstance() - : ZoneOffset.newBuilder() - .setId(ZoneId.newBuilder() - .setValue(input)) - .build(); - } - }; - - private static final Function STRING_TO_PERSON_NAME = - new Function() { - @Nullable - @Override - public PersonName apply(@Nullable String input) { - return input == null - ? PersonName.getDefaultInstance() - : PersonName.newBuilder().setFamilyName(input).build(); - } - }; - - private static final Function STRING_TO_INT = - new Function() { - @Override - public Integer apply(@Nullable String input) { - return 0; - } - }; } } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/StringToPersonName.java b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToPersonName.java new file mode 100644 index 00000000000..3c623ad290d --- /dev/null +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToPersonName.java @@ -0,0 +1,70 @@ +/* + * Copyright 2018, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.outbus.enrich.given; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import io.spine.people.PersonName; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; + +/** + * Converts a string into a {@link PersonName} instance. + * + *

Uses the simplest approach for setting a person name by concatenating + * strings starting from the second. + * + *

Production code should analyze the content of the names and set + * corresponding fields of the {@code PersonName}. + * + * @author Alexander Yevsyukov + */ +public class StringToPersonName implements Function { + + private static final Splitter SPLITTER = Splitter.on(' '); + private static final Joiner JOINER = Joiner.on(' '); + + @Override + public @Nullable PersonName apply(@Nullable String input) { + if (input == null) { + return PersonName.getDefaultInstance(); + } + List names = newArrayList(SPLITTER.split(input)); + PersonName.Builder builder = PersonName + .newBuilder() + .setGivenName(names.get(0)); + addOtherNames(builder, names); + return builder.build(); + } + + @SuppressWarnings("CheckReturnValue") // calling builders + private static void addOtherNames(PersonName.Builder builder, List names) { + if (names.size() > 1) { + List otherNames = names.subList(1, names.size() - 1); + String joined = JOINER.join(otherNames); + builder.setFamilyName(joined); + } + } +} diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java new file mode 100644 index 00000000000..57f72616c48 --- /dev/null +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java @@ -0,0 +1,45 @@ +/* + * Copyright 2018, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.outbus.enrich.given; + +import com.google.common.base.Function; +import io.spine.time.ZoneId; +import io.spine.time.ZoneOffset; +import org.checkerframework.checker.nullness.qual.Nullable; + +/** + * Naïve implementation of string to ZoneOffset conversion for the enrichment tests purposes. + * + *

Production code should perform validation. + * + * @author Alexander Yevsyukov + */ +class StringToZoneOffset implements Function { + @Override + public @Nullable ZoneOffset apply(@Nullable String input) { + return input == null + ? ZoneOffset.getDefaultInstance() + : ZoneOffset.newBuilder() + .setId(ZoneId.newBuilder() + .setValue(input)) + .build(); + } +} diff --git a/server/src/test/java/io/spine/server/storage/AbstractStorageShould.java b/server/src/test/java/io/spine/server/storage/AbstractStorageShould.java index 652ae2e94d1..78916d26b83 100644 --- a/server/src/test/java/io/spine/server/storage/AbstractStorageShould.java +++ b/server/src/test/java/io/spine/server/storage/AbstractStorageShould.java @@ -21,13 +21,15 @@ package io.spine.server.storage; import com.google.common.base.Optional; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.server.entity.Entity; import io.spine.test.Tests; -import io.spine.test.Verify; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Collection; import java.util.HashSet; @@ -35,6 +37,7 @@ import java.util.Set; import static com.google.common.collect.Sets.newHashSet; +import static io.spine.test.Verify.assertContainsAll; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -67,6 +70,9 @@ public abstract class AbstractStorageShould storage) { /** Writes a record, reads it and asserts it is the same as the expected one. */ @SuppressWarnings("OptionalGetWithoutIsPresent") // We do check. protected void writeAndReadRecordTest(I id) { - final M expected = writeRecord(id); + M expected = writeRecord(id); - final R readRequest = newReadRequest(id); - final Optional actual = storage.read(readRequest); + R readRequest = newReadRequest(id); + Optional actual = storage.read(readRequest); assertTrue(actual.isPresent()); assertEquals(expected, actual.get()); } + @CanIgnoreReturnValue private M writeRecord(I id) { - final M expected = newStorageRecord(); + M expected = newStorageRecord(); storage.write(id, expected); return expected; } @Test public void handle_absence_of_record_with_passed_id() { - final R readRequest = newReadRequest(newId()); - final Optional record = storage.read(readRequest); + R readRequest = newReadRequest(newId()); + Optional record = storage.read(readRequest); assertResultForMissingId(record); } @@ -167,19 +174,22 @@ protected void assertResultForMissingId(Optional record) { assertFalse(record.isPresent()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_read_by_null_id() { - storage.read(Tests.nullRef()); + thrown.expect(NullPointerException.class); + storage.read(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_write_by_null_id() { - storage.write(Tests.nullRef(), newStorageRecord()); + thrown.expect(NullPointerException.class); + storage.write(Tests.nullRef(), newStorageRecord()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_write_null_record() { - storage.write(newId(), Tests.nullRef()); + thrown.expect(NullPointerException.class); + storage.write(newId(), Tests.nullRef()); } @Test @@ -196,38 +206,38 @@ public void write_and_read_several_records_by_different_ids() { @Test public void rewrite_record_if_write_by_the_same_id() { - final I id = newId(); + I id = newId(); writeAndReadRecordTest(id); writeAndReadRecordTest(id); } @Test public void have_index_on_ID() { - final Iterator index = storage.index(); + Iterator index = storage.index(); assertNotNull(index); } @Test public void index_all_IDs() { - final int recordCount = 10; - final Set ids = new HashSet<>(recordCount); + int recordCount = 10; + Set ids = new HashSet<>(recordCount); for (int i = 0; i < recordCount; i++) { - final I id = newId(); + I id = newId(); writeRecord(id); ids.add(id); } - final Iterator index = storage.index(); - final Collection indexValues = newHashSet(index); + Iterator index = storage.index(); + Collection indexValues = newHashSet(index); assertEquals(ids.size(), indexValues.size()); - Verify.assertContainsAll(indexValues, (I[]) ids.toArray()); + assertContainsAll(indexValues, (I[]) ids.toArray()); } @Test public void have_immutable_index() { writeRecord(newId()); - final Iterator index = storage.index(); + Iterator index = storage.index(); assertTrue(index.hasNext()); try { index.remove(); @@ -240,10 +250,11 @@ public void have_immutable_index() { } } - @Test(expected = IllegalStateException.class) - public void assure_it_is_closed() throws Exception { + @Test + public void assure_it_is_closed() { closeAndFailIfException(storage); + thrown.expect(IllegalStateException.class); storage.checkNotClosed(); } @@ -258,42 +269,45 @@ public void return_true_if_it_is_opened() { } @Test - public void return_false_if_it_not_opened() throws Exception { + public void return_false_if_it_not_opened() { storage.close(); assertFalse(storage.isOpen()); } @Test - public void return_true_if_it_is_closed() throws Exception { + public void return_true_if_it_is_closed() { storage.close(); assertTrue(storage.isClosed()); } @Test - public void return_false_if_it_not_closed() throws Exception { + public void return_false_if_it_not_closed() { assertFalse(storage.isClosed()); } - @Test(expected = IllegalStateException.class) - public void close_itself_and_throw_exception_if_read_after() throws Exception { + @Test + public void close_itself_and_throw_exception_if_read_after() { closeAndFailIfException(storage); - final R readRequest = newReadRequest(newId()); + R readRequest = newReadRequest(newId()); + thrown.expect(IllegalStateException.class); storage.read(readRequest); } - @Test(expected = IllegalStateException.class) - public void close_itself_and_throw_exception_if_write_after() throws Exception { + @Test + public void close_itself_and_throw_exception_if_write_after() { closeAndFailIfException(storage); + thrown.expect(IllegalStateException.class); storage.write(newId(), newStorageRecord()); } - @Test(expected = IllegalStateException.class) - public void throw_exception_if_close_twice() throws Exception { + @Test + public void throw_exception_if_close_twice() { storage.close(); + thrown.expect(IllegalStateException.class); storage.close(); } @@ -301,10 +315,10 @@ public void throw_exception_if_close_twice() throws Exception { checking via #contains(Object). */) @Test public void return_unique_ID() { - final int checkCount = 10; - final Set ids = newHashSet(); + int checkCount = 10; + Set ids = newHashSet(); for (int i = 0; i < checkCount; i++) { - final I newId = newId(); + I newId = newId(); if (ids.contains(newId)) { fail("AbstractStorageShould.newId() should return unique IDs."); } diff --git a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateMessageDispatcher.java b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateMessageDispatcher.java index ac62aee4cf5..fb8c6fd7f41 100644 --- a/testutil-server/src/main/java/io/spine/server/aggregate/AggregateMessageDispatcher.java +++ b/testutil-server/src/main/java/io/spine/server/aggregate/AggregateMessageDispatcher.java @@ -20,6 +20,7 @@ package io.spine.server.aggregate; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Message; import io.spine.core.CommandEnvelope; import io.spine.core.EventEnvelope; @@ -39,7 +40,8 @@ public class AggregateMessageDispatcher { /** Prevents instantiation of this utility class. */ - private AggregateMessageDispatcher() {} + private AggregateMessageDispatcher() { + } /** * Dispatches the {@linkplain CommandEnvelope command envelope} and applies the resulting events @@ -47,10 +49,11 @@ private AggregateMessageDispatcher() {} * * @return the list of event messages. */ + @CanIgnoreReturnValue public static List dispatchCommand(Aggregate aggregate, CommandEnvelope envelope) { checkNotNull(envelope); - final List eventMessages = aggregate.dispatchCommand(envelope); + List eventMessages = aggregate.dispatchCommand(envelope); apply(aggregate, eventMessages, envelope); return eventMessages; } @@ -61,10 +64,11 @@ public static List dispatchCommand(Aggregate aggrega * * @return the list of event messages. */ + @CanIgnoreReturnValue public static List dispatchEvent(Aggregate aggregate, EventEnvelope envelope) { checkNotNull(envelope); - final List eventMessages = aggregate.reactOn(envelope); + List eventMessages = aggregate.reactOn(envelope); apply(aggregate, eventMessages, envelope); return eventMessages; } @@ -75,11 +79,12 @@ public static List dispatchEvent(Aggregate aggregate * * @return the list of event messages. */ + @CanIgnoreReturnValue public static List dispatchRejection(Aggregate aggregate, RejectionEnvelope envelope) { checkNotNull(envelope); - final List eventMessages = aggregate.reactOn(envelope); + List eventMessages = aggregate.reactOn(envelope); apply(aggregate, eventMessages, envelope); return eventMessages; } @@ -87,7 +92,7 @@ public static List dispatchRejection(Aggregate aggre private static void apply(Aggregate aggregate, List eventMessages, MessageEnvelope envelope) { - final AggregateTransaction tx = AggregateTransaction.start(aggregate); + AggregateTransaction tx = AggregateTransaction.start(aggregate); aggregate.apply(eventMessages, envelope); tx.commit(); } diff --git a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java index 1bace40ac2d..541c4da019a 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java +++ b/testutil-server/src/main/java/io/spine/server/entity/EntityBuilder.java @@ -28,8 +28,8 @@ import io.spine.core.Version; import io.spine.core.Versions; import io.spine.test.ReflectiveBuilder; - import org.checkerframework.checker.nullness.qual.Nullable; + import java.lang.reflect.Constructor; import static com.google.common.base.Preconditions.checkNotNull; @@ -123,12 +123,12 @@ private I createDefaultId() { @Override public E build() { - final I id = id(); - final E result = createEntity(id); - final S state = state(result); - final Timestamp timestamp = timestamp(); + I id = id(); + E result = createEntity(id); + S state = state(result); + Timestamp timestamp = timestamp(); - final Version version = Versions.newVersion(this.version, timestamp); + Version version = Versions.newVersion(this.version, timestamp); setState(result, state, version); return result; } @@ -166,7 +166,7 @@ protected Timestamp timestamp() { @Override protected Constructor getConstructor() { - final Constructor constructor = entityClass().getConstructor(); + Constructor constructor = entityClass().getConstructor(); constructor.setAccessible(true); return constructor; } @@ -175,7 +175,7 @@ protected Constructor getConstructor() { * Creates an empty entity instance. */ protected E createEntity(I id) { - final E result = entityClass().createEntity(id); + E result = entityClass().createEntity(id); return result; } } diff --git a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java index eeec0aa2fbf..fd44e37d13d 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java +++ b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java @@ -53,7 +53,7 @@ private Given() { public static , I, S extends Message> EntityBuilder entityOfClass(Class entityClass) { checkNotNull(entityClass); - final EntityBuilder result = new EntityBuilder<>(); + EntityBuilder result = new EntityBuilder<>(); result.setResultClass(entityClass); return result; } @@ -62,9 +62,9 @@ EntityBuilder entityOfClass(Class entityClass) { * Creates dynamic builder for building an {@code Aggregate}. */ public static , I, S extends Message> - AggregateBuilder aggregateOfClass(Class aggregateClass) { + AggregateBuilder aggregateOfClass(Class aggregateClass) { checkNotNull(aggregateClass); - final AggregateBuilder result = new AggregateBuilder<>(); + AggregateBuilder result = new AggregateBuilder<>(); result.setResultClass(aggregateClass); return result; } @@ -72,13 +72,15 @@ AggregateBuilder aggregateOfClass(Class aggregateClass) { /** * Creates a builder for an {@code AggregatePart}. */ - public static , - I, - S extends Message, - R extends AggregateRoot> + public static < + A extends AggregatePart, + I, + S extends Message, + R extends AggregateRoot + > AggregatePartBuilder aggregatePartOfClass(Class partClass) { checkNotNull(partClass); - final AggregatePartBuilder result = new AggregatePartBuilder<>(); + AggregatePartBuilder result = new AggregatePartBuilder<>(); result.setResultClass(partClass); return result; } @@ -86,13 +88,15 @@ AggregatePartBuilder aggregatePartOfClass(Class partClass) { /** * Creates a builder for a {@code Projection}. */ - public static

, + public static < + P extends Projection, I, S extends Message, - B extends ValidatingBuilder> + B extends ValidatingBuilder + > ProjectionBuilder projectionOfClass(Class

projectionClass) { checkNotNull(projectionClass); - final ProjectionBuilder result = new ProjectionBuilder<>(); + ProjectionBuilder result = new ProjectionBuilder<>(); result.setResultClass(projectionClass); return result; } @@ -100,11 +104,15 @@ ProjectionBuilder projectionOfClass(Class

projectionClass) { /** * Creates a builder for a {@code ProcessManager}. */ - public static -

, I, S extends Message, B extends ValidatingBuilder> - ProcessManagerBuilder processManagerOfClass(Class

pmClass) { + public static < + P extends ProcessManager, + I, + S extends Message, + B extends ValidatingBuilder + > + ProcessManagerBuilder processManagerOfClass(Class

pmClass) { checkNotNull(pmClass); - final ProcessManagerBuilder result = new ProcessManagerBuilder<>(); + ProcessManagerBuilder result = new ProcessManagerBuilder<>(); result.setResultClass(pmClass); return result; } From 86c9ae0e502d2dcb7598ecb7e876ddc5b9da455c Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 01:19:36 +0300 Subject: [PATCH 13/53] Handle ignored return values --- .idea/codeStyles/Project.xml | 7 +- .../io/spine/client/ActorRequestFactory.java | 30 +- .../spine/server/delivery/ShardedStream.java | 6 + .../io/spine/server/entity/EntityClass.java | 19 +- .../io/spine/server/entity/Transaction.java | 3 +- .../server/model/DefaultStateRegistry.java | 37 +- .../java/io/spine/server/model/Model.java | 20 +- .../server/procman/AbstractCommandRouter.java | 1 + .../DelegatingRejectionDispatcher.java | 14 +- .../server/storage/StorageFactorySwitch.java | 12 +- .../src/test/java/io/spine/server/Given.java | 106 +-- .../aggregate/AggregateTransactionShould.java | 1 - .../command/CommandHandlerMethodShould.java | 73 +- .../CommandDispatcherRegistryTestEnv.java | 5 +- .../server/commandstore/StorageShould.java | 48 +- .../delivery/ShardedStreamBuilderShould.java | 44 +- .../delivery/UniformAcrossTargetsShould.java | 11 +- .../delivery/given/ShardedStreamTestEnv.java | 74 +- .../io/spine/server/event/EventBusShould.java | 226 +++--- .../event/given/EventEnricherTestEnv.java | 134 ++-- .../model/DefaultStateRegistryShould.java | 87 +-- .../server/model/HandlerMethodShould.java | 89 ++- .../io/spine/server/model/ModelShould.java | 6 +- .../enrich/given/StringToZoneOffset.java | 2 +- .../procman/AbstractCommandRouterShould.java | 17 +- .../procman/CommandRouterOnErrorShould.java | 20 +- .../ProcessManagerRepositoryShould.java | 152 ++-- .../server/procman/ProcessManagerShould.java | 165 +++-- .../procman/given/PmTransactionTestEnv.java | 14 +- .../projection/ProjectionStorageShould.java | 170 ++--- .../io/spine/server/reflect/FieldShould.java | 38 +- .../DelegatingRejectionDispatcherShould.java | 7 +- .../rejection/RejectionEnricherShould.java | 31 +- .../RejectionReactorMethodShould.java | 43 +- .../RejectionSubscriberMethodShould.java | 61 +- .../server/stand/MultiTenantStandShould.java | 50 +- .../spine/server/stand/StandPostShould.java | 264 ++++--- .../io/spine/server/stand/StandShould.java | 9 +- .../storage/OperatorEvaluatorShould.java | 76 +- .../server/storage/RecordStorageShould.java | 697 +++++++++--------- .../storage/StorageFactorySwitchShould.java | 93 +-- 41 files changed, 1500 insertions(+), 1462 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 48c2acd8f6d..fafa9ba0439 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -2,12 +2,14 @@ - + \ No newline at end of file diff --git a/client/src/main/java/io/spine/client/ActorRequestFactory.java b/client/src/main/java/io/spine/client/ActorRequestFactory.java index d1969e843b7..b238c3277a6 100644 --- a/client/src/main/java/io/spine/client/ActorRequestFactory.java +++ b/client/src/main/java/io/spine/client/ActorRequestFactory.java @@ -27,7 +27,6 @@ import io.spine.core.UserId; import io.spine.time.ZoneOffset; import io.spine.time.ZoneOffsets; - import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -53,8 +52,7 @@ public class ActorRequestFactory { * *

This field is null in a single tenant application. */ - @Nullable - private final TenantId tenantId; + private final @Nullable TenantId tenantId; protected ActorRequestFactory(Builder builder) { this.actor = builder.actor; @@ -74,8 +72,7 @@ public ZoneOffset getZoneOffset() { return zoneOffset; } - @Nullable - public TenantId getTenantId() { + public @Nullable TenantId getTenantId() { return tenantId; } @@ -140,11 +137,11 @@ protected CommandContext createCommandContext() { */ @SuppressWarnings("CheckReturnValue") // calling builder ActorContext actorContext() { - ActorContext.Builder builder = - ActorContext.newBuilder() - .setActor(actor) - .setTimestamp(getCurrentTime()) - .setZoneOffset(zoneOffset); + ActorContext.Builder builder = ActorContext + .newBuilder() + .setActor(actor) + .setTimestamp(getCurrentTime()) + .setZoneOffset(zoneOffset); if (tenantId != null) { builder.setTenantId(tenantId); } @@ -160,8 +157,7 @@ public static class Builder { private ZoneOffset zoneOffset; - @Nullable - private TenantId tenantId; + private @Nullable TenantId tenantId; public UserId getActor() { return actor; @@ -172,13 +168,13 @@ public UserId getActor() { * * @param actor the ID of the user generating commands */ + @CanIgnoreReturnValue public Builder setActor(UserId actor) { this.actor = checkNotNull(actor); return this; } - @Nullable - public ZoneOffset getZoneOffset() { + public @Nullable ZoneOffset getZoneOffset() { return zoneOffset; } @@ -187,13 +183,13 @@ public ZoneOffset getZoneOffset() { * * @param zoneOffset the offset of the timezone the user works in */ + @CanIgnoreReturnValue public Builder setZoneOffset(ZoneOffset zoneOffset) { this.zoneOffset = checkNotNull(zoneOffset); return this; } - @Nullable - public TenantId getTenantId() { + public @Nullable TenantId getTenantId() { return tenantId; } @@ -202,6 +198,7 @@ public TenantId getTenantId() { * * @param tenantId the ID of the tenant or null for single-tenant applications */ + @CanIgnoreReturnValue public Builder setTenantId(@Nullable TenantId tenantId) { this.tenantId = tenantId; return this; @@ -214,7 +211,6 @@ public Builder setTenantId(@Nullable TenantId tenantId) { * * @return {@code null} */ - @SuppressWarnings("CheckReturnValue") // calling builder @CanIgnoreReturnValue public ActorRequestFactory build() { checkNotNull(actor, "`actor` must be defined"); diff --git a/server/src/main/java/io/spine/server/delivery/ShardedStream.java b/server/src/main/java/io/spine/server/delivery/ShardedStream.java index 6f13bc0b9ae..d42885704fb 100644 --- a/server/src/main/java/io/spine/server/delivery/ShardedStream.java +++ b/server/src/main/java/io/spine/server/delivery/ShardedStream.java @@ -20,6 +20,7 @@ package io.spine.server.delivery; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.Message; import com.google.protobuf.StringValue; @@ -372,6 +373,7 @@ public BoundedContextName getBoundedContextName() { return boundedContextName; } + @CanIgnoreReturnValue public B setBoundedContextName(BoundedContextName boundedContextName) { checkNotNull(boundedContextName); this.boundedContextName = boundedContextName; @@ -382,6 +384,7 @@ public ShardingKey getKey() { return key; } + @CanIgnoreReturnValue public B setKey(ShardingKey key) { checkNotNull(key); this.key = key; @@ -392,12 +395,14 @@ public DeliveryTag getTag() { return tag; } + @CanIgnoreReturnValue public B setTag(DeliveryTag tag) { checkNotNull(tag); this.tag = tag; return thisAsB(); } + @CanIgnoreReturnValue public B setTargetIdClass(Class targetIdClass) { checkNotNull(targetIdClass); this.targetIdClass = targetIdClass; @@ -408,6 +413,7 @@ public Class getTargetIdClass() { return targetIdClass; } + @CanIgnoreReturnValue public B setConsumer(ShardedStreamConsumer consumer) { checkNotNull(consumer); this.consumer = consumer; diff --git a/server/src/main/java/io/spine/server/entity/EntityClass.java b/server/src/main/java/io/spine/server/entity/EntityClass.java index b5313fac461..4a46411532a 100644 --- a/server/src/main/java/io/spine/server/entity/EntityClass.java +++ b/server/src/main/java/io/spine/server/entity/EntityClass.java @@ -23,6 +23,7 @@ import com.google.protobuf.Message; import io.spine.annotation.Internal; import io.spine.base.Identifier; +import io.spine.protobuf.Messages; import io.spine.server.model.ModelClass; import io.spine.server.model.ModelError; import io.spine.type.TypeUrl; @@ -56,8 +57,7 @@ public class EntityClass extends ModelClass { /** The constructor for entities of this class. */ @SuppressWarnings("TransientFieldNotInitialized") // Lazily initialized via accessor method. - @Nullable - private transient Constructor entityConstructor; + private transient @Nullable Constructor entityConstructor; /** Creates new instance of the model class for the passed class of entities. */ public EntityClass(Class cls) { @@ -104,13 +104,24 @@ private static ModelError noSuchConstructor(String entityClass, String idClass) * public API. It is used internally by other framework routines and not designed for efficient * execution by Spine users. */ - @Internal - public static Class getStateClass(Class entityClass) { + private static Class getStateClass(Class entityClass) { @SuppressWarnings("unchecked") // The type is preserved by the Entity type declaration. final Class result = (Class) Entity.GenericParameter.STATE.getArgumentIn(entityClass); return result; } + /** + * Creates default state by entity class. + * + * @return default state + */ + @Internal + public static Message createDefaultState(Class entityClass) { + Class stateClass = getStateClass(entityClass); + Message result = Messages.newInstance(stateClass); + return result; + } + /** * Obtains constructor for the entities of this class. */ diff --git a/server/src/main/java/io/spine/server/entity/Transaction.java b/server/src/main/java/io/spine/server/entity/Transaction.java index ff2fb3aa74a..9d3532122f6 100644 --- a/server/src/main/java/io/spine/server/entity/Transaction.java +++ b/server/src/main/java/io/spine/server/entity/Transaction.java @@ -362,9 +362,8 @@ private void commitAttributeChanges() { entity.updateStateChanged(); } - @SuppressWarnings("CheckReturnValue") // calling builder method void initAll(S state, Version version) { - final B builder = getBuilder(); + B builder = getBuilder(); builder.clear(); builder.mergeFrom(state); initVersion(version); diff --git a/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java b/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java index ba1dd4447dd..9b972554731 100644 --- a/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java +++ b/server/src/main/java/io/spine/server/model/DefaultStateRegistry.java @@ -21,7 +21,6 @@ package io.spine.server.model; import com.google.protobuf.Message; -import io.spine.protobuf.Messages; import io.spine.server.entity.Entity; import io.spine.server.entity.EntityClass; @@ -63,7 +62,7 @@ class DefaultStateRegistry { boolean contains(Class entityClass) { lock.readLock().lock(); try { - final boolean result = defaultStates.containsKey(entityClass); + boolean result = defaultStates.containsKey(entityClass); return result; } finally { lock.readLock().unlock(); @@ -71,19 +70,21 @@ boolean contains(Class entityClass) { } /** - * If {@link #defaultStates} does not contain state then save state and return it otherwise - * return saved state. + * Obtains the default state message for the passed entity class. + * + *

If the entity class was not registered before, its default state message is + * remembered. Otherwise, the previously stored message is returned. * * @param entityClass an entity class */ - Message putOrGet(Class entityClass) { + Message get(Class entityClass) { lock.writeLock().lock(); try { if (!contains(entityClass)) { - final Message defaultState = createDefaultState(entityClass); + Message defaultState = EntityClass.createDefaultState(entityClass); defaultStates.put(entityClass, defaultState); } - final Message result = get(entityClass); + Message result = doGet(entityClass); return result; } finally { lock.writeLock().unlock(); @@ -95,34 +96,16 @@ Message putOrGet(Class entityClass) { * * @param entityClass an entity class */ - Message get(Class entityClass) { + private Message doGet(Class entityClass) { lock.readLock().lock(); try { - final Message state = defaultStates.get(entityClass); + Message state = defaultStates.get(entityClass); return state; } finally { lock.readLock().unlock(); } } - /** - * Creates default state by entity class. - * - * @return default state - */ - private Message createDefaultState(Class entityClass) { - final Class stateClass = getStateClass(entityClass); - final Message result = Messages.newInstance(stateClass); - return result; - } - - /** - * Obtains the class of the entity state. - */ - private Class getStateClass(Class entityClass) { - return EntityClass.getStateClass(entityClass); - } - static DefaultStateRegistry getInstance() { return Singleton.INSTANCE.value; } diff --git a/server/src/main/java/io/spine/server/model/Model.java b/server/src/main/java/io/spine/server/model/Model.java index 0b2bda4c3df..bf34749e589 100644 --- a/server/src/main/java/io/spine/server/model/Model.java +++ b/server/src/main/java/io/spine/server/model/Model.java @@ -70,7 +70,8 @@ public static Model getInstance() { } /** Prevent instantiation from outside. */ - private Model() {} + private Model() { + } @VisibleForTesting void clear() { @@ -213,15 +214,14 @@ RejectionSubscriberClass asRejectionSubscriber(Class candidateCommands = candidate.getCommands(); - final ImmutableMap.Builder, CommandHandlingClass> map = - ImmutableMap.builder(); + Set candidateCommands = candidate.getCommands(); + ImmutableMap.Builder, CommandHandlingClass> map = ImmutableMap.builder(); for (ModelClass modelClass : classes.values()) { if (modelClass instanceof CommandHandlingClass) { - final CommandHandlingClass commandHandler = (CommandHandlingClass) modelClass; - final Set commandClasses = commandHandler.getCommands(); - final Sets.SetView intersection = + CommandHandlingClass commandHandler = (CommandHandlingClass) modelClass; + Set commandClasses = commandHandler.getCommands(); + Sets.SetView intersection = Sets.intersection(commandClasses, candidateCommands); if (intersection.size() > 0) { map.put(intersection, commandHandler); @@ -229,7 +229,7 @@ private void checkDuplicates(CommandHandlingClass candidate) } } - final ImmutableMap, CommandHandlingClass> currentHandlers = map.build(); + ImmutableMap, CommandHandlingClass> currentHandlers = map.build(); if (!currentHandlers.isEmpty()) { throw new DuplicateCommandHandlerError(candidate, currentHandlers); } @@ -258,8 +258,8 @@ public EntityClass asEntityClass(Class cls) { */ public Message getDefaultState(Class cls) { checkNotNull(cls); - final DefaultStateRegistry registry = DefaultStateRegistry.getInstance(); - final Message result = registry.putOrGet(cls); + DefaultStateRegistry registry = DefaultStateRegistry.getInstance(); + Message result = registry.get(cls); return result; } diff --git a/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java b/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java index b92f0c730f2..a34af515b04 100644 --- a/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java +++ b/server/src/main/java/io/spine/server/procman/AbstractCommandRouter.java @@ -106,6 +106,7 @@ public T add(Message commandMessage) { /** * Adds all command messages from the passed iterable. */ + @CanIgnoreReturnValue protected T addAll(Iterable iterable) { for (Message message : iterable) { add(message); diff --git a/server/src/main/java/io/spine/server/rejection/DelegatingRejectionDispatcher.java b/server/src/main/java/io/spine/server/rejection/DelegatingRejectionDispatcher.java index b3f2bb85179..a2ffda35f86 100644 --- a/server/src/main/java/io/spine/server/rejection/DelegatingRejectionDispatcher.java +++ b/server/src/main/java/io/spine/server/rejection/DelegatingRejectionDispatcher.java @@ -108,23 +108,23 @@ public ExternalMessageDispatcher getExternalDispatcher() { return new ExternalMessageDispatcher() { @Override public Set getMessageClasses() { - final Set rejectionClasses = delegate.getExternalRejectionClasses(); + Set rejectionClasses = delegate.getExternalRejectionClasses(); return ExternalMessageClass.fromRejectionClasses(rejectionClasses); } @Override public Set dispatch(ExternalMessageEnvelope envelope) { - final ExternalMessage externalMessage = envelope.getOuterObject(); - final Rejection rejection = unpack(externalMessage.getOriginalMessage()); - final Set ids = delegate.dispatchRejection(RejectionEnvelope.of(rejection)); + ExternalMessage externalMessage = envelope.getOuterObject(); + Rejection rejection = unpack(externalMessage.getOriginalMessage()); + Set ids = delegate.dispatchRejection(RejectionEnvelope.of(rejection)); return ids; } @Override public void onError(ExternalMessageEnvelope envelope, RuntimeException exception) { - final MessageClass messageClass = envelope.getMessageClass(); - final String messageId = Stringifiers.toString(envelope.getId()); - final String errorMessage = + MessageClass messageClass = envelope.getMessageClass(); + String messageId = Stringifiers.toString(envelope.getId()); + String errorMessage = format("Error dispatching external rejection (class: %s, id: %s)", messageClass, messageId); log().error(errorMessage, exception); diff --git a/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java b/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java index 755abd37ec4..866f82ffac4 100644 --- a/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java +++ b/server/src/main/java/io/spine/server/storage/StorageFactorySwitch.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.base.Supplier; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.spine.base.Environment; import io.spine.core.BoundedContextName; import io.spine.server.storage.memory.InMemoryStorageFactory; @@ -57,15 +58,12 @@ public final class StorageFactorySwitch implements Supplier { /** The name of the BoundedContext where this switch works. */ private final BoundedContextName boundedContextName; - @Nullable - private Supplier productionSupplier; + private @Nullable Supplier productionSupplier; - @Nullable - private Supplier testsSupplier; + private @Nullable Supplier testsSupplier; /** Cached instance of the StorageFactory supplied by one of the suppliers. */ - @Nullable - private StorageFactory storageFactory; + private @Nullable StorageFactory storageFactory; private final boolean multitenant; @@ -89,12 +87,12 @@ public static StorageFactorySwitch newInstance(BoundedContextName boundedContext /** * Initializes the current singleton instance with the suppliers. * - * * @param productionSupplier the supplier for the production mode * @param testsSupplier the supplier for the tests mode. * If {@code null} is passed {@link InMemoryStorageFactory} will be used * @return this */ + @CanIgnoreReturnValue public StorageFactorySwitch init(Supplier productionSupplier, @Nullable Supplier testsSupplier) { this.productionSupplier = checkNotNull(productionSupplier); diff --git a/server/src/test/java/io/spine/server/Given.java b/server/src/test/java/io/spine/server/Given.java index 87aea93ae6a..2f7457c2fb8 100644 --- a/server/src/test/java/io/spine/server/Given.java +++ b/server/src/test/java/io/spine/server/Given.java @@ -67,13 +67,6 @@ public class Given { private Given() { } - static ProjectId newProjectId() { - final String uuid = newUuid(); - return ProjectId.newBuilder() - .setId(uuid) - .build(); - } - static class EventMessage { private EventMessage() { @@ -81,20 +74,20 @@ private EventMessage() { static AggTaskAdded taskAdded(ProjectId id) { return AggTaskAdded.newBuilder() - .setProjectId(id) - .build(); + .setProjectId(id) + .build(); } static AggProjectCreated projectCreated(ProjectId id) { return AggProjectCreated.newBuilder() - .setProjectId(id) - .build(); + .setProjectId(id) + .build(); } static AggProjectStarted projectStarted(ProjectId id) { return AggProjectStarted.newBuilder() - .setProjectId(id) - .build(); + .setProjectId(id) + .build(); } } @@ -105,8 +98,8 @@ private CommandMessage() { public static AggCreateProject createProject(ProjectId id) { return AggCreateProject.newBuilder() - .setProjectId(id) - .build(); + .setProjectId(id) + .build(); } } @@ -127,12 +120,12 @@ private ACommand() { * timestamp using default {@link ACommand} instance. */ private static Command create(Message command, UserId userId, Timestamp when) { - final TenantId generatedTenantId = TenantId.newBuilder() - .setValue(newUuid()) - .build(); - final TestActorRequestFactory factory = + TenantId generatedTenantId = TenantId.newBuilder() + .setValue(newUuid()) + .build(); + TestActorRequestFactory factory = TestActorRequestFactory.newInstance(userId, generatedTenantId); - final Command result = factory.createCommand(command, when); + Command result = factory.createCommand(command, when); return result; } @@ -145,34 +138,45 @@ private static Command createProject(Timestamp when) { } private static Command createProject(UserId userId, ProjectId projectId, Timestamp when) { - final AggCreateProject command = CommandMessage.createProject(projectId); + AggCreateProject command = CommandMessage.createProject(projectId); return create(command, userId, when); } static Command createCustomer() { - final LocalDate localDate = LocalDates.now(); - final CustomerId customerId = CustomerId.newBuilder() - .setRegistrationDate(localDate) - .setNumber(customerNumber.get()) - .build(); + LocalDate localDate = LocalDates.now(); + CustomerId customerId = CustomerId + .newBuilder() + .setRegistrationDate(localDate) + .setNumber(customerNumber.get()) + .build(); customerNumber.incrementAndGet(); - final PersonName personName = PersonName.newBuilder() - .setGivenName("Kreat") - .setFamilyName("C'Ustomer") - .setHonorificSuffix("Cmd") - .build(); - final Customer customer = Customer.newBuilder() - .setId(customerId) - .setName(personName) - .build(); - final Message msg = CreateCustomer.newBuilder() - .setCustomerId(customerId) - .setCustomer(customer) - .build(); - final UserId userId = of(Identifier.newUuid()); - final Command result = create(msg, userId, getCurrentTime()); + PersonName personName = PersonName + .newBuilder() + .setGivenName("Kreat") + .setFamilyName("C'Ustomer") + .setHonorificSuffix("Cmd") + .build(); + Customer customer = Customer + .newBuilder() + .setId(customerId) + .setName(personName) + .build(); + Message msg = CreateCustomer + .newBuilder() + .setCustomerId(customerId) + .setCustomer(customer) + .build(); + UserId userId = of(Identifier.newUuid()); + Command result = create(msg, userId, getCurrentTime()); return result; } + + private static ProjectId newProjectId() { + String uuid = newUuid(); + return ProjectId.newBuilder() + .setId(uuid) + .build(); + } } static class AQuery { @@ -193,6 +197,7 @@ static Query readAllProjects() { static class ProjectAggregateRepository extends AggregateRepository { + ProjectAggregateRepository() { super(); } @@ -200,6 +205,7 @@ static class ProjectAggregateRepository private static class ProjectAggregate extends Aggregate { + // an aggregate constructor must be public because it is used via reflection @SuppressWarnings("PublicConstructorInNonPublicClass") public ProjectAggregate(ProjectId id) { @@ -218,7 +224,7 @@ AggTaskAdded handle(AggAddTask cmd, CommandContext ctx) { @Assign List handle(AggStartProject cmd, CommandContext ctx) { - final AggProjectStarted message = EventMessage.projectStarted(cmd.getProjectId()); + AggProjectStarted message = EventMessage.projectStarted(cmd.getProjectId()); return newArrayList(message); } @@ -226,8 +232,7 @@ List handle(AggStartProject cmd, CommandContext ctx) { void event(AggProjectCreated event) { getBuilder() .setId(event.getProjectId()) - .setStatus(Status.CREATED) - .build(); + .setStatus(Status.CREATED); } @Apply @@ -238,13 +243,13 @@ void event(AggTaskAdded event) { void event(AggProjectStarted event) { getBuilder() .setId(event.getProjectId()) - .setStatus(Status.STARTED) - .build(); + .setStatus(Status.STARTED); } } public static class CustomerAggregateRepository extends AggregateRepository { + public CustomerAggregateRepository() { super(); } @@ -261,10 +266,11 @@ public CustomerAggregate(CustomerId id) { @Assign CustomerCreated handle(CreateCustomer cmd, CommandContext ctx) { - final CustomerCreated event = CustomerCreated.newBuilder() - .setCustomerId(cmd.getCustomerId()) - .setCustomer(cmd.getCustomer()) - .build(); + CustomerCreated event = CustomerCreated + .newBuilder() + .setCustomerId(cmd.getCustomerId()) + .setCustomer(cmd.getCustomer()) + .build(); return event; } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java index ec545680848..6bf3796f4a5 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateTransactionShould.java @@ -167,7 +167,6 @@ AggProjectCreated handle(AggCreateProject cmd, CommandContext ctx) { return projectCreated(cmd.getProjectId(), cmd.getName()); } - @SuppressWarnings("CheckReturnValue") // calling builder @Apply void event(AggProjectCreated event) { receivedEvents.add(event); diff --git a/server/src/test/java/io/spine/server/command/CommandHandlerMethodShould.java b/server/src/test/java/io/spine/server/command/CommandHandlerMethodShould.java index 5c29c033ead..20c1e6affaa 100644 --- a/server/src/test/java/io/spine/server/command/CommandHandlerMethodShould.java +++ b/server/src/test/java/io/spine/server/command/CommandHandlerMethodShould.java @@ -50,7 +50,9 @@ import io.spine.test.reflect.command.RefCreateProject; import io.spine.test.reflect.event.RefProjectCreated; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.lang.reflect.Method; import java.util.List; @@ -72,6 +74,9 @@ */ public class CommandHandlerMethodShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final TestActorRequestFactory requestFactory = TestActorRequestFactory.newInstance(CommandHandlerMethodShould.class); @@ -82,10 +87,10 @@ private static void assertIsCommandHandler(Method handler, boolean isHandler) { } private static void assertCauseAndId(HandlerMethodFailedException e, Object handlerId) { - final Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof ThrowableMessage); - final ThrowableMessage thrown = (ThrowableMessage) cause; + ThrowableMessage thrown = (ThrowableMessage) cause; assertTrue(thrown.producerId() .isPresent()); @@ -110,129 +115,132 @@ public void pass_null_tolerance_check() { @Test public void invoke_handler_method_which_returns_one_message() { - final ValidHandlerTwoParams handlerObject = spy(new ValidHandlerTwoParams()); - final CommandHandlerMethod handler = from(handlerObject.getHandler()); - final RefCreateProject cmd = createProject(); + ValidHandlerTwoParams handlerObject = spy(new ValidHandlerTwoParams()); + CommandHandlerMethod handler = from(handlerObject.getHandler()); + RefCreateProject cmd = createProject(); - final List events = handler.invoke(handlerObject, cmd, emptyContext); + List events = handler.invoke(handlerObject, cmd, emptyContext); verify(handlerObject, times(1)) .handleTest(cmd, emptyContext); assertEquals(1, events.size()); - final RefProjectCreated event = (RefProjectCreated) events.get(0); + RefProjectCreated event = (RefProjectCreated) events.get(0); assertEquals(cmd.getProjectId(), event.getProjectId()); } @Test public void invoke_handler_method_and_return_message_list() { - final ValidHandlerOneParamReturnsList handlerObject = + ValidHandlerOneParamReturnsList handlerObject = spy(new ValidHandlerOneParamReturnsList()); - final CommandHandlerMethod handler = from(handlerObject.getHandler()); - final RefCreateProject cmd = createProject(); + CommandHandlerMethod handler = from(handlerObject.getHandler()); + RefCreateProject cmd = createProject(); - final List events = handler.invoke(handlerObject, cmd, emptyContext); + List events = handler.invoke(handlerObject, cmd, emptyContext); verify(handlerObject, times(1)).handleTest(cmd); assertEquals(1, events.size()); - final RefProjectCreated event = (RefProjectCreated) events.get(0); + RefProjectCreated event = (RefProjectCreated) events.get(0); assertEquals(cmd.getProjectId(), event.getProjectId()); } @Test public void consider_handler_with_one_msg_param_valid() { - final Method handler = new ValidHandlerOneParam().getHandler(); + Method handler = new ValidHandlerOneParam().getHandler(); assertIsCommandHandler(handler, true); } @Test public void consider_handler_with_one_msg_param_which_returns_list_valid() { - final Method handler = new ValidHandlerOneParamReturnsList().getHandler(); + Method handler = new ValidHandlerOneParamReturnsList().getHandler(); assertIsCommandHandler(handler, true); } @Test public void consider_handler_with_msg_and_context_params_valid() { - final Method handler = new ValidHandlerTwoParams().getHandler(); + Method handler = new ValidHandlerTwoParams().getHandler(); assertIsCommandHandler(handler, true); } @Test public void consider_handler_with_msg_and_context_params_which_returns_list_valid() { - final Method handler = new ValidHandlerTwoParamsReturnsList().getHandler(); + Method handler = new ValidHandlerTwoParamsReturnsList().getHandler(); assertIsCommandHandler(handler, true); } @Test public void consider_not_public_handler_valid() { - final Method method = new ValidHandlerButPrivate().getHandler(); + Method method = new ValidHandlerButPrivate().getHandler(); assertIsCommandHandler(method, true); } @Test public void consider_not_annotated_handler_invalid() { - final Method handler = new InvalidHandlerNoAnnotation().getHandler(); + Method handler = new InvalidHandlerNoAnnotation().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_handler_without_params_invalid() { - final Method handler = new InvalidHandlerNoParams().getHandler(); + Method handler = new InvalidHandlerNoParams().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_handler_with_too_many_params_invalid() { - final Method handler = new InvalidHandlerTooManyParams().getHandler(); + Method handler = new InvalidHandlerTooManyParams().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_handler_with_one_invalid_param_invalid() { - final Method handler = new InvalidHandlerOneNotMsgParam().getHandler(); + Method handler = new InvalidHandlerOneNotMsgParam().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_handler_with_first_not_message_param_invalid() { - final Method handler = new InvalidHandlerTwoParamsFirstInvalid().getHandler(); + Method handler = new InvalidHandlerTwoParamsFirstInvalid().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_handler_with_second_not_context_param_invalid() { - final Method handler = new InvalidHandlerTwoParamsSecondInvalid().getHandler(); + Method handler = new InvalidHandlerTwoParamsSecondInvalid().getHandler(); assertIsCommandHandler(handler, false); } @Test public void consider_void_handler_invalid() { - final Method handler = new InvalidHandlerReturnsVoid().getHandler(); + Method handler = new InvalidHandlerReturnsVoid().getHandler(); assertIsCommandHandler(handler, false); } - @Test(expected = IllegalStateException.class) + @Test public void throw_ISE_for_not_handled_command_type() { - final CommandHandler handler = new ValidHandlerOneParam(); - final CommandEnvelope cmd = requestFactory.createEnvelope(startProject()); + CommandHandler handler = new ValidHandlerOneParam(); + CommandEnvelope cmd = requestFactory.createEnvelope(startProject()); + + thrown.expect(IllegalStateException.class); handler.dispatch(cmd); } + @SuppressWarnings("CheckReturnValue") // no need as the call to dispatch() throws @Test public void set_producer_ID_if_command_handler() { - final CommandHandler handler = new RejectingHandler(); - final CommandEnvelope envelope = requestFactory.createEnvelope(createProject()); + CommandHandler handler = new RejectingHandler(); + CommandEnvelope envelope = requestFactory.createEnvelope(createProject()); try { handler.dispatch(envelope); } catch (HandlerMethodFailedException e) { @@ -240,12 +248,13 @@ public void set_producer_ID_if_command_handler() { } } + @SuppressWarnings("CheckReturnValue") // no need as the call to dispatchCommand() throws @Test public void set_producer_ID_if_entity() { - final RefCreateProject commandMessage = createProject(); - final Aggregate entity = + RefCreateProject commandMessage = createProject(); + Aggregate entity = new RejectingAggregate(commandMessage.getProjectId()); - final CommandEnvelope cmd = requestFactory.createEnvelope(commandMessage); + CommandEnvelope cmd = requestFactory.createEnvelope(commandMessage); try { AggregateMessageDispatcher.dispatchCommand(entity, cmd); } catch (HandlerMethodFailedException e) { diff --git a/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java b/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java index 21e261fc668..008892b651e 100644 --- a/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java +++ b/server/src/test/java/io/spine/server/commandbus/given/CommandDispatcherRegistryTestEnv.java @@ -38,10 +38,10 @@ import io.spine.server.procman.ProcessManagerRepository; import io.spine.test.command.CmdAddTask; import io.spine.test.command.CmdCreateProject; +import io.spine.test.command.CmdStartProject; import io.spine.test.command.Project; import io.spine.test.command.ProjectId; import io.spine.test.command.ProjectVBuilder; -import io.spine.test.command.CmdStartProject; import io.spine.test.command.Task; import io.spine.test.command.event.CmdProjectCreated; import io.spine.test.command.event.CmdProjectStarted; @@ -87,7 +87,6 @@ public void on(CmdProjectCreated event) { handleProjectCreated(event.getProjectId()); } - @SuppressWarnings("CheckReturnValue") // calling builder private void handleProjectCreated(ProjectId projectId) { final Project newState = getState().toBuilder() .setId(projectId) @@ -104,7 +103,6 @@ public void on(CmdTaskAdded event) { handleTaskAdded(task); } - @SuppressWarnings("CheckReturnValue") // calling builder private void handleTaskAdded(Task task) { final Project newState = getState().toBuilder() .addTask(task) @@ -119,7 +117,6 @@ public void on(CmdProjectStarted event) { handleProjectStarted(); } - @SuppressWarnings("CheckReturnValue") // calling builder private void handleProjectStarted() { final Project newState = getState().toBuilder() .setStatus(Project.Status.STARTED) diff --git a/server/src/test/java/io/spine/server/commandstore/StorageShould.java b/server/src/test/java/io/spine/server/commandstore/StorageShould.java index b50f9fca6fe..3558b40a3bd 100644 --- a/server/src/test/java/io/spine/server/commandstore/StorageShould.java +++ b/server/src/test/java/io/spine/server/commandstore/StorageShould.java @@ -44,7 +44,9 @@ import io.spine.test.Tests; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; import java.util.List; @@ -79,6 +81,9 @@ public class StorageShould extends TenantAwareTest { private static final Error defaultError = Error.getDefaultInstance(); private static final Rejection DEFAULT_REJECTION = Rejection.getDefaultInstance(); + @Rule + public ExpectedException thrown = ExpectedException.none(); + private CRepository repository; private CommandId id; @@ -264,72 +269,79 @@ public void convert_cmd_to_record() { * Check that exception is thrown if try to pass null to methods. **************************************************************/ - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_store_null() { + thrown.expect(NullPointerException.class); repository.store(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_set_OK_status_by_null_ID() { - repository.setOkStatus(Tests.nullRef()); + thrown.expect(NullPointerException.class); + repository.setOkStatus(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_try_to_set_error_status_by_null_ID() { + thrown.expect(NullPointerException.class); repository.updateStatus(Tests.nullRef(), defaultError); } @Test(expected = NullPointerException.class) public void throw_exception_if_try_to_set_rejection_status_by_null_ID() { - repository.updateStatus(Tests.nullRef(), DEFAULT_REJECTION); + repository.updateStatus(Tests.nullRef(), DEFAULT_REJECTION); } /* * Check that exception is thrown if try to use closed storage. **************************************************************/ - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_store_cmd_to_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.store(Given.ACommand.createProject()); } - @Test(expected = IllegalStateException.class) - public void throw_exception_if_try_to_store_cmd_with_error_to_closed_storage() throws - Exception { + @Test + public void throw_exception_if_try_to_store_cmd_with_error_to_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.store(Given.ACommand.createProject(), newError()); } - @Test(expected = IllegalStateException.class) - public void throw_exception_if_try_to_store_cmd_with_status_to_closed_storage() throws - Exception { + @Test + public void throw_exception_if_try_to_store_cmd_with_status_to_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.store(Given.ACommand.createProject(), OK); } - @Test(expected = IllegalStateException.class) - public void throw_exception_if_try_to_load_commands_by_status_from_closed_storage() throws - Exception { + @Test + public void throw_exception_if_try_to_load_commands_by_status_from_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.iterator(OK); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_set_OK_status_using_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.setOkStatus(generateId()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_set_ERROR_status_using_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.updateStatus(generateId(), newError()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_try_to_set_REJECTED_status_using_closed_storage() { repository.close(); + thrown.expect(IllegalStateException.class); repository.updateStatus(generateId(), newRejection()); } diff --git a/server/src/test/java/io/spine/server/delivery/ShardedStreamBuilderShould.java b/server/src/test/java/io/spine/server/delivery/ShardedStreamBuilderShould.java index 8d3a0092224..52e74e27566 100644 --- a/server/src/test/java/io/spine/server/delivery/ShardedStreamBuilderShould.java +++ b/server/src/test/java/io/spine/server/delivery/ShardedStreamBuilderShould.java @@ -23,11 +23,12 @@ import io.spine.server.BoundedContext; import io.spine.server.delivery.given.ShardedStreamTestEnv.TaskAggregateRepository; import io.spine.server.model.ModelTests; -import io.spine.server.transport.TransportFactory; import io.spine.test.Tests; import io.spine.test.aggregate.ProjectId; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.server.delivery.given.ShardedStreamTestEnv.builder; import static org.junit.Assert.assertEquals; @@ -39,74 +40,83 @@ @SuppressWarnings("unchecked") // the numerous generic parameters are omitted to simplify tests. public class ShardedStreamBuilderShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void setUp() { // as long as we refer to the Model in delivery tag initialization. ModelTests.clearModel(); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_boundedContextName() { - builder().setBoundedContextName(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setBoundedContextName(Tests.nullRef()); } @Test public void return_set_boundedContextName() { - final BoundedContextName value = BoundedContext.newName("ShardedStreams"); + BoundedContextName value = BoundedContext.newName("ShardedStreams"); assertEquals(value, builder().setBoundedContextName(value) .getBoundedContextName()); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_key() { - builder().setKey(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setKey(Tests.nullRef()); } @Test public void return_set_key() { - final ShardingKey value = mock(ShardingKey.class); + ShardingKey value = mock(ShardingKey.class); assertEquals(value, builder().setKey(value) .getKey()); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_tag() { - builder().setTag(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setTag(Tests.nullRef()); } @Test public void return_set_tag() { - final DeliveryTag value = DeliveryTag.forCommandsOf(new TaskAggregateRepository()); + DeliveryTag value = DeliveryTag.forCommandsOf(new TaskAggregateRepository()); assertEquals(value, builder().setTag(value) .getTag()); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_targetIdClass() { - builder().setTargetIdClass(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setTargetIdClass(Tests.nullRef()); } @Test public void return_set_targetIdClass() { - final Class value = ProjectId.class; + Class value = ProjectId.class; assertEquals(value, builder().setTargetIdClass(value) .getTargetIdClass()); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_consumer() { + thrown.expect(NullPointerException.class); builder().setConsumer(Tests.nullRef()); } @Test public void return_set_consumer() { - final Consumer value = mock(Consumer.class); + Consumer value = mock(Consumer.class); assertEquals(value, builder().setConsumer(value) .getConsumer()); } - @Test(expected = NullPointerException.class) + @Test public void not_accept_null_transportFactory() { - builder().build(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().build(Tests.nullRef()); } } diff --git a/server/src/test/java/io/spine/server/delivery/UniformAcrossTargetsShould.java b/server/src/test/java/io/spine/server/delivery/UniformAcrossTargetsShould.java index 560cb968532..46b3af8c9a9 100644 --- a/server/src/test/java/io/spine/server/delivery/UniformAcrossTargetsShould.java +++ b/server/src/test/java/io/spine/server/delivery/UniformAcrossTargetsShould.java @@ -20,7 +20,9 @@ package io.spine.server.delivery; import com.google.common.testing.EqualsTester; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.server.delivery.UniformAcrossTargets.forNumber; import static io.spine.server.delivery.UniformAcrossTargets.singleShard; @@ -30,6 +32,9 @@ */ public class UniformAcrossTargetsShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void support_equality() { new EqualsTester().addEqualityGroup(singleShard(), singleShard(), forNumber(1)) @@ -38,13 +43,15 @@ public void support_equality() { .testEquals(); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_allow_negative_number_of_shards() { + thrown.expect(IllegalArgumentException.class); forNumber(-1); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_allow_zero_number_of_shards() { + thrown.expect(IllegalArgumentException.class); forNumber(0); } } diff --git a/server/src/test/java/io/spine/server/delivery/given/ShardedStreamTestEnv.java b/server/src/test/java/io/spine/server/delivery/given/ShardedStreamTestEnv.java index 278da2bf2e7..6193763f266 100644 --- a/server/src/test/java/io/spine/server/delivery/given/ShardedStreamTestEnv.java +++ b/server/src/test/java/io/spine/server/delivery/given/ShardedStreamTestEnv.java @@ -77,7 +77,7 @@ public class ShardedStreamTestEnv { private static final CommandShardedStream tasksShardOne; static { - final Model model = Model.getInstance(); + Model model = Model.getInstance(); projectAggregateClass = model.asAggregateClass(ProjectAggregate.class); taskAggregateClass = model.asAggregateClass(TaskAggregate.class); projectRepo = new ProjectAggregateRepository(); @@ -85,11 +85,11 @@ public class ShardedStreamTestEnv { projectsShardOneKey = shardingKeyOf(projectAggregateClass, 1); commandsToProjects = DeliveryTag.forCommandsOf(projectRepo); - final TaskAggregateRepository taskRepo = new TaskAggregateRepository(); - final BoundedContextName tasksContextName = taskRepo.getBoundedContextName(); - final ShardingKey tasksShardZeroKey = shardingKeyOf(taskAggregateClass, 0); - final ShardingKey tasksShardOneKey = shardingKeyOf(taskAggregateClass, 1); - final DeliveryTag commandsToTask = DeliveryTag.forCommandsOf(taskRepo); + TaskAggregateRepository taskRepo = new TaskAggregateRepository(); + BoundedContextName tasksContextName = taskRepo.getBoundedContextName(); + ShardingKey tasksShardZeroKey = shardingKeyOf(taskAggregateClass, 0); + ShardingKey tasksShardOneKey = shardingKeyOf(taskAggregateClass, 1); + DeliveryTag commandsToTask = DeliveryTag.forCommandsOf(taskRepo); projectsShardZero = streamToProject(transportFactory, projectsContextName, @@ -111,7 +111,7 @@ public class ShardedStreamTestEnv { projectsShardOneKey, commandsToProjects); - final ShardedStreamConsumer taskConsumer = dummyConsumer(); + ShardedStreamConsumer taskConsumer = dummyConsumer(); tasksShardZero = streamToTask(tasksContextName, tasksShardZeroKey, commandsToTask, @@ -122,23 +122,24 @@ public class ShardedStreamTestEnv { taskConsumer); } + /** + * Prevents this test environment utility from initialization. + */ + private ShardedStreamTestEnv() { + } + private static CommandShardedStream streamToTask(BoundedContextName contextName, ShardingKey key, DeliveryTag tag, ShardedStreamConsumer consumer) { - return CommandShardedStream.newBuilder().setBoundedContextName(contextName) - .setKey(key) - .setTag(tag) - .setConsumer(consumer) - .setTargetIdClass(TaskId.class) - .build(transportFactory); - } - - /** - * Prevents this test environment utility from initialization. - */ - private ShardedStreamTestEnv() { + return CommandShardedStream.newBuilder() + .setBoundedContextName(contextName) + .setKey(key) + .setTag(tag) + .setConsumer(consumer) + .setTargetIdClass(TaskId.class) + .build(transportFactory); } public static CommandShardedStream projectsShardZero() { @@ -167,22 +168,22 @@ public static CommandShardedStream tasksShardOne() { public static CommandShardedStream streamToShardWithFactory(TransportFactory factory) { - final CommandShardedStream.Builder builder = CommandShardedStream.newBuilder(); - final ShardedStreamConsumer consumer = dummyConsumer(); + CommandShardedStream.Builder builder = CommandShardedStream.newBuilder(); + ShardedStreamConsumer consumer = dummyConsumer(); builder.setBoundedContextName(projectsContextName) .setKey(projectsShardZeroKey) .setTag(commandsToProjects) .setConsumer(consumer) .setTargetIdClass(ProjectId.class); - final CommandShardedStream result = builder.build(factory); + CommandShardedStream result = builder.build(factory); return result; } private static CommandShardedStream streamToProject(TransportFactory factory, BoundedContextName contextName, ShardingKey key, DeliveryTag tag) { - final CommandShardedStream.Builder builder = CommandShardedStream.newBuilder(); - final ShardedStreamConsumer consumer = dummyConsumer(); + CommandShardedStream.Builder builder = CommandShardedStream.newBuilder(); + ShardedStreamConsumer consumer = dummyConsumer(); return builder.setBoundedContextName(contextName) .setKey(key) .setTag(tag) @@ -229,14 +230,14 @@ private static ShardIndex shardIndexOf(int index) { } public static TransportFactory - customFactory(final Function, Void> observerCallback) { + customFactory(Function, Void> observerCallback) { return new InMemoryTransportFactory() { @Override protected Subscriber newSubscriber(ChannelId channelId) { return new InMemorySubscriber(channelId) { @Override public void onMessage(ExternalMessage message) { - final Iterable> observers = getObservers(); + Iterable> observers = getObservers(); for (StreamObserver observer : observers) { observerCallback.apply(observer); } @@ -246,6 +247,16 @@ public void onMessage(ExternalMessage message) { }; } + public static CommandShardedStream.AbstractBuilder builder() { + return new ShardedStream.AbstractBuilder() { + @Override + protected ShardedStream createStream() { + throw newIllegalStateException("Method mustn't be called " + + "in the `AbstractBuilder` tests"); + } + }; + } + public static class ProjectAggregate extends Aggregate { @@ -293,19 +304,10 @@ private void on(AggTaskAdded event) { public static class TaskAggregateRepository extends AggregateRepository { + @Override public BoundedContextName getBoundedContextName() { return tasksContextName; } } - - public static CommandShardedStream.AbstractBuilder builder() { - return new ShardedStream.AbstractBuilder() { - @Override - protected ShardedStream createStream() { - throw newIllegalStateException("Method mustn't be called " + - "in the `AbstractBuilder` tests"); - } - }; - } } diff --git a/server/src/test/java/io/spine/server/event/EventBusShould.java b/server/src/test/java/io/spine/server/event/EventBusShould.java index ceec1102367..b19549349f5 100644 --- a/server/src/test/java/io/spine/server/event/EventBusShould.java +++ b/server/src/test/java/io/spine/server/event/EventBusShould.java @@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableSet; import com.google.protobuf.Int32Value; import com.google.protobuf.Message; -import io.spine.core.Ack; import io.spine.core.Command; import io.spine.core.Event; import io.spine.core.EventClass; @@ -45,12 +44,14 @@ import io.spine.test.event.EBTaskAdded; import io.spine.test.event.ProjectCreated; import io.spine.test.event.Task; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.After; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.List; import java.util.Set; @@ -85,24 +86,38 @@ */ public class EventBusShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private EventBus eventBus; private CommandBus commandBus; private BoundedContext bc; + @SuppressWarnings("CheckReturnValue") // conditionally calling builder + private static EventBus.Builder eventBusBuilder(@Nullable EventEnricher enricher) { + EventBus.Builder busBuilder = EventBus + .newBuilder() + .appendFilter(new TaskCreatedFilter()); + if (enricher != null) { + busBuilder.setEnricher(enricher); + } + return busBuilder; + } + @Before public void setUp() { setUp(null); } private void setUp(@Nullable EventEnricher enricher) { - final EventBus.Builder eventBusBuilder = eventBusBuilder(enricher); + EventBus.Builder eventBusBuilder = eventBusBuilder(enricher); bc = BoundedContext.newBuilder() .setEventBus(eventBusBuilder) .setMultitenant(true) .build(); - final ProjectRepository projectRepository = new ProjectRepository(); + ProjectRepository projectRepository = new ProjectRepository(); bc.register(projectRepository); this.commandBus = bc.getCommandBus(); @@ -114,15 +129,6 @@ public void tearDown() throws Exception { bc.close(); } - private static EventBus.Builder eventBusBuilder(@Nullable EventEnricher enricher) { - final EventBus.Builder busBuilder = EventBus.newBuilder() - .appendFilter(new TaskCreatedFilter()); - if (enricher != null) { - busBuilder.setEnricher(enricher); - } - return busBuilder; - } - @Test public void have_builder() { assertNotNull(EventBus.newBuilder()); @@ -130,15 +136,16 @@ public void have_builder() { @Test public void return_associated_EventStore() { - final EventStore eventStore = mock(EventStore.class); - final EventBus result = EventBus.newBuilder() - .setEventStore(eventStore) - .build(); + EventStore eventStore = mock(EventStore.class); + EventBus result = EventBus.newBuilder() + .setEventStore(eventStore) + .build(); assertEquals(eventStore, result.getEventStore()); } - @Test(expected = IllegalArgumentException.class) + @Test public void reject_object_with_no_subscriber_methods() { + thrown.expect(IllegalArgumentException.class); // Pass just String instance. eventBus.register(new EventSubscriber() { }); @@ -146,16 +153,16 @@ public void reject_object_with_no_subscriber_methods() { @Test public void register_event_subscriber() { - final EventSubscriber subscriberOne = new ProjectCreatedSubscriber(); - final EventSubscriber subscriberTwo = new ProjectCreatedSubscriber(); + EventSubscriber subscriberOne = new ProjectCreatedSubscriber(); + EventSubscriber subscriberTwo = new ProjectCreatedSubscriber(); eventBus.register(subscriberOne); eventBus.register(subscriberTwo); - final EventClass eventClass = EventClass.of(ProjectCreated.class); + EventClass eventClass = EventClass.of(ProjectCreated.class); assertTrue(eventBus.hasDispatchers(eventClass)); - final Collection> dispatchers = + Collection> dispatchers = eventBus.getDispatchers(eventClass); assertTrue(dispatchers.contains(subscriberOne)); assertTrue(dispatchers.contains(subscriberTwo)); @@ -163,17 +170,17 @@ public void register_event_subscriber() { @Test public void unregister_subscribers() { - final EventSubscriber subscriberOne = new ProjectCreatedSubscriber(); - final EventSubscriber subscriberTwo = new ProjectCreatedSubscriber(); + EventSubscriber subscriberOne = new ProjectCreatedSubscriber(); + EventSubscriber subscriberTwo = new ProjectCreatedSubscriber(); eventBus.register(subscriberOne); eventBus.register(subscriberTwo); - final EventClass eventClass = EventClass.of(ProjectCreated.class); + EventClass eventClass = EventClass.of(ProjectCreated.class); eventBus.unregister(subscriberOne); // Check that the 2nd subscriber with the same event subscriber method remains // after the 1st subscriber unregisters. - final Collection> subscribers = + Collection> subscribers = eventBus.getDispatchers(eventClass); assertFalse(subscribers.contains(subscriberOne)); assertTrue(subscribers.contains(subscriberTwo)); @@ -187,8 +194,8 @@ public void unregister_subscribers() { @Test public void call_subscriber_when_event_posted() { - final ProjectCreatedSubscriber subscriber = new ProjectCreatedSubscriber(); - final Event event = GivenEvent.projectCreated(); + ProjectCreatedSubscriber subscriber = new ProjectCreatedSubscriber(); + Event event = GivenEvent.projectCreated(); eventBus.register(subscriber); eventBus.post(event); @@ -200,7 +207,7 @@ public void call_subscriber_when_event_posted() { @Test public void register_dispatchers() { - final EventDispatcher dispatcher = new BareDispatcher(); + EventDispatcher dispatcher = new BareDispatcher(); eventBus.register(dispatcher); @@ -210,7 +217,7 @@ public void register_dispatchers() { @Test public void call_dispatchers() { - final BareDispatcher dispatcher = new BareDispatcher(); + BareDispatcher dispatcher = new BareDispatcher(); eventBus.register(dispatcher); @@ -221,14 +228,14 @@ public void call_dispatchers() { @Test public void unregister_dispatchers() { - final EventDispatcher dispatcherOne = new BareDispatcher(); - final EventDispatcher dispatcherTwo = new BareDispatcher(); - final EventClass eventClass = EventClass.of(ProjectCreated.class); + EventDispatcher dispatcherOne = new BareDispatcher(); + EventDispatcher dispatcherTwo = new BareDispatcher(); + EventClass eventClass = EventClass.of(ProjectCreated.class); eventBus.register(dispatcherOne); eventBus.register(dispatcherTwo); eventBus.unregister(dispatcherOne); - final Set> dispatchers = eventBus.getDispatchers(eventClass); + Set> dispatchers = eventBus.getDispatchers(eventClass); // Check we don't have 1st dispatcher, but have 2nd. assertFalse(dispatchers.contains(dispatcherOne)); @@ -241,13 +248,14 @@ public void unregister_dispatchers() { @Test public void unregister_registries_on_close() throws Exception { - final EventStore eventStore = spy(mock(EventStore.class)); - final EventBus eventBus = EventBus.newBuilder() - .setEventStore(eventStore) - .build(); + EventStore eventStore = spy(mock(EventStore.class)); + EventBus eventBus = EventBus + .newBuilder() + .setEventStore(eventStore) + .build(); eventBus.register(new BareDispatcher()); eventBus.register(new ProjectCreatedSubscriber()); - final EventClass eventClass = EventClass.of(ProjectCreated.class); + EventClass eventClass = EventClass.of(ProjectCreated.class); eventBus.close(); @@ -258,8 +266,8 @@ public void unregister_registries_on_close() throws Exception { @Test public void enrich_event_if_it_can_be_enriched() { - final EventEnricher enricher = mock(EventEnricher.class); - final EventEnvelope event = EventEnvelope.of(GivenEvent.projectCreated()); + EventEnricher enricher = mock(EventEnricher.class); + EventEnvelope event = EventEnvelope.of(GivenEvent.projectCreated()); doReturn(true).when(enricher) .canBeEnriched(any(EventEnvelope.class)); doReturn(event).when(enricher) @@ -277,7 +285,7 @@ public void enrich_event_if_it_can_be_enriched() { @Test public void do_not_enrich_event_if_it_cannot_be_enriched() { - final EventEnricher enricher = mock(EventEnricher.class); + EventEnricher enricher = mock(EventEnricher.class); doReturn(false).when(enricher) .canBeEnriched(any(EventEnvelope.class)); @@ -293,72 +301,70 @@ public void do_not_enrich_event_if_it_cannot_be_enriched() { @Test public void create_validator_once() { - final EnvelopeValidator validator = eventBus.getValidator(); + EnvelopeValidator validator = eventBus.getValidator(); assertNotNull(validator); assertSame(validator, eventBus.getValidator()); } @Test public void store_an_event() { - final Command command = command(createProject()); + Command command = command(createProject()); eventBus.register(new EBProjectCreatedNoOpSubscriber()); + commandBus.post(command, StreamObservers.noOpObserver()); - System.out.println("JUnit test: " + Thread.currentThread().getId()); - commandBus.post(command, StreamObservers.noOpObserver()); - - final List events = readEvents(eventBus); + List events = readEvents(eventBus); assertSize(1, events); } @Test public void store_a_dead_event() { - final Command command = command(createProject()); + Command command = command(createProject()); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List events = readEvents(eventBus); + List events = readEvents(eventBus); assertSize(1, events); } @Test public void not_store_an_invalid_event() { - final Command command = command(invalidArchiveProject()); + Command command = command(invalidArchiveProject()); eventBus.register(new EBProjectArchivedSubscriber()); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List events = readEvents(eventBus); + List events = readEvents(eventBus); assertSize(0, events); } @Test public void not_store_an_invalid_dead_event() { - final Command command = command(invalidArchiveProject()); + Command command = command(invalidArchiveProject()); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List events = readEvents(eventBus); + List events = readEvents(eventBus); assertSize(0, events); } /** * Ensures that events are stored when all of them pass the filters. * - *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. - * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with + *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. + * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with * {@link Task#getDone()} set to {@code true}. * - *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get + *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get * filtered out by the {@link io.spine.server.bus.DeadMessageFilter}. */ @Test public void store_multiple_messages_passing_filters() { eventBus.register(new EBTaskAddedNoOpSubscriber()); - final Command command = command(addTasks(newTask(false), newTask(false), newTask(false))); + Command command = command(addTasks(newTask(false), newTask(false), newTask(false))); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List storedEvents = readEvents(eventBus); + List storedEvents = readEvents(eventBus); assertSize(3, storedEvents); } @@ -366,28 +372,27 @@ public void store_multiple_messages_passing_filters() { * Ensures that events which pass filters and the ones that don’t are treated independently when * sent in batch. * - *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. - * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with + *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. + * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with * {@link Task#getDone()} set to {@code true}. - * - *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get + * + *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get * filtered out by the {@link io.spine.server.bus.DeadMessageFilter}. - * */ @Test public void store_only_events_passing_filters() { eventBus.register(new EBTaskAddedNoOpSubscriber()); - final Command command = command(addTasks(newTask(false), newTask(true), newTask(false), - newTask(true), newTask(true))); + Command command = command(addTasks(newTask(false), newTask(true), newTask(false), + newTask(true), newTask(true))); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List storedEvents = readEvents(eventBus); + List storedEvents = readEvents(eventBus); assertSize(2, storedEvents); for (Event event : storedEvents) { - final EBTaskAdded contents = unpack(event.getMessage()); - final Task task = contents.getTask(); + EBTaskAdded contents = unpack(event.getMessage()); + Task task = contents.getTask(); assertFalse(task.getDone()); } } @@ -395,21 +400,21 @@ public void store_only_events_passing_filters() { /** * Ensures that events are not stored when none of them pass the filters. * - *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. - * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with + *

To filter the {@link EBTaskAdded} events the {@linkplain EventBus} has a custom filter. + * The {@link TaskCreatedFilter} filters out {@link EBTaskAdded} events with * {@link Task#getDone()} set to {@code true}. * - *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get + *

The {@link EBTaskAddedNoOpSubscriber} is registered so that the event would not get * filtered out by the {@link io.spine.server.bus.DeadMessageFilter}. */ @Test public void not_store_any_events_when_they_are_failing_filtering() { eventBus.register(new EBTaskAddedNoOpSubscriber()); - final Command command = command(addTasks(newTask(true), newTask(true), newTask(true))); + Command command = command(addTasks(newTask(true), newTask(true), newTask(true))); - commandBus.post(command, StreamObservers.noOpObserver()); + commandBus.post(command, StreamObservers.noOpObserver()); - final List storedEvents = readEvents(eventBus); + List storedEvents = readEvents(eventBus); assertSize(0, storedEvents); } @@ -428,35 +433,34 @@ public void not_store_any_events_when_they_are_failing_filtering() { */ @SuppressWarnings("MethodWithMultipleLoops") // OK for such test case. @Ignore // This test is used only to diagnose EventBus malfunctions in concurrent environment. - // It's too long to execute this test per each build, so we leave it as is for now. - // Please see build log to find out if there were some errors during the test execution. + // It's too long to execute this test per each build, so we leave it as is for now. + // Please see build log to find out if there were some errors during the test execution. @Test public void store_filters_regarding_possible_concurrent_modifications() throws InterruptedException { - final int threadCount = 50; + int threadCount = 50; // "Random" more or less valid Event. - final Event event = Event.newBuilder() - .setId(EventId.newBuilder().setValue("123-1")) - .setMessage(pack(Int32Value.newBuilder() - .setValue(42) - .build())) - .build(); - final StorageFactory storageFactory = - StorageFactorySwitch.newInstance(newName("baz"), false).get(); - final ExecutorService executor = Executors.newFixedThreadPool(threadCount); + Event event = Event + .newBuilder() + .setId(EventId.newBuilder() + .setValue("123-1")) + .setMessage(pack(Int32Value.newBuilder() + .setValue(42) + .build())) + .build(); + StorageFactory storageFactory = + StorageFactorySwitch.newInstance(newName("baz"), false) + .get(); + ExecutorService executor = Executors.newFixedThreadPool(threadCount); // Catch non-easily reproducible bugs. for (int i = 0; i < 300; i++) { - final EventBus eventBus = EventBus.newBuilder() - .setStorageFactory(storageFactory) - .build(); + EventBus eventBus = EventBus + .newBuilder() + .setStorageFactory(storageFactory) + .build(); for (int j = 0; j < threadCount; j++) { - executor.execute(new Runnable() { - @Override - public void run() { - eventBus.post(event); - } - }); + executor.execute(() -> eventBus.post(event)); } // Let the system destroy all the native threads, clean up, etc. Thread.sleep(100); @@ -464,9 +468,17 @@ public void run() { executor.shutdownNow(); } + private void closeBoundedContext() { + try { + bc.close(); + } catch (Exception ignored) { + } + } + /** - * {@link EBProjectCreated} subscriber that does nothing. Can be used for the event to get pass the - * {@link io.spine.server.bus.DeadMessageFilter}. + * {@link EBProjectCreated} subscriber that does nothing. + * + *

Can be used for the event to get pass the {@link io.spine.server.bus.DeadMessageFilter}. */ private static class EBProjectCreatedNoOpSubscriber extends EventSubscriber { @@ -476,7 +488,6 @@ public void on(EBProjectCreated message, EventContext context) { } } - private static class EBProjectArchivedSubscriber extends EventSubscriber { private Message eventMessage; @@ -551,11 +562,4 @@ private boolean isDispatchCalled() { return dispatchCalled; } } - - private void closeBoundedContext() { - try { - bc.close(); - } catch (Exception ignored) { - } - } } diff --git a/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java b/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java index 1e80ef5b3c3..bff01684da0 100644 --- a/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/EventEnricherTestEnv.java @@ -21,6 +21,7 @@ package io.spine.server.event.given; import com.google.common.base.Function; +import com.google.protobuf.AbstractMessage; import com.google.protobuf.Any; import com.google.protobuf.Message; import com.google.protobuf.Timestamp; @@ -32,6 +33,8 @@ import io.spine.people.PersonName; import io.spine.server.command.TestEventFactory; import io.spine.server.event.EventEnricher; +import io.spine.server.outbus.enrich.given.StringToPersonName; +import io.spine.server.outbus.enrich.given.StringToZoneOffset; import io.spine.test.event.ProjectCompleted; import io.spine.test.event.ProjectCreated; import io.spine.test.event.ProjectId; @@ -40,9 +43,7 @@ import io.spine.test.event.user.permission.PermissionGrantedEvent; import io.spine.test.event.user.permission.PermissionRevokedEvent; import io.spine.test.event.user.sharing.SharingRequestApproved; -import io.spine.time.ZoneId; import io.spine.time.ZoneOffset; - import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -55,12 +56,12 @@ public class EventEnricherTestEnv { /** Prevents instantiation of this utility class. */ - private EventEnricherTestEnv() {} + private EventEnricherTestEnv() { + } - static ProjectId newProjectId() { - final String uuid = newUuid(); + private static ProjectId newProjectId() { return ProjectId.newBuilder() - .setId(uuid) + .setId(newUuid()) .build(); } @@ -144,7 +145,7 @@ public static class GivenEvent { private GivenEvent() {} private static TestEventFactory eventFactory() { - final TestEventFactory result = + TestEventFactory result = TestEventFactory.newInstance(pack(PROJECT_ID), GivenEvent.class); return result; } @@ -154,66 +155,67 @@ public static Event projectCreated() { } public static Event projectStarted() { - final ProjectStarted msg = GivenEventMessage.projectStarted(); - final Event event = eventFactory().createEvent(msg); + ProjectStarted msg = GivenEventMessage.projectStarted(); + Event event = eventFactory().createEvent(msg); return event; } public static Event projectCreated(ProjectId projectId) { - final ProjectCreated msg = GivenEventMessage.projectCreated(projectId); - final Event event = eventFactory().createEvent(msg); + ProjectCreated msg = GivenEventMessage.projectCreated(projectId); + Event event = eventFactory().createEvent(msg); return event; } public static Event permissionGranted() { - final PermissionGrantedEvent message = GivenEventMessage.permissionGranted(); - final Event permissionGranted = createGenericEvent(message); + PermissionGrantedEvent message = GivenEventMessage.permissionGranted(); + Event permissionGranted = createGenericEvent(message); return permissionGranted; } public static Event permissionRevoked() { - final PermissionRevokedEvent message = GivenEventMessage.permissionRevoked(); - final Event permissionRevoked = createGenericEvent(message); + PermissionRevokedEvent message = GivenEventMessage.permissionRevoked(); + Event permissionRevoked = createGenericEvent(message); return permissionRevoked; } public static Event sharingRequestApproved() { - final SharingRequestApproved message = GivenEventMessage.sharingRequestApproved(); - final Event sharingRequestApproved = createGenericEvent(message); + SharingRequestApproved message = GivenEventMessage.sharingRequestApproved(); + Event sharingRequestApproved = createGenericEvent(message); return sharingRequestApproved; } private static Event createGenericEvent(Message eventMessage) { - final Any wrappedMessage = pack(eventMessage); - final Event permissionRevoked = eventFactory().createEvent(wrappedMessage); + Any wrappedMessage = pack(eventMessage); + Event permissionRevoked = eventFactory().createEvent(wrappedMessage); return permissionRevoked; } } public static class Enrichment { - private Enrichment() {} + private Enrichment() { + } /** Creates a new enricher with all required enrichment functions set. */ public static EventEnricher newEventEnricher() { - final EventEnricher.Builder builder = EventEnricher.newBuilder(); - builder.add(ProjectId.class, String.class, new GetProjectName()) - .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) - .add(EventId.class, String.class, EVENT_ID_TO_STRING) - .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) - .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) - .add(Any.class, String.class, ANY_TO_STRING) - .add(Integer.class, String.class, VERSION_TO_STRING) - .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) - .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) - .add(String.class, Integer.class, STRING_TO_INT); + EventEnricher.Builder builder = EventEnricher + .newBuilder() + .add(ProjectId.class, String.class, new GetProjectName()) + .add(ProjectId.class, UserId.class, new GetProjectOwnerId()) + .add(EventId.class, String.class, EVENT_ID_TO_STRING) + .add(Timestamp.class, String.class, TIMESTAMP_TO_STRING) + .add(CommandContext.class, String.class, CMD_CONTEXT_TO_STRING) + .add(Any.class, String.class, ANY_TO_STRING) + .add(Integer.class, String.class, VERSION_TO_STRING) + .add(String.class, ZoneOffset.class, STRING_TO_ZONE_OFFSET) + .add(String.class, PersonName.class, STRING_TO_PERSON_NAME) + .add(String.class, Integer.class, STRING_TO_INT); return builder.build(); } public static class GetProjectName implements Function { - @Nullable @Override - public String apply(@Nullable ProjectId id) { + public @Nullable String apply(@Nullable ProjectId id) { checkNotNull(id); final String name = "prj_" + id.getId(); return name; @@ -221,9 +223,8 @@ public String apply(@Nullable ProjectId id) { } public static class GetProjectOwnerId implements Function { - @Nullable @Override - public UserId apply(@Nullable ProjectId id) { + public @Nullable UserId apply(@Nullable ProjectId id) { checkNotNull(id); return GivenUserId.of("po_" + id.getId()); } @@ -231,78 +232,31 @@ public UserId apply(@Nullable ProjectId id) { private static final Function EVENT_ID_TO_STRING = new Function() { - @Nullable @Override - public String apply(@Nullable EventId input) { + public @Nullable String apply(@Nullable EventId input) { checkNotNull(input); return input.getValue(); } }; private static final Function TIMESTAMP_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Timestamp input) { - checkNotNull(input); - return input.toString(); - } - }; + AbstractMessage::toString; private static final Function CMD_CONTEXT_TO_STRING = - new Function() { - @Override - public String apply(@Nullable CommandContext input) { - return checkNotNull(input).toString(); - } - }; + input -> checkNotNull(input).toString(); private static final Function ANY_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Any input) { - return checkNotNull(input).toString(); - } - }; + input -> checkNotNull(input).toString(); private static final Function VERSION_TO_STRING = - new Function() { - @Override - public String apply(@Nullable Integer input) { - return checkNotNull(input).toString(); - } - }; + input -> checkNotNull(input).toString(); private static final Function STRING_TO_ZONE_OFFSET = - new Function() { - @Nullable - @Override - public ZoneOffset apply(@Nullable String input) { - checkNotNull(input); - return ZoneOffset.newBuilder() - .setId(ZoneId.newBuilder() - .setValue(input)) - .build(); - } - }; + new StringToZoneOffset(); private static final Function STRING_TO_PERSON_NAME = - new Function() { - @Nullable - @Override - public PersonName apply(@Nullable String input) { - checkNotNull(input); - return PersonName.newBuilder() - .setFamilyName(input) - .build(); - } - }; + new StringToPersonName(); - private static final Function STRING_TO_INT = - new Function() { - @Override - public Integer apply(@Nullable String input) { - return 0; - } - }; + private static final Function STRING_TO_INT = Integer::valueOf; } } diff --git a/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java b/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java index 70c0f905cfd..5071e30212d 100644 --- a/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java +++ b/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java @@ -54,6 +54,27 @@ public class DefaultStateRegistryShould { private DefaultStateRegistry registry; private Map spyMap; + private static void runParallel(Collection> tasks) { + ExecutorService executor = + Executors.newFixedThreadPool(Runtime.getRuntime() + .availableProcessors() * 2); + try { + executor.invokeAll(tasks); + } catch (InterruptedException ignored) { + } + } + + private static void injectField(Object target, String fieldName, Object valueToInject) { + try { + Field defaultStates = target.getClass() + .getDeclaredField(fieldName); + defaultStates.setAccessible(true); + defaultStates.set(target, valueToInject); + } catch (NoSuchFieldException | IllegalAccessException ignored) { + fail("Field " + fieldName + " should exist"); + } + } + @Before public void setUp() { spyMap = spy(newConcurrentMap()); @@ -61,70 +82,50 @@ public void setUp() { injectField(registry, DEFAULT_STATES_FIELD_NAME, spyMap); } + @SuppressWarnings("CheckReturnValue") + /* We ignore the result of the getDefaultState() because we check the calls to the registry + via spies. */ @Test - public void verify_put_invoked_one_time_when_invoke_get_default_state_in_multithreaded_environment() { - final int numberOfEntities = 1000; - final Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); + public void invoke_put_once_when_calling_getDefaultState_in_multithreaded_environment() { + int numberOfEntities = 1000; + Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); for (int i = 0; i < numberOfEntities; i++) { - tasks.add(Executors.callable(new Runnable() { - @Override - public void run() { - final TestEntity testEntity = Given.entityOfClass(TestEntity.class) - .build(); - testEntity.getDefaultState(); - } + tasks.add(Executors.callable(() -> { + TestEntity testEntity = Given.entityOfClass(TestEntity.class) + .build(); + testEntity.getDefaultState(); })); } - executeInMultithreadedEnvironment(tasks); + runParallel(tasks); - final int expected = 1; + int expected = 1; verify(spyMap, times(expected)).put(any(), any()); assertEquals(expected, spyMap.size()); } + @SuppressWarnings("CheckReturnValue") + /* We ignore the result of the getDefaultState() because we check the calls to the registry + via spies. */ @Test - public void verify_put_invoked_one_time_when_invoke_put_or_get_in_multithreaded_environment() { - final int numberOfEntities = 1000; - final Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); + public void invoke_put_once_when_calling_putOrGet_in_multithreaded_environment() { + int numberOfEntities = 1000; + Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); for (int i = 0; i < numberOfEntities; i++) { - tasks.add(Executors.callable(new Runnable() { - @Override - public void run() { - registry.putOrGet(TimerSnapshot.class); - } + tasks.add(Executors.callable(() -> { + registry.get(TimerSnapshot.class); })); } - executeInMultithreadedEnvironment(tasks); + runParallel(tasks); - final int expected = 1; + int expected = 1; verify(spyMap, times(expected)).put(any(), any()); assertEquals(expected, spyMap.size()); } - private void executeInMultithreadedEnvironment(Collection> tasks) { - final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime() - .availableProcessors() * - 2); - try { - executor.invokeAll(tasks); - } catch (InterruptedException ignored) { - } - } - - private void injectField(Object target, String fieldName, Object valueToInject) { - try { - final Field defaultStates = target.getClass() - .getDeclaredField(fieldName); - defaultStates.setAccessible(true); - defaultStates.set(target, valueToInject); - } catch (NoSuchFieldException | IllegalAccessException ignored) { - fail("Field " + fieldName + " should exist"); - } - } - private static class TimerSnapshot extends AbstractEntity { + protected TimerSnapshot(Long id) { super(id); } diff --git a/server/src/test/java/io/spine/server/model/HandlerMethodShould.java b/server/src/test/java/io/spine/server/model/HandlerMethodShould.java index 5e74776bac4..7a725172318 100644 --- a/server/src/test/java/io/spine/server/model/HandlerMethodShould.java +++ b/server/src/test/java/io/spine/server/model/HandlerMethodShould.java @@ -28,14 +28,14 @@ import io.spine.core.EventContext; import io.spine.test.Tests; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; @@ -47,9 +47,11 @@ public class HandlerMethodShould { private final HandlerMethod.Factory factory = OneParamMethod.factory(); + @Rule + public ExpectedException thrown = ExpectedException.none(); + private HandlerMethod twoParamMethod; private HandlerMethod oneParamMethod; - private Object target; @Before @@ -59,10 +61,10 @@ public void setUp() { oneParamMethod = new OneParamMethod(StubHandler.getOneParameterMethod()); } - @Test(expected = NullPointerException.class) + @Test public void do_not_accept_null_method() { - //noinspection ResultOfObjectAllocationIgnored - new TwoParamMethod(Tests.nullRef()); + thrown.expect(NullPointerException.class); + new TwoParamMethod(Tests.nullRef()); } @Test @@ -85,8 +87,9 @@ public void return_first_param_type() { assertEquals(BoolValue.class, HandlerMethod.getFirstParamType(oneParamMethod.getMethod())); } + @SuppressWarnings("CheckReturnValue") // can ignore the result in this test @Test - public void invoke_the_method_with_two_parameters() throws InvocationTargetException { + public void invoke_the_method_with_two_parameters() { twoParamMethod.invoke(target, StringValue.getDefaultInstance(), EventContext.getDefaultInstance()); @@ -94,8 +97,9 @@ public void invoke_the_method_with_two_parameters() throws InvocationTargetExcep assertTrue(((StubHandler) target).wasOnInvoked()); } + @SuppressWarnings("CheckReturnValue") // can ignore the result in this test @Test - public void invoke_the_method_with_one_parameter() throws InvocationTargetException { + public void invoke_the_method_with_one_parameter() { oneParamMethod.invoke(target, BoolValue.getDefaultInstance(), Empty.getDefaultInstance()); assertTrue(((StubHandler) target).wasHandleInvoked()); @@ -108,28 +112,25 @@ public void return_full_name_in_toString() { @Test public void be_equal_to_itself() { - //noinspection EqualsWithItself - assertTrue(twoParamMethod.equals(twoParamMethod)); + assertEquals(twoParamMethod, twoParamMethod); } @Test public void be_not_equal_to_null() { - //noinspection ObjectEqualsNull - assertFalse(oneParamMethod.equals(null)); + assertNotEquals(null, oneParamMethod); } @Test public void be_not_equal_to_another_class_instance() { - //noinspection EqualsBetweenInconvertibleTypes - assertFalse(twoParamMethod.equals(oneParamMethod)); + assertNotEquals(twoParamMethod, oneParamMethod); } @Test public void compare_fields_in_equals() { - final HandlerMethod anotherMethod = + HandlerMethod anotherMethod = new TwoParamMethod(StubHandler.getTwoParameterMethod()); - assertTrue(twoParamMethod.equals(anotherMethod)); + assertEquals(twoParamMethod, anotherMethod); } @Test @@ -137,15 +138,15 @@ public void have_hashCode() { assertNotEquals(System.identityHashCode(twoParamMethod), twoParamMethod.hashCode()); } - @SuppressWarnings("ResultOfMethodCallIgnored") // Method is called only to throw exception. - @Test(expected = IllegalStateException.class) + @Test public void do_not_be_created_from_method_with_checked_exception() { + thrown.expect(IllegalStateException.class); factory.create(StubHandler.getMethodWithCheckedException()); } @Test public void be_normally_created_from_method_with_runtime_exception() { - final OneParamMethod method = factory.create(StubHandler.getMethodWithRuntimeException()); + OneParamMethod method = factory.create(StubHandler.getMethodWithRuntimeException()); assertEquals(StubHandler.getMethodWithRuntimeException(), method.getMethod()); } @@ -159,15 +160,6 @@ private static class StubHandler { private boolean onInvoked; private boolean handleInvoked; - public void on(StringValue message, EventContext context) { - onInvoked = true; - } - - @SuppressWarnings("unused") // The method is used via reflection. - private void handle(BoolValue message) { - handleInvoked = true; - } - private static void throwCheckedException(BoolValue message) throws Exception { throw new IOException("Throw new checked exception"); } @@ -177,8 +169,8 @@ private static void throwRuntimeException(BoolValue message) throws RuntimeExcep } private static Method getTwoParameterMethod() { - final Method method; - final Class clazz = StubHandler.class; + Method method; + Class clazz = StubHandler.class; try { method = clazz.getMethod("on", StringValue.class, EventContext.class); } catch (NoSuchMethodException e) { @@ -188,8 +180,8 @@ private static Method getTwoParameterMethod() { } private static Method getOneParameterMethod() { - final Method method; - final Class clazz = StubHandler.class; + Method method; + Class clazz = StubHandler.class; try { method = clazz.getDeclaredMethod("handle", BoolValue.class); } catch (NoSuchMethodException e) { @@ -199,8 +191,8 @@ private static Method getOneParameterMethod() { } private static Method getMethodWithCheckedException() { - final Method method; - final Class clazz = StubHandler.class; + Method method; + Class clazz = StubHandler.class; try { method = clazz.getDeclaredMethod("throwCheckedException", BoolValue.class); } catch (NoSuchMethodException e) { @@ -210,8 +202,8 @@ private static Method getMethodWithCheckedException() { } private static Method getMethodWithRuntimeException() { - final Method method; - final Class clazz = StubHandler.class; + Method method; + Class clazz = StubHandler.class; try { method = clazz.getDeclaredMethod("throwRuntimeException", BoolValue.class); } catch (NoSuchMethodException e) { @@ -220,6 +212,15 @@ private static Method getMethodWithRuntimeException() { return method; } + public void on(StringValue message, EventContext context) { + onInvoked = true; + } + + @SuppressWarnings("unused") // The method is used via reflection. + private void handle(BoolValue message) { + handleInvoked = true; + } + private boolean wasOnInvoked() { return onInvoked; } @@ -252,18 +253,11 @@ private OneParamMethod(Method method) { super(method); } - @Override - public EventClass getMessageClass() { - return EventClass.of(rawMessageClass()); - } - - @Override - public HandlerKey key() { - throw new IllegalStateException("The method is not a target of the test."); - } - public static Factory factory() { return Factory.getInstance(); + } @Override + public EventClass getMessageClass() { + return EventClass.of(rawMessageClass()); } private static class Factory extends HandlerMethod.Factory { @@ -293,6 +287,9 @@ public void checkAccessModifier(Method method) { protected OneParamMethod createFromMethod(Method method) { return new OneParamMethod(method); } + } @Override + public HandlerKey key() { + throw new IllegalStateException("The method is not a target of the test."); } } } diff --git a/server/src/test/java/io/spine/server/model/ModelShould.java b/server/src/test/java/io/spine/server/model/ModelShould.java index b8e0df809dd..373c25eaa4f 100644 --- a/server/src/test/java/io/spine/server/model/ModelShould.java +++ b/server/src/test/java/io/spine/server/model/ModelShould.java @@ -49,6 +49,7 @@ public void setUp() { model.clear(); } + @SuppressWarnings("CheckReturnValue") // returned values are not used in this test @Test public void not_allow_duplicated_command_handlers() { try { @@ -62,6 +63,7 @@ public void not_allow_duplicated_command_handlers() { } } + @SuppressWarnings("CheckReturnValue") // returned values are not used in this test @Test public void not_allow_more_than_one_command_duplication() { try { @@ -78,12 +80,12 @@ public void not_allow_more_than_one_command_duplication() { @Test public void return_default_state_for_entity_class() { - final Message defaultState = model.getDefaultState(MAggregate.class); + Message defaultState = model.getDefaultState(MAggregate.class); assertNotNull("Default state cannot be null for the entity class.", defaultState); } private static void assertContainsClassName(DuplicateCommandHandlerError error, Class cls) { - final String errorMessage = error.getMessage(); + String errorMessage = error.getMessage(); assertTrue(errorMessage.contains(cls.getName())); } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java index 57f72616c48..2bc46da05d3 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/StringToZoneOffset.java @@ -32,7 +32,7 @@ * * @author Alexander Yevsyukov */ -class StringToZoneOffset implements Function { +public class StringToZoneOffset implements Function { @Override public @Nullable ZoneOffset apply(@Nullable String input) { return input == null diff --git a/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java b/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java index 04bbcc29eda..f27dd8ced7a 100644 --- a/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java +++ b/server/src/test/java/io/spine/server/procman/AbstractCommandRouterShould.java @@ -20,9 +20,7 @@ package io.spine.server.procman; -import com.google.common.base.Function; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import com.google.protobuf.Any; import com.google.protobuf.Message; import com.google.protobuf.StringValue; @@ -38,9 +36,9 @@ import io.spine.server.commandbus.CommandDispatcher; import org.junit.Before; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import static io.spine.core.Commands.sameActorAndTenant; import static io.spine.protobuf.TypeConverter.toMessage; @@ -142,15 +140,8 @@ protected void assertActorAndTenant(Command produced) { } static List unpackAll(List anyList) { - return Lists.transform(anyList, new Function() { - @Nullable - @Override - public StringValue apply(@Nullable Any input) { - if (input == null) { - return null; - } - return AnyPacker.unpack(input); - } - }); + return anyList.stream() + .map(AnyPacker::unpack) + .collect(Collectors.toList()); } } diff --git a/server/src/test/java/io/spine/server/procman/CommandRouterOnErrorShould.java b/server/src/test/java/io/spine/server/procman/CommandRouterOnErrorShould.java index fbc1863fdcb..47b774adcdb 100644 --- a/server/src/test/java/io/spine/server/procman/CommandRouterOnErrorShould.java +++ b/server/src/test/java/io/spine/server/procman/CommandRouterOnErrorShould.java @@ -29,7 +29,9 @@ import io.spine.server.BoundedContext; import io.spine.server.commandbus.CommandBus; import io.spine.server.commandbus.CommandDispatcher; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Set; @@ -40,6 +42,9 @@ */ public class CommandRouterOnErrorShould extends AbstractCommandRouterShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + /** * Creates a router with mocked {@code CommandBus} which always calls * {@link StreamObserver#onError(Throwable) StreamObserver.onError()} when @@ -52,11 +57,11 @@ CommandRouter createRouter(CommandBus commandBus, return new CommandRouter(commandBus, sourceMessage, commandContext); } - @Test(expected = IllegalStateException.class) + @Test public void throw_IllegalStateException_when_caught_error_when_posting() { - final BoundedContext boundedContext = BoundedContext.newBuilder() - .build(); - final CommandBus commandBus = boundedContext.getCommandBus(); + BoundedContext boundedContext = BoundedContext.newBuilder() + .build(); + CommandBus commandBus = boundedContext.getCommandBus(); // Register dispatcher for `StringValue` message type. // Fails each time of dispatch(). @@ -77,12 +82,13 @@ public void onError(CommandEnvelope envelope, RuntimeException exception) { } }); - final StringValue sourceMessage = toMessage(getClass().getSimpleName()); - final CommandContext sourceContext = getRequestFactory().createCommandContext(); + StringValue sourceMessage = toMessage(getClass().getSimpleName()); + CommandContext sourceContext = getRequestFactory().createCommandContext(); - final CommandRouter router = createRouter(commandBus, sourceMessage, sourceContext); + CommandRouter router = createRouter(commandBus, sourceMessage, sourceContext); router.addAll(getMessages()); + thrown.expect(IllegalStateException.class); router.routeAll(); } } diff --git a/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java b/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java index 00b6b35e7bb..14a32905e42 100644 --- a/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java +++ b/server/src/test/java/io/spine/server/procman/ProcessManagerRepositoryShould.java @@ -63,12 +63,13 @@ import io.spine.test.procman.event.PmProjectCreated; import io.spine.test.procman.event.PmProjectStarted; import io.spine.test.procman.event.PmTaskAdded; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; -import org.checkerframework.checker.nullness.qual.Nullable; -import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Set; @@ -107,6 +108,8 @@ public class ProcessManagerRepositoryShould TenantId.newBuilder() .setValue(newUuid()) .build()); + @Rule + public ExpectedException thrown = ExpectedException.none(); private BoundedContext boundedContext; @Override @@ -172,26 +175,35 @@ ProcessManagerRepository repository() { return (ProcessManagerRepository) repository; } - private void testDispatchCommand(Message cmdMsg) throws InvocationTargetException { - final Command cmd = requestFactory.command() - .create(cmdMsg); - repository().dispatchCommand(CommandEnvelope.of(cmd)); + @SuppressWarnings("CheckReturnValue") + // We can ignore the ID of the PM handling the command in the calling tests. + private void dispatchCommand(Command command) { + repository().dispatchCommand(CommandEnvelope.of(command)); + } + + private void testDispatchCommand(Message cmdMsg) { + Command cmd = requestFactory.command() + .create(cmdMsg); + dispatchCommand(cmd); assertTrue(TestProcessManager.processed(cmdMsg)); } + @SuppressWarnings("CheckReturnValue") // can ignore IDs of target PMs in this test. private void testDispatchEvent(Message eventMessage) { - final CommandContext commandContext = requestFactory.createCommandContext(); + CommandContext commandContext = requestFactory.createCommandContext(); // EventContext should have CommandContext with appropriate TenantId to avoid usage // of different storages during command and event dispatching. - final EventContext eventContextWithTenantId = GivenEvent.context() - .toBuilder() - .setCommandContext(commandContext) - .build(); - final Event event = GivenEvent.withMessage(eventMessage) - .toBuilder() - .setContext(eventContextWithTenantId) - .build(); + EventContext eventContextWithTenantId = + GivenEvent.context() + .toBuilder() + .setCommandContext(commandContext) + .build(); + Event event = + GivenEvent.withMessage(eventMessage) + .toBuilder() + .setContext(eventContextWithTenantId) + .build(); repository().dispatch(EventEnvelope.of(event)); assertTrue(TestProcessManager.processed(eventMessage)); } @@ -209,18 +221,18 @@ public void dispatch_several_events() { } @Test - public void dispatch_event_to_archived_process_manager() throws InvocationTargetException { - final PmArchiveProcess archiveProcess = archiveProcess(); + public void dispatch_event_to_archived_process_manager() { + PmArchiveProcess archiveProcess = archiveProcess(); testDispatchCommand(archiveProcess); - final ProjectId projectId = archiveProcess.getProjectId(); + ProjectId projectId = archiveProcess.getProjectId(); TestProcessManager processManager = repository().findOrCreate(projectId); assertTrue(processManager.isArchived()); // Dispatch an event to the archived process manager. testDispatchEvent(taskAdded()); processManager = repository().findOrCreate(projectId); - final List addedTasks = processManager.getState() - .getTaskList(); + List addedTasks = processManager.getState() + .getTaskList(); assertFalse(addedTasks.isEmpty()); // Check that the process manager was not re-created before dispatching. @@ -228,18 +240,18 @@ public void dispatch_event_to_archived_process_manager() throws InvocationTarget } @Test - public void dispatch_event_to_deleted_process_manager() throws InvocationTargetException { - final PmDeleteProcess deleteProcess = deleteProcess(); + public void dispatch_event_to_deleted_process_manager() { + PmDeleteProcess deleteProcess = deleteProcess(); testDispatchCommand(deleteProcess); - final ProjectId projectId = deleteProcess.getProjectId(); + ProjectId projectId = deleteProcess.getProjectId(); TestProcessManager processManager = repository().findOrCreate(projectId); assertTrue(processManager.isDeleted()); // Dispatch an event to the deleted process manager. testDispatchEvent(taskAdded()); processManager = repository().findOrCreate(projectId); - final List addedTasks = processManager.getState() - .getTaskList(); + List addedTasks = processManager.getState() + .getTaskList(); assertFalse(addedTasks.isEmpty()); // Check that the process manager was not re-created before dispatching. @@ -247,30 +259,30 @@ public void dispatch_event_to_deleted_process_manager() throws InvocationTargetE } @Test - public void dispatch_command() throws InvocationTargetException { + public void dispatch_command() { testDispatchCommand(addTask()); } @Test - public void dispatch_several_commands() throws InvocationTargetException { + public void dispatch_several_commands() { testDispatchCommand(createProject()); testDispatchCommand(addTask()); testDispatchCommand(startProject()); } @Test - public void dispatch_command_to_archived_process_manager() throws InvocationTargetException { - final PmDeleteProcess deleteProcess = deleteProcess(); + public void dispatch_command_to_archived_process_manager() { + PmDeleteProcess deleteProcess = deleteProcess(); testDispatchCommand(deleteProcess); - final ProjectId projectId = deleteProcess.getProjectId(); + ProjectId projectId = deleteProcess.getProjectId(); TestProcessManager processManager = repository().findOrCreate(projectId); assertTrue(processManager.isDeleted()); // Dispatch a command to the deleted process manager. testDispatchCommand(addTask()); processManager = repository().findOrCreate(projectId); - final List addedTasks = processManager.getState() - .getTaskList(); + List addedTasks = processManager.getState() + .getTaskList(); assertFalse(addedTasks.isEmpty()); // Check that the process manager was not re-created before dispatching. @@ -278,18 +290,18 @@ public void dispatch_command_to_archived_process_manager() throws InvocationTarg } @Test - public void dispatch_command_to_deleted_process_manager() throws InvocationTargetException { - final PmArchiveProcess archiveProcess = archiveProcess(); + public void dispatch_command_to_deleted_process_manager() { + PmArchiveProcess archiveProcess = archiveProcess(); testDispatchCommand(archiveProcess); - final ProjectId projectId = archiveProcess.getProjectId(); + ProjectId projectId = archiveProcess.getProjectId(); TestProcessManager processManager = repository().findOrCreate(projectId); assertTrue(processManager.isArchived()); // Dispatch a command to the archived process manager. testDispatchCommand(addTask()); processManager = repository().findOrCreate(projectId); - final List addedTasks = processManager.getState() - .getTaskList(); + List addedTasks = processManager.getState() + .getTaskList(); assertFalse(addedTasks.isEmpty()); // Check that the process manager was not re-created before dispatching. @@ -297,35 +309,35 @@ public void dispatch_command_to_deleted_process_manager() throws InvocationTarge } @Test - public void allow_ProcMan_have_unmodified_state_after_command_handling() - throws InvocationTargetException { + public void allow_ProcMan_have_unmodified_state_after_command_handling() { testDispatchCommand(doNothing()); } @Test - public void dispatch_command_and_post_events() throws InvocationTargetException { - final RememberingSubscriber subscriber = new RememberingSubscriber(); + public void dispatch_command_and_post_events() { + RememberingSubscriber subscriber = new RememberingSubscriber(); boundedContext.getEventBus() .register(subscriber); testDispatchCommand(addTask()); - final PmTaskAdded message = subscriber.remembered; + PmTaskAdded message = subscriber.remembered; assertNotNull(message); assertEquals(ID, message.getProjectId()); } - @Test(expected = IllegalArgumentException.class) + @Test public void throw_exception_if_dispatch_unknown_command() { - final Command unknownCommand = + Command unknownCommand = requestFactory.createCommand(Int32Value.getDefaultInstance()); - final CommandEnvelope request = CommandEnvelope.of(unknownCommand); + CommandEnvelope request = CommandEnvelope.of(unknownCommand); + thrown.expect(IllegalArgumentException.class); repository().dispatchCommand(request); } @Test public void return_command_classes() { - final Set commandClasses = repository().getCommandClasses(); + Set commandClasses = repository().getCommandClasses(); assertContains(commandClasses, PmCreateProject.class, PmCreateProject.class, PmStartProject.class); @@ -333,7 +345,7 @@ public void return_command_classes() { @Test public void return_event_classes() { - final Set eventClasses = repository().getMessageClasses(); + Set eventClasses = repository().getMessageClasses(); assertContains(eventClasses, PmProjectCreated.class, PmTaskAdded.class, PmProjectStarted.class); @@ -341,7 +353,7 @@ public void return_event_classes() { @Test public void return_rejection_classes() { - final Set rejectionClasses = repository().getRejectionClasses(); + Set rejectionClasses = repository().getRejectionClasses(); assertContains(rejectionClasses, EntityAlreadyArchived.class, EntityAlreadyDeleted.class); @@ -349,16 +361,16 @@ public void return_rejection_classes() { @Test public void post_command_rejections() { - final ProjectId id = ProjectId.newBuilder() - .setId(newUuid()) - .build(); - final PmThrowEntityAlreadyArchived commandMsg = + ProjectId id = ProjectId.newBuilder() + .setId(newUuid()) + .build(); + PmThrowEntityAlreadyArchived commandMsg = PmThrowEntityAlreadyArchived.newBuilder() .setProjectId(id) .build(); - final Command command = requestFactory.createCommand(commandMsg); - repository().dispatchCommand(CommandEnvelope.of(command)); - final StandardRejections.EntityAlreadyArchived expected = + Command command = requestFactory.createCommand(commandMsg); + dispatchCommand(command); + StandardRejections.EntityAlreadyArchived expected = StandardRejections.EntityAlreadyArchived.newBuilder() .setEntityId(AnyPacker.pack(id)) .build(); @@ -367,35 +379,36 @@ public void post_command_rejections() { @Test public void dispatch_rejection() { - final CommandEnvelope ce = requestFactory.generateEnvelope(); - final EntityAlreadyArchived rejectionMessage = + CommandEnvelope ce = requestFactory.generateEnvelope(); + EntityAlreadyArchived rejectionMessage = EntityAlreadyArchived.newBuilder() .setEntityId(Identifier.pack(newUuid())) .build(); - final Rejection rejection = createRejection(rejectionMessage, - ce.getCommand()); - final ProjectId id = ProcessManagerRepositoryTestEnv.GivenCommandMessage.ID; - final Rejection.Builder builder = + Rejection rejection = createRejection(rejectionMessage, + ce.getCommand()); + ProjectId id = ProcessManagerRepositoryTestEnv.GivenCommandMessage.ID; + Rejection.Builder builder = rejection.toBuilder() .setContext(rejection.getContext() .toBuilder() .setProducerId(Identifier.pack(id))); - final RejectionEnvelope re = RejectionEnvelope.of(builder.build()); + RejectionEnvelope re = RejectionEnvelope.of(builder.build()); - final Set delivered = repository().dispatchRejection(re); + Set delivered = repository().dispatchRejection(re); assertTrue(delivered.contains(id)); assertTrue(TestProcessManager.processed(rejectionMessage)); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_on_attempt_to_register_in_bc_with_no_messages_handled() { - final SensoryDeprivedPmRepository repo = new SensoryDeprivedPmRepository(); - final BoundedContext boundedContext = BoundedContext.newBuilder() - .setMultitenant(false) - .build(); + SensoryDeprivedPmRepository repo = new SensoryDeprivedPmRepository(); + BoundedContext boundedContext = BoundedContext.newBuilder() + .setMultitenant(false) + .build(); repo.setBoundedContext(boundedContext); + thrown.expect(IllegalStateException.class); repo.onRegistered(); } @@ -404,8 +417,7 @@ public void throw_exception_on_attempt_to_register_in_bc_with_no_messages_handle */ private static class RememberingSubscriber extends EventSubscriber { - @Nullable - private PmTaskAdded remembered; + private @Nullable PmTaskAdded remembered; @Subscribe void on(PmTaskAdded msg) { diff --git a/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java b/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java index b81478f7541..cf9d808cee8 100644 --- a/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java +++ b/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java @@ -20,6 +20,7 @@ package io.spine.server.procman; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.Int32Value; import com.google.protobuf.Message; @@ -57,7 +58,9 @@ import io.spine.test.procman.event.PmTaskAdded; import io.spine.testdata.Sample; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.List; @@ -88,23 +91,52 @@ public class ProcessManagerShould { private final TestEventFactory eventFactory = TestEventFactory.newInstance(Identifier.pack(ID), getClass()); - private final TestActorRequestFactory requestFactory = TestActorRequestFactory.newInstance(getClass()); + @Rule + public ExpectedException thrown = ExpectedException.none(); private CommandBus commandBus; - private TestProcessManager processManager; + private static PmCreateProject createProject() { + return ((PmCreateProject.Builder) Sample.builderForType(PmCreateProject.class)) + .setProjectId(ID) + .build(); + } + + private static PmStartProject startProject() { + return ((PmStartProject.Builder) Sample.builderForType(PmStartProject.class)) + .setProjectId(ID) + .build(); + } + + private static PmAddTask addTask() { + return ((PmAddTask.Builder) Sample.builderForType(PmAddTask.class)) + .setProjectId(ID) + .build(); + } + + private static RejectionEnvelope entityAlreadyArchived( + Class commandMessageCls) { + Any id = Identifier.pack(ProcessManagerShould.class.getName()); + EntityAlreadyArchived rejectionMessage = EntityAlreadyArchived.newBuilder() + .setEntityId(id) + .build(); + Command command = ACommand.withMessage(Sample.messageOfType(commandMessageCls)); + Rejection rejection = Rejections.createRejection(rejectionMessage, command); + return RejectionEnvelope.of(rejection); + } + @Before public void setUp() { ModelTests.clearModel(); - final BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(true) - .build(); - final StorageFactory storageFactory = bc.getStorageFactory(); - final TenantIndex tenantIndex = TenantAwareTest.createTenantIndex(false, storageFactory); - final CommandStore commandStore = spy( + BoundedContext bc = BoundedContext.newBuilder() + .setMultitenant(true) + .build(); + StorageFactory storageFactory = bc.getStorageFactory(); + TenantIndex tenantIndex = TenantAwareTest.createTenantIndex(false, storageFactory); + CommandStore commandStore = spy( new CommandStore(storageFactory, tenantIndex) ); @@ -118,6 +150,23 @@ public void setUp() { .build(); } + @CanIgnoreReturnValue + private List testDispatchEvent(Message eventMessage) { + Event event = eventFactory.createEvent(eventMessage); + List result = dispatch(processManager, EventEnvelope.of(event)); + assertEquals(pack(eventMessage), processManager.getState()); + return result; + } + + @CanIgnoreReturnValue + private List testDispatchCommand(Message commandMsg) { + CommandEnvelope envelope = CommandEnvelope.of(requestFactory.command() + .create(commandMsg)); + List events = dispatch(processManager, envelope); + assertEquals(pack(commandMsg), processManager.getState()); + return events; + } + @Test public void have_default_state_initially() { assertEquals(processManager.getDefaultState(), processManager.getState()); @@ -125,7 +174,7 @@ public void have_default_state_initially() { @Test public void dispatch_event() { - final List eventMessages = + List eventMessages = testDispatchEvent(Sample.messageOfType(PmProjectStarted.class)); assertEquals(1, eventMessages.size()); @@ -139,13 +188,6 @@ public void dispatch_several_events() { testDispatchEvent(Sample.messageOfType(PmProjectStarted.class)); } - private List testDispatchEvent(Message eventMessage) { - final Event event = eventFactory.createEvent(eventMessage); - final List result = dispatch(processManager, EventEnvelope.of(event)); - assertEquals(pack(eventMessage), processManager.getState()); - return result; - } - @Test public void dispatch_command() { testDispatchCommand(addTask()); @@ -161,22 +203,14 @@ public void dispatch_several_commands() { testDispatchCommand(startProject()); } - private List testDispatchCommand(Message commandMsg) { - final CommandEnvelope envelope = CommandEnvelope.of(requestFactory.command() - .create(commandMsg)); - final List events = dispatch(processManager, envelope); - assertEquals(pack(commandMsg), processManager.getState()); - return events; - } - @Test public void dispatch_command_and_return_events() { - final List events = testDispatchCommand(createProject()); + List events = testDispatchCommand(createProject()); assertEquals(1, events.size()); - final Event event = events.get(0); + Event event = events.get(0); assertNotNull(event); - final PmProjectCreated message = unpack(event.getMessage()); + PmProjectCreated message = unpack(event.getMessage()); assertEquals(ID, message.getProjectId()); } @@ -188,56 +222,60 @@ public void dispatch_command_and_return_events() { @Test public void route_commands() { // Add dispatcher for the routed command. Otherwise the command would reject the command. - final AddTaskDispatcher dispatcher = new AddTaskDispatcher(); + AddTaskDispatcher dispatcher = new AddTaskDispatcher(); commandBus.register(dispatcher); processManager.injectCommandBus(commandBus); - final List events = testDispatchCommand(startProject()); + List events = testDispatchCommand(startProject()); // There's only one event generated. assertEquals(1, events.size()); - final Event event = events.get(0); + Event event = events.get(0); // The producer of the event is our Process Manager. assertEquals(processManager.getId(), Events.getProducer(event.getContext())); - final Message message = AnyPacker.unpack(event.getMessage()); + Message message = AnyPacker.unpack(event.getMessage()); // The event type is CommandRouted. assertThat(message, instanceOf(CommandRouted.class)); - final CommandRouted commandRouted = (CommandRouted) message; + CommandRouted commandRouted = (CommandRouted) message; // The source of the command is StartProject. assertThat(getMessage(commandRouted.getSource()), instanceOf(PmStartProject.class)); - final List dispatchedCommands = dispatcher.getCommands(); + List dispatchedCommands = dispatcher.getCommands(); assertSize(1, dispatchedCommands); - final CommandEnvelope dispatchedCommand = dispatcher.getCommands() - .get(0); + CommandEnvelope dispatchedCommand = dispatcher.getCommands() + .get(0); assertEquals(commandRouted.getProduced(0), dispatchedCommand.getCommand()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_dispatch_unknown_command() { - final Int32Value unknownCommand = Int32Value.getDefaultInstance(); + Int32Value unknownCommand = Int32Value.getDefaultInstance(); - final CommandEnvelope envelope = CommandEnvelope.of( + CommandEnvelope envelope = CommandEnvelope.of( requestFactory.createCommand(unknownCommand) ); + + thrown.expect(IllegalStateException.class); processManager.dispatchCommand(envelope); } @Test(expected = IllegalStateException.class) public void throw_exception_if_dispatch_unknown_event() { - final StringValue unknownEvent = StringValue.getDefaultInstance(); - final EventEnvelope envelope = EventEnvelope.of(eventFactory.createEvent(unknownEvent)); + StringValue unknownEvent = StringValue.getDefaultInstance(); + EventEnvelope envelope = EventEnvelope.of(eventFactory.createEvent(unknownEvent)); + + thrown.expect(IllegalStateException.class); dispatch(processManager, envelope); } @Test public void dispatch_rejection_by_rejection_message_only() { - final RejectionEnvelope rejection = entityAlreadyArchived(StringValue.class); + RejectionEnvelope rejection = entityAlreadyArchived(StringValue.class); dispatch(processManager, rejection); assertEquals(rejection.getOuterObject() .getMessage(), processManager.getState()); @@ -245,19 +283,19 @@ public void dispatch_rejection_by_rejection_message_only() { @Test public void dispatch_rejection_by_rejection_and_command_message() { - final RejectionEnvelope rejection = entityAlreadyArchived(PmAddTask.class); + RejectionEnvelope rejection = entityAlreadyArchived(PmAddTask.class); dispatch(processManager, rejection); assertEquals(AnyPacker.pack(rejection.getCommandMessage()), processManager.getState()); } @Test public void create_iterating_router() { - final StringValue commandMessage = toMessage("create_iterating_router"); - final CommandContext commandContext = requestFactory.createCommandContext(); + StringValue commandMessage = toMessage("create_iterating_router"); + CommandContext commandContext = requestFactory.createCommandContext(); processManager.injectCommandBus(mock(CommandBus.class)); - final IteratingCommandRouter router + IteratingCommandRouter router = processManager.newIteratingRouterFor(commandMessage, commandContext); assertNotNull(router); @@ -267,52 +305,25 @@ public void create_iterating_router() { .getContext()); } - @Test(expected = IllegalStateException.class) + @Test public void require_command_bus_when_creating_router() { + thrown.expect(IllegalStateException.class); processManager.newRouterFor(StringValue.getDefaultInstance(), CommandContext.getDefaultInstance()); } @Test public void create_router() { - final StringValue commandMessage = toMessage("create_router"); - final CommandContext commandContext = requestFactory.createCommandContext(); + StringValue commandMessage = toMessage("create_router"); + CommandContext commandContext = requestFactory.createCommandContext(); processManager.injectCommandBus(mock(CommandBus.class)); - final CommandRouter router = processManager.newRouterFor(commandMessage, commandContext); + CommandRouter router = processManager.newRouterFor(commandMessage, commandContext); assertNotNull(router); assertEquals(commandMessage, getMessage(router.getSource())); assertEquals(commandContext, router.getSource() .getContext()); } - - private static PmCreateProject createProject() { - return ((PmCreateProject.Builder) Sample.builderForType(PmCreateProject.class)) - .setProjectId(ID) - .build(); - } - - private static PmStartProject startProject() { - return ((PmStartProject.Builder) Sample.builderForType(PmStartProject.class)) - .setProjectId(ID) - .build(); - } - - private static PmAddTask addTask() { - return ((PmAddTask.Builder) Sample.builderForType(PmAddTask.class)) - .setProjectId(ID) - .build(); - } - - private static RejectionEnvelope entityAlreadyArchived(Class commandMessageCls) { - final Any id = Identifier.pack(ProcessManagerShould.class.getName()); - final EntityAlreadyArchived rejectionMessage = EntityAlreadyArchived.newBuilder() - .setEntityId(id) - .build(); - final Command command = ACommand.withMessage(Sample.messageOfType(commandMessageCls)); - final Rejection rejection = Rejections.createRejection(rejectionMessage, command); - return RejectionEnvelope.of(rejection); - } } diff --git a/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java b/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java index dd461d75186..1b13d499dca 100644 --- a/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java +++ b/server/src/test/java/io/spine/server/procman/given/PmTransactionTestEnv.java @@ -31,8 +31,8 @@ import io.spine.test.procman.event.PmProjectCreated; import io.spine.test.procman.event.PmTaskAdded; import io.spine.validate.ConstraintViolation; - import org.checkerframework.checker.nullness.qual.Nullable; + import java.util.List; import static com.google.common.collect.Lists.newLinkedList; @@ -50,7 +50,7 @@ public static class TestProcessManager extends ProcessManager { private final List receivedEvents = newLinkedList(); - private final List violations; + private final @Nullable List violations; public TestProcessManager(ProjectId id) { this(id, null); @@ -58,7 +58,9 @@ public TestProcessManager(ProjectId id) { public TestProcessManager(ProjectId id, @Nullable List violations) { super(id); - this.violations = violations; + this.violations = violations == null + ? null + : ImmutableList.copyOf(violations); } @Override @@ -72,9 +74,9 @@ protected List checkEntityState(Project newState) { @React public Empty event(PmProjectCreated event) { receivedEvents.add(event); - final Project newState = Project.newBuilder(getState()) - .setId(event.getProjectId()) - .build(); + Project newState = Project.newBuilder(getState()) + .setId(event.getProjectId()) + .build(); getBuilder().mergeFrom(newState); return Empty.getDefaultInstance(); } diff --git a/server/src/test/java/io/spine/server/projection/ProjectionStorageShould.java b/server/src/test/java/io/spine/server/projection/ProjectionStorageShould.java index 3a2cf901c42..2d746b679ed 100644 --- a/server/src/test/java/io/spine/server/projection/ProjectionStorageShould.java +++ b/server/src/test/java/io/spine/server/projection/ProjectionStorageShould.java @@ -20,6 +20,7 @@ package io.spine.server.projection; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.FieldMask; import com.google.protobuf.Message; @@ -67,13 +68,46 @@ public abstract class ProjectionStorageShould private ProjectionStorage storage; + @SuppressWarnings("BreakStatement") + @CanIgnoreReturnValue + private static Project checkProjectIdIsInList(EntityRecord project, List ids) { + Any packedState = project.getState(); + Project state = AnyPacker.unpack(packedState); + ProjectId id = state.getId(); + + boolean isIdPresent = false; + for (ProjectId genericId : ids) { + isIdPresent = genericId.equals(id); + if (isIdPresent) { + break; + } + } + assertTrue(isIdPresent); + + return state; + } + + private static FieldMask maskForPaths(String... paths) { + FieldMask mask = FieldMask + .newBuilder() + .addAllPaths(Arrays.asList(paths)) + .build(); + return mask; + } + @Override protected Message newState(ProjectId id) { - final String uniqueName = format("Projection_name-%s-%s", id.getId(), System.nanoTime()); - final Project state = Given.project(id, uniqueName); + String uniqueName = format("Projection_name-%s-%s", id.getId(), System.nanoTime()); + Project state = Given.project(id, uniqueName); return state; } + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + protected EntityRecord newStorageRecord() { + return newEntityStorageRecord(); + } + @Override protected ProjectId newId() { return ProjectId.newBuilder() @@ -91,64 +125,55 @@ public void tearDownProjectionStorageTest() { close(storage); } - @SuppressWarnings("MethodDoesntCallSuperMethod") - @Override - protected EntityRecord newStorageRecord() { - return newEntityStorageRecord(); - } - @Test public void return_null_if_no_event_time_in_storage() { - final Timestamp time = storage.readLastHandledEventTime(); + Timestamp time = storage.readLastHandledEventTime(); assertNull(time); } - @SuppressWarnings("MethodWithMultipleLoops") @Test public void read_all_messages() { - final List ids = fillStorage(5); + List ids = fillStorage(5); - final Iterator read = storage.readAll(); - final Collection readRecords = newArrayList(read); + Iterator read = storage.readAll(); + Collection readRecords = newArrayList(read); assertSize(ids.size(), readRecords); for (EntityRecord record : readRecords) { - final Project state = AnyPacker.unpack(record.getState()); - final ProjectId id = state.getId(); + Project state = AnyPacker.unpack(record.getState()); + ProjectId id = state.getId(); assertContains(id, ids); } } - @SuppressWarnings("MethodWithMultipleLoops") @Test public void read_all_messages_with_field_mask() { - final List ids = fillStorage(5); + List ids = fillStorage(5); - final String projectDescriptor = Project.getDescriptor() - .getFullName(); + String projectDescriptor = Project.getDescriptor() + .getFullName(); @SuppressWarnings("DuplicateStringLiteralInspection") // clashes with non-related tests. - final FieldMask fieldMask = maskForPaths(projectDescriptor + ".id", - projectDescriptor + ".name"); + FieldMask fieldMask = maskForPaths(projectDescriptor + ".id", + projectDescriptor + ".name"); - final Iterator read = storage.readAll(fieldMask); - final Collection readRecords = newArrayList(read); + Iterator read = storage.readAll(fieldMask); + Collection readRecords = newArrayList(read); assertSize(ids.size(), readRecords); for (EntityRecord record : readRecords) { - final Any packedState = record.getState(); - final Project state = AnyPacker.unpack(packedState); + Any packedState = record.getState(); + Project state = AnyPacker.unpack(packedState); assertMatchesMask(state, fieldMask); } } - @SuppressWarnings({"MethodWithMultipleLoops", "BreakStatement"}) @Test public void perform_read_bulk_operations() { // Get a subset of IDs - final List ids = fillStorage(10).subList(0, 5); + List ids = fillStorage(10).subList(0, 5); - final Iterator read = storage.readMultiple(ids); - final Collection readRecords = newArrayList(read); + Iterator read = storage.readMultiple(ids); + Collection readRecords = newArrayList(read); assertSize(ids.size(), readRecords); // Check data consistency @@ -157,31 +182,31 @@ public void perform_read_bulk_operations() { } } - @SuppressWarnings({"MethodWithMultipleLoops", "BreakStatement"}) @Test public void perform_bulk_read_with_field_mask_operation() { // Get a subset of IDs - final List ids = fillStorage(10).subList(0, 5); + List ids = fillStorage(10).subList(0, 5); - final String projectDescriptor = Project.getDescriptor() - .getFullName(); - final FieldMask fieldMask = maskForPaths(projectDescriptor + ".id", - projectDescriptor + ".status"); + String projectDescriptor = Project.getDescriptor() + .getFullName(); + FieldMask fieldMask = maskForPaths(projectDescriptor + ".id", + projectDescriptor + ".status"); - final Iterator read = storage.readMultiple(ids, fieldMask); - final Collection readRecords = newArrayList(read); + Iterator read = storage.readMultiple(ids, fieldMask); + Collection readRecords = newArrayList(read); assertSize(ids.size(), readRecords); // Check data consistency for (EntityRecord record : readRecords) { - final Project state = checkProjectIdIsInList(record, ids); + Project state = checkProjectIdIsInList(record, ids); assertMatchesMask(state, fieldMask); } } - @Test(expected = NullPointerException.class) + @Test public void throw_exception_if_write_null_event_time() { - storage.writeLastHandledEventTime(Tests.nullRef()); + thrown.expect(NullPointerException.class); + storage.writeLastHandledEventTime(Tests.nullRef()); } @Test @@ -191,26 +216,27 @@ public void write_and_read_last_event_time() { @Test public void write_and_read_last_event_time_several_times() { - final Timestamp time1 = getCurrentTime(); - final Timestamp time2 = add(time1, fromSeconds(10L)); + Timestamp time1 = getCurrentTime(); + Timestamp time2 = add(time1, fromSeconds(10L)); writeAndReadLastEventTimeTest(time1); writeAndReadLastEventTimeTest(time2); } @SuppressWarnings("ConstantConditions") // Converter nullability issues private List fillStorage(int count) { - final List ids = new LinkedList<>(); + List ids = new LinkedList<>(); for (int i = 0; i < count; i++) { - final ProjectId id = newId(); - final Project state = Given.project(id, format("project-%d", i)); - final Any packedState = AnyPacker.pack(state); - - final EntityRecord rawRecord = EntityRecord.newBuilder() - .setState(packedState) - .setVersion(GivenVersion.withNumber(1)) - .build(); - final EntityRecordWithColumns record = withLifecycleColumns(rawRecord); + ProjectId id = newId(); + Project state = Given.project(id, format("project-%d", i)); + Any packedState = AnyPacker.pack(state); + + EntityRecord rawRecord = EntityRecord + .newBuilder() + .setState(packedState) + .setVersion(GivenVersion.withNumber(1)) + .build(); + EntityRecordWithColumns record = withLifecycleColumns(rawRecord); storage.write(id, record); ids.add(id); } @@ -221,45 +247,21 @@ private List fillStorage(int count) { private void writeAndReadLastEventTimeTest(Timestamp expected) { storage.writeLastHandledEventTime(expected); - final Timestamp actual = storage.readLastHandledEventTime(); + Timestamp actual = storage.readLastHandledEventTime(); assertEquals(expected, actual); } - @SuppressWarnings("BreakStatement") - private static Project checkProjectIdIsInList(EntityRecord project, List ids) { - final Any packedState = project.getState(); - final Project state = AnyPacker.unpack(packedState); - final ProjectId id = state.getId(); - - boolean isIdPresent = false; - for (ProjectId genericId : ids) { - isIdPresent = genericId.equals(id); - if (isIdPresent) { - break; - } - } - assertTrue(isIdPresent); - - return state; - } - - private static FieldMask maskForPaths(String... paths) { - final FieldMask mask = FieldMask.newBuilder() - .addAllPaths(Arrays.asList(paths)) - .build(); - return mask; - } - private static class Given { private static Project project(ProjectId id, String name) { - final Project project = Project.newBuilder() - .setId(id) - .setName(name) - .setStatus(Project.Status.CREATED) - .addTask(Task.getDefaultInstance()) - .build(); + Project project = Project + .newBuilder() + .setId(id) + .setName(name) + .setStatus(Project.Status.CREATED) + .addTask(Task.getDefaultInstance()) + .build(); return project; } } diff --git a/server/src/test/java/io/spine/server/reflect/FieldShould.java b/server/src/test/java/io/spine/server/reflect/FieldShould.java index 8c4e7fbc572..df0c38561f1 100644 --- a/server/src/test/java/io/spine/server/reflect/FieldShould.java +++ b/server/src/test/java/io/spine/server/reflect/FieldShould.java @@ -41,7 +41,9 @@ import io.spine.test.reflect.TestEnum; import io.spine.test.reflect.TestEnumValue; import io.spine.type.TypeUrl; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -51,6 +53,16 @@ */ public class FieldShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static void assertReturnsFieldClass(Class expectedClass, Descriptor msgDescriptor) { + FieldDescriptor field = msgDescriptor.getFields() + .get(0); + + assertEquals(expectedClass, Field.getFieldClass(field)); + } + @Test public void pass_null_tolerance_check() { new NullPointerTester() @@ -61,7 +73,7 @@ public void pass_null_tolerance_check() { @SuppressWarnings("OptionalGetWithoutIsPresent") // OK as the field is present in this type. @Test public void return_name() { - final String fieldName = "seconds"; + String fieldName = "seconds"; assertEquals(fieldName, Field.newField(Timestamp.class, fieldName) .get() .getName()); @@ -76,24 +88,18 @@ public void return_absent_for_missing_field() { @SuppressWarnings("OptionalGetWithoutIsPresent") // OK since we know the field is present. @Test public void return_absent_for_default_Any_field() { - final Field messageField = Field.newField(Command.class, "message") - .get(); - final Optional value = messageField.getValue(Command.getDefaultInstance()); + Field messageField = Field.newField(Command.class, "message") + .get(); + Optional value = messageField.getValue(Command.getDefaultInstance()); assertFalse(value.isPresent()); } - @Test(expected = IllegalArgumentException.class) + @Test public void reject_field_filter_without_a_field_name() { + thrown.expect(IllegalArgumentException.class); Field.forFilter(Timestamp.class, FieldFilter.getDefaultInstance()); } - private static void assertReturnsFieldClass(Class expectedClass, Descriptor msgDescriptor) { - final FieldDescriptor field = msgDescriptor.getFields() - .get(0); - - assertEquals(expectedClass, Field.getFieldClass(field)); - } - @Test public void return_int_msg_field_class_by_descriptor() { assertReturnsFieldClass(Integer.class, Int32Value.getDescriptor()); @@ -141,10 +147,10 @@ public void return_msg_field_class_by_descriptor() { @Test public void pass_the_null_tolerance_check() { - final FieldDescriptor defaultFieldDescriptor = StringValue.getDefaultInstance() - .getDescriptorForType() - .getFields() - .get(0); + FieldDescriptor defaultFieldDescriptor = StringValue.getDefaultInstance() + .getDescriptorForType() + .getFields() + .get(0); new NullPointerTester() .setDefault(TypeUrl.class, TypeUrl.of(StringValue.class)) .setDefault(FieldDescriptor.class, defaultFieldDescriptor) diff --git a/server/src/test/java/io/spine/server/rejection/DelegatingRejectionDispatcherShould.java b/server/src/test/java/io/spine/server/rejection/DelegatingRejectionDispatcherShould.java index c6bb241b45b..86496cf579d 100644 --- a/server/src/test/java/io/spine/server/rejection/DelegatingRejectionDispatcherShould.java +++ b/server/src/test/java/io/spine/server/rejection/DelegatingRejectionDispatcherShould.java @@ -54,12 +54,12 @@ public void setUp() { delegate = new EmptyRejectionDispatcherDelegate(); delegatingDispatcher = DelegatingRejectionDispatcher.of(delegate); - final Command command = requestFactory.generateCommand(); - final Message rejectionMessage = + Command command = requestFactory.generateCommand(); + Message rejectionMessage = EntityAlreadyDeleted.newBuilder() .setEntityId(Identifier.pack(getClass().getName())) .build(); - final Rejection rejection = Rejections.createRejection(rejectionMessage, command); + Rejection rejection = Rejections.createRejection(rejectionMessage, command); rejectionEnvelope = RejectionEnvelope.of(rejection); } @@ -76,6 +76,7 @@ public void return_rejection_classes_of_the_delegate() { delegate.getRejectionClasses()); } + @SuppressWarnings("CheckReturnValue") // can ignore in this test @Test public void dispatch_rejection() { delegatingDispatcher.dispatch(rejectionEnvelope); diff --git a/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java b/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java index 805353881d6..d4010740c3e 100644 --- a/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java +++ b/server/src/test/java/io/spine/server/rejection/RejectionEnricherShould.java @@ -20,7 +20,6 @@ package io.spine.server.rejection; -import com.google.common.base.Function; import com.google.common.base.Optional; import io.spine.core.Enrichment; import io.spine.core.Enrichments; @@ -32,8 +31,6 @@ import org.junit.Before; import org.junit.Test; -import org.checkerframework.checker.nullness.qual.Nullable; - import static io.spine.server.rejection.given.Given.invalidProjectNameRejection; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; @@ -50,14 +47,11 @@ public class RejectionEnricherShould { @Before public void setUp() { - final RejectionEnricher.Builder builder = RejectionEnricher.newBuilder(); - builder.add(ProjectId.class, String.class, - new Function() { - @Override - public String apply(@Nullable ProjectId input) { - return PROJECT_NAME_PREFIX + input.getId(); - } - }); + RejectionEnricher.Builder builder = RejectionEnricher + .newBuilder() + .add(ProjectId.class, + String.class, + input -> PROJECT_NAME_PREFIX + input.getId()); RejectionEnricher enricher = builder.build(); rejectionBus = RejectionBus.newBuilder() @@ -67,19 +61,22 @@ public String apply(@Nullable ProjectId input) { @Test public void boolean_enrich_rejection() { - final RejectionEnrichmentConsumer consumer = new RejectionEnrichmentConsumer(); + RejectionEnrichmentConsumer consumer = new RejectionEnrichmentConsumer(); rejectionBus.register(consumer); - final Rejection rejection = invalidProjectNameRejection(); + Rejection rejection = invalidProjectNameRejection(); rejectionBus.post(rejection); - final RejectionContext context = consumer.getContext(); + RejectionContext context = consumer.getContext(); - final Enrichment enrichment = context.getEnrichment(); + Enrichment enrichment = context.getEnrichment(); assertNotEquals(Enrichment.getDefaultInstance(), enrichment); - final Optional optional = + + Optional optional = Enrichments.getEnrichment(ProjectRejections.ProjectInfo.class, context); assertTrue(optional.isPresent()); - assertTrue(optional.get().getProjectName().startsWith(PROJECT_NAME_PREFIX)); + assertTrue(optional.get() + .getProjectName() + .startsWith(PROJECT_NAME_PREFIX)); } } diff --git a/server/src/test/java/io/spine/server/rejection/RejectionReactorMethodShould.java b/server/src/test/java/io/spine/server/rejection/RejectionReactorMethodShould.java index 1e280bd819a..5b34cc4af74 100644 --- a/server/src/test/java/io/spine/server/rejection/RejectionReactorMethodShould.java +++ b/server/src/test/java/io/spine/server/rejection/RejectionReactorMethodShould.java @@ -39,7 +39,6 @@ import io.spine.test.rejection.command.RjUpdateProjectName; import org.junit.Test; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static io.spine.protobuf.AnyPacker.pack; @@ -48,7 +47,6 @@ /** * @author Alexander Yevsyukov */ -@SuppressWarnings("unused") // some of tests address just the fact of method declaration. public class RejectionReactorMethodShould { private static final CommandContext emptyCommandContext = CommandContext.getDefaultInstance(); @@ -62,23 +60,26 @@ public void pass_null_tolerance_check() { .testAllPublicStaticMethods(RejectionReactorMethod.class); } + @SuppressWarnings("CheckReturnValue" + /* 1. Ignore builder method (setCommand()) call result. + 2. Ignore result of invoke() -- we check object internals instead. */) @Test - public void invoke_reactor_method() throws InvocationTargetException { - final RValidThreeParams reactorObject = new RValidThreeParams(); - final RejectionReactorMethod reactor = + public void invoke_reactor_method() { + RValidThreeParams reactorObject = new RValidThreeParams(); + RejectionReactorMethod reactor = new RejectionReactorMethod(reactorObject.getMethod()); - final InvalidProjectName rejectionMessage = Given.RejectionMessage.invalidProjectName(); + InvalidProjectName rejectionMessage = Given.RejectionMessage.invalidProjectName(); - final RejectionContext.Builder builder = RejectionContext.newBuilder(); - final CommandContext commandContext = + RejectionContext.Builder builder = RejectionContext.newBuilder(); + CommandContext commandContext = CommandContext.newBuilder() .setTargetVersion(3040) .build(); - final RjUpdateProjectName commandMessage = RjUpdateProjectName.getDefaultInstance(); + RjUpdateProjectName commandMessage = RjUpdateProjectName.getDefaultInstance(); builder.setCommand(Command.newBuilder() .setMessage(pack(commandMessage)) .setContext(commandContext)); - final RejectionContext rejectionContext = builder.build(); + RejectionContext rejectionContext = builder.build(); reactor.invoke(reactorObject, rejectionMessage, rejectionContext); @@ -89,77 +90,77 @@ public void invoke_reactor_method() throws InvocationTargetException { @Test public void consider_reactor_with_two_msg_param_valid() { - final Method reactor = new RValidTwoParams().getMethod(); + Method reactor = new RValidTwoParams().getMethod(); assertIsRejectionReactor(reactor, true); } @Test public void consider_reactor_with_both_messages_and_context_params_valid() { - final Method reactor = new RValidThreeParams().getMethod(); + Method reactor = new RValidThreeParams().getMethod(); assertIsRejectionReactor(reactor, true); } @Test public void consider_not_public_reactor_valid() { - final Method method = new RValidButPrivate().getMethod(); + Method method = new RValidButPrivate().getMethod(); assertIsRejectionReactor(method, true); } @Test public void consider_not_annotated_reactor_invalid() { - final Method reactor = new RInvalidNoAnnotation().getMethod(); + Method reactor = new RInvalidNoAnnotation().getMethod(); assertIsRejectionReactor(reactor, false); } @Test public void consider_reactor_without_params_invalid() { - final Method reactor = new RInvalidNoParams().getMethod(); + Method reactor = new RInvalidNoParams().getMethod(); assertIsRejectionReactor(reactor, false); } @Test public void consider_reactor_with_too_many_params_invalid() { - final Method reactor = new RInvalidTooManyParams().getMethod(); + Method reactor = new RInvalidTooManyParams().getMethod(); assertIsRejectionReactor(reactor, false); } @Test(expected = IllegalArgumentException.class) public void throw_exception_on_attempt_to_create_instance_for_a_method_with_too_many_params() { - final Method illegalMethod = new RInvalidTooManyParams().getMethod(); + Method illegalMethod = new RInvalidTooManyParams().getMethod(); new RejectionReactorMethod(illegalMethod); } @Test public void consider_reactor_with_one_invalid_param_invalid() { - final Method reactor = new RInvalidOneNotMsgParam().getMethod(); + Method reactor = new RInvalidOneNotMsgParam().getMethod(); assertIsRejectionReactor(reactor, false); } @Test public void consider_reactor_with_first_not_message_param_invalid() { - final Method reactor = new RInvalidTwoParamsFirstInvalid().getMethod(); + Method reactor = new RInvalidTwoParamsFirstInvalid().getMethod(); assertIsRejectionReactor(reactor, false); } @Test public void consider_reactor_with_second_not_context_param_invalid() { - final Method reactor = new RInvalidTwoParamsSecondInvalid().getMethod(); + Method reactor = new RInvalidTwoParamsSecondInvalid().getMethod(); assertIsRejectionReactor(reactor, false); } @Test public void consider_not_void_reactor_invalid() { - final Method reactor = new RInvalidNotMessage().getMethod(); + Method reactor = new RInvalidNotMessage().getMethod(); assertIsRejectionReactor(reactor, false); } diff --git a/server/src/test/java/io/spine/server/rejection/RejectionSubscriberMethodShould.java b/server/src/test/java/io/spine/server/rejection/RejectionSubscriberMethodShould.java index 79cf29cb9ed..2340b183dc4 100644 --- a/server/src/test/java/io/spine/server/rejection/RejectionSubscriberMethodShould.java +++ b/server/src/test/java/io/spine/server/rejection/RejectionSubscriberMethodShould.java @@ -27,7 +27,8 @@ import io.spine.core.RejectionEnvelope; import io.spine.server.model.given.Given; import io.spine.server.rejection.given.FaultySubscriber; -import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv; +import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv.InvalidNoAnnotation; +import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv.InvalidNoParams; import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv.InvalidNotMessage; import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv.InvalidOneNotMsgParam; import io.spine.server.rejection.given.RejectionSubscriberMethodTestEnv.InvalidTooManyParams; @@ -41,7 +42,6 @@ import io.spine.test.rejection.command.RjUpdateProjectName; import org.junit.Test; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static io.spine.protobuf.AnyPacker.pack; @@ -67,23 +67,25 @@ public void pass_null_tolerance_check() { .testAllPublicStaticMethods(RejectionSubscriberMethod.class); } + @SuppressWarnings("CheckReturnValue") // can ignore the result of invoke() in this test @Test - public void invoke_subscriber_method() throws InvocationTargetException { - final ValidThreeParams subscriberObject = new ValidThreeParams(); - final RejectionSubscriberMethod method = + public void invoke_subscriber_method() { + ValidThreeParams subscriberObject = new ValidThreeParams(); + RejectionSubscriberMethod method = new RejectionSubscriberMethod(subscriberObject.getMethod()); - final InvalidProjectName rejectionMessage = Given.RejectionMessage.invalidProjectName(); - - final RejectionContext.Builder builder = RejectionContext.newBuilder(); - final CommandContext commandContext = - CommandContext.newBuilder() - .setTargetVersion(1020) - .build(); - final RjUpdateProjectName commandMessage = RjUpdateProjectName.getDefaultInstance(); - builder.setCommand(Command.newBuilder() - .setMessage(pack(commandMessage)) - .setContext(commandContext)); - final RejectionContext rejectionContext = builder.build(); + InvalidProjectName rejectionMessage = Given.RejectionMessage.invalidProjectName(); + + CommandContext commandContext = CommandContext + .newBuilder() + .setTargetVersion(1020) + .build(); + RjUpdateProjectName commandMessage = RjUpdateProjectName.getDefaultInstance(); + RejectionContext.Builder builder = RejectionContext + .newBuilder() + .setCommand(Command.newBuilder() + .setMessage(pack(commandMessage)) + .setContext(commandContext)); + RejectionContext rejectionContext = builder.build(); method.invoke(subscriberObject, rejectionMessage, rejectionContext); @@ -92,9 +94,10 @@ public void invoke_subscriber_method() throws InvocationTargetException { assertEquals(commandContext, subscriberObject.getLastCommandContext()); } + @SuppressWarnings("CheckReturnValue") // can ignore the result of dispatch() in this test @Test public void catch_exceptions_caused_by_subscribers() { - final VerifiableSubscriber faultySubscriber = new FaultySubscriber(); + VerifiableSubscriber faultySubscriber = new FaultySubscriber(); faultySubscriber.dispatch(RejectionEnvelope.of(invalidProjectNameRejection())); @@ -103,77 +106,77 @@ public void catch_exceptions_caused_by_subscribers() { @Test public void consider_subscriber_with_two_msg_param_valid() { - final Method subscriber = new ValidTwoParams().getMethod(); + Method subscriber = new ValidTwoParams().getMethod(); assertIsRejectionSubscriber(subscriber, true); } @Test public void consider_subscriber_with_both_messages_and_context_params_valid() { - final Method subscriber = new ValidThreeParams().getMethod(); + Method subscriber = new ValidThreeParams().getMethod(); assertIsRejectionSubscriber(subscriber, true); } @Test public void consider_not_public_subscriber_valid() { - final Method method = new ValidButPrivate().getMethod(); + Method method = new ValidButPrivate().getMethod(); assertIsRejectionSubscriber(method, true); } @Test public void consider_not_annotated_subscriber_invalid() { - final Method subscriber = new RejectionSubscriberMethodTestEnv.InvalidNoAnnotation().getMethod(); + Method subscriber = new InvalidNoAnnotation().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test public void consider_subscriber_without_params_invalid() { - final Method subscriber = new RejectionSubscriberMethodTestEnv.InvalidNoParams().getMethod(); + Method subscriber = new InvalidNoParams().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test public void consider_subscriber_with_too_many_params_invalid() { - final Method subscriber = new InvalidTooManyParams().getMethod(); + Method subscriber = new InvalidTooManyParams().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test(expected = IllegalArgumentException.class) public void throw_exception_on_attempt_to_create_instance_for_a_method_with_too_many_params() { - final Method illegalMethod = new InvalidTooManyParams().getMethod(); + Method illegalMethod = new InvalidTooManyParams().getMethod(); new RejectionSubscriberMethod(illegalMethod); } @Test public void consider_subscriber_with_one_invalid_param_invalid() { - final Method subscriber = new InvalidOneNotMsgParam().getMethod(); + Method subscriber = new InvalidOneNotMsgParam().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test public void consider_subscriber_with_first_not_message_param_invalid() { - final Method subscriber = new InvalidTwoParamsFirstInvalid().getMethod(); + Method subscriber = new InvalidTwoParamsFirstInvalid().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test public void consider_subscriber_with_second_not_context_param_invalid() { - final Method subscriber = new InvalidTwoParamsSecondInvalid().getMethod(); + Method subscriber = new InvalidTwoParamsSecondInvalid().getMethod(); assertIsRejectionSubscriber(subscriber, false); } @Test public void consider_not_void_subscriber_invalid() { - final Method subscriber = new InvalidNotMessage().getMethod(); + Method subscriber = new InvalidNotMessage().getMethod(); assertIsRejectionSubscriber(subscriber, false); } diff --git a/server/src/test/java/io/spine/server/stand/MultiTenantStandShould.java b/server/src/test/java/io/spine/server/stand/MultiTenantStandShould.java index aca5e2ee5ef..3819bf3bd85 100644 --- a/server/src/test/java/io/spine/server/stand/MultiTenantStandShould.java +++ b/server/src/test/java/io/spine/server/stand/MultiTenantStandShould.java @@ -55,7 +55,7 @@ public class MultiTenantStandShould extends StandShould { @Before public void setUp() { super.setUp(); - final TenantId tenantId = newUuid(); + TenantId tenantId = newUuid(); setCurrentTenant(tenantId); setMultitenant(true); @@ -69,52 +69,51 @@ public void tearDown() { @Test public void not_allow_reading_aggregate_records_for_another_tenant() { - final Stand stand = doCheckReadingCustomersById(15); + Stand stand = doCheckReadingCustomersById(15); - final TenantId anotherTenant = newUuid(); - final ActorRequestFactory requestFactory = createRequestFactory(anotherTenant); + TenantId anotherTenant = newUuid(); + ActorRequestFactory requestFactory = createRequestFactory(anotherTenant); - final Query readAllCustomers = requestFactory.query().all(Customer.class); + Query readAllCustomers = requestFactory.query() + .all(Customer.class); - final MemoizeQueryResponseObserver responseObserver = new MemoizeQueryResponseObserver(); + MemoizeQueryResponseObserver responseObserver = new MemoizeQueryResponseObserver(); stand.execute(readAllCustomers, responseObserver); - final QueryResponse response = responseObserver.getResponseHandled(); + QueryResponse response = responseObserver.getResponseHandled(); assertTrue(Responses.isOk(response.getResponse())); assertEquals(0, response.getMessagesCount()); } @Test public void not_trigger_updates_of_aggregate_records_for_another_tenant_subscriptions() { - final StandStorage standStorage = + StandStorage standStorage = InMemoryStorageFactory.newInstance(newName(getClass().getSimpleName()), isMultitenant()) .createStandStorage(); - final Stand stand = prepareStandWithAggregateRepo(standStorage); + Stand stand = prepareStandWithAggregateRepo(standStorage); // --- Default Tenant - final ActorRequestFactory requestFactory = getRequestFactory(); - final MemoizeEntityUpdateCallback defaultTenantCallback = subscribeToAllOf(stand, - requestFactory, - Customer.class); + ActorRequestFactory requestFactory = getRequestFactory(); + MemoizeEntityUpdateCallback defaultTenantCallback = + subscribeToAllOf(stand, requestFactory, Customer.class); // --- Another Tenant - final TenantId anotherTenant = newUuid(); - final ActorRequestFactory anotherFactory = createRequestFactory(anotherTenant); - final MemoizeEntityUpdateCallback anotherCallback = subscribeToAllOf(stand, - anotherFactory, - Customer.class); + TenantId anotherTenant = newUuid(); + ActorRequestFactory anotherFactory = createRequestFactory(anotherTenant); + MemoizeEntityUpdateCallback anotherCallback = + subscribeToAllOf(stand, anotherFactory, Customer.class); // Trigger updates in Default Tenant. - final Map.Entry sampleData = + Map.Entry sampleData = fillSampleCustomers(1).entrySet() .iterator() .next(); - final CustomerId customerId = sampleData.getKey(); - final Customer customer = sampleData.getValue(); - final Version stateVersion = GivenVersion.withNumber(1); + CustomerId customerId = sampleData.getKey(); + Customer customer = sampleData.getValue(); + Version stateVersion = GivenVersion.withNumber(1); stand.update(asEnvelope(customerId, customer, stateVersion)); - final Any packedState = AnyPacker.pack(customer); + Any packedState = AnyPacker.pack(customer); // Verify that Default Tenant callback has got the update. assertEquals(packedState, defaultTenantCallback.getNewEntityState()); @@ -125,8 +124,9 @@ public void not_trigger_updates_of_aggregate_records_for_another_tenant_subscrip protected MemoizeEntityUpdateCallback subscribeToAllOf(Stand stand, ActorRequestFactory requestFactory, Class entityClass) { - final Topic allCustomers = requestFactory.topic().allOf(entityClass); - final MemoizeEntityUpdateCallback callback = new MemoizeEntityUpdateCallback(); + Topic allCustomers = requestFactory.topic() + .allOf(entityClass); + MemoizeEntityUpdateCallback callback = new MemoizeEntityUpdateCallback(); subscribeAndActivate(stand, allCustomers, callback); assertNull(callback.getNewEntityState()); diff --git a/server/src/test/java/io/spine/server/stand/StandPostShould.java b/server/src/test/java/io/spine/server/stand/StandPostShould.java index 508d694f90c..2892c94ab34 100644 --- a/server/src/test/java/io/spine/server/stand/StandPostShould.java +++ b/server/src/test/java/io/spine/server/stand/StandPostShould.java @@ -63,91 +63,35 @@ public class StandPostShould { // **** Positive scenarios (unit) **** - @SuppressWarnings({"OverlyComplexAnonymousInnerClass", "ConstantConditions"}) - @Test - public void deliver_updates() { - final AggregateRepository repository = - Given.aggregateRepo(); - final ProjectId entityId = ProjectId.newBuilder() - .setId("PRJ-001") - .build(); - final Given.StandTestAggregate entity = repository.create(entityId); - final StringValue state = entity.getState(); - final Version version = entity.getVersion(); - - final Stand innerStand = Stand.newBuilder().build(); - final Stand stand = spy(innerStand); - - stand.post(requestFactory.createCommandContext() - .getActorContext() - .getTenantId(), entity); - - final ArgumentMatcher> argumentMatcher = - new ArgumentMatcher>() { - @Override - public boolean matches(EntityStateEnvelope argument) { - final boolean entityIdMatches = argument.getEntityId() - .equals(entityId); - final boolean versionMatches = version.equals(argument.getEntityVersion() - .orNull()); - final boolean stateMatches = argument.getMessage() - .equals(state); - return entityIdMatches && - versionMatches && - stateMatches; - } - }; - verify(stand).update(ArgumentMatchers.argThat(argumentMatcher)); - } - - // **** Integration scenarios ( -> StandFunnel -> Mock Stand) **** - - @Test - public void deliver_updates_from_projection_repository() { - checkUpdatesDelivery(false, projectionRepositoryDispatch()); - } - - @Test - public void deliver_updates_from_aggregate_repository() { - checkUpdatesDelivery(false, aggregateRepositoryDispatch()); - } - - @Test - public void deliver_updates_from_several_repositories_in_single_thread() { - checkUpdatesDelivery(false, getSeveralRepositoryDispatchCalls()); - } - - @Test - public void deliver_updates_from_several_repositories_in_multiple_threads() { - checkUpdatesDelivery(true, getSeveralRepositoryDispatchCalls()); - } - private static BoundedContextAction[] getSeveralRepositoryDispatchCalls() { - final BoundedContextAction[] result = new BoundedContextAction[Given.SEVERAL]; + BoundedContextAction[] result = new BoundedContextAction[Given.SEVERAL]; for (int i = 0; i < result.length; i++) { result[i] = (i % 2 == 0) - ? aggregateRepositoryDispatch() - : projectionRepositoryDispatch(); + ? aggregateRepositoryDispatch() + : projectionRepositoryDispatch(); } return result; } + // **** Integration scenarios ( -> StandFunnel -> Mock Stand) **** + private static void checkUpdatesDelivery(boolean isConcurrent, BoundedContextAction... dispatchActions) { checkNotNull(dispatchActions); - final Executor executor = isConcurrent - ? Executors.newFixedThreadPool(Given.THREADS_COUNT_IN_POOL_EXECUTOR) - : MoreExecutors.directExecutor(); + Executor executor = isConcurrent + ? Executors.newFixedThreadPool( + Given.THREADS_COUNT_IN_POOL_EXECUTOR) + : MoreExecutors.directExecutor(); - final BoundedContext boundedContext = + BoundedContext boundedContext = BoundedContext.newBuilder() .setStand(Stand.newBuilder()) .build(); - final Stand stand = boundedContext.getStand(); + Stand stand = boundedContext.getStand(); for (BoundedContextAction dispatchAction : dispatchActions) { dispatchAction.perform(boundedContext); @@ -163,103 +107,149 @@ private static void checkUpdatesDelivery(boolean isConcurrent, verify(stand, times(dispatchActions.length)).update(any(EntityStateEnvelope.class)); } + @SuppressWarnings("CheckReturnValue") // can ignore the dispatch() result private static BoundedContextAction aggregateRepositoryDispatch() { - return new BoundedContextAction() { - @Override - public void perform(BoundedContext context) { - // Init repository - final AggregateRepository repository = Given.aggregateRepo(); - - repository.initStorage(storageFactory(context.isMultitenant())); - - try { - // Mock aggregate and mock stand are not able to handle events - // returned after command handling. - // This causes IllegalStateException to be thrown. - // Note that this is not the end of a test case, - // so we can't just "expect=IllegalStateException". - final CommandEnvelope cmd = CommandEnvelope.of(Given.validCommand()); - repository.dispatch(cmd); - } catch (IllegalStateException e) { - // Handle null event dispatching after the command is handled. - - // Check if this error is caused by returning nuu or empty list after - // command processing. - // Proceed crash if it's not. - if (!e.getMessage() - .contains("No record found for command ID: EMPTY")) { - throw e; - } + return context -> { + // Init repository + final AggregateRepository repository = Given.aggregateRepo(); + + repository.initStorage(storageFactory(context.isMultitenant())); + + try { + // Mock aggregate and mock stand are not able to handle events + // returned after command handling. + // This causes IllegalStateException to be thrown. + // Note that this is not the end of a test case, + // so we can't just "expect=IllegalStateException". + CommandEnvelope cmd = CommandEnvelope.of(Given.validCommand()); + repository.dispatch(cmd); + } catch (IllegalStateException e) { + // Handle null event dispatching after the command is handled. + + // Check if this error is caused by returning null or empty list after + // command processing. + // Proceed crash if it's not. + if (!e.getMessage() + .contains("No record found for command ID: EMPTY")) { + throw e; } } }; } + @SuppressWarnings("CheckReturnValue") // can ignore the dispatch() result private static BoundedContextAction projectionRepositoryDispatch() { - return new BoundedContextAction() { - @Override - public void perform(BoundedContext context) { - // Init repository - final ProjectionRepository repository = Given.projectionRepo(); - repository.initStorage(storageFactory(context.isMultitenant())); - - // Dispatch an update from projection repo - repository.dispatch(EventEnvelope.of(Given.validEvent())); - } + return context -> { + // Init repository + ProjectionRepository repository = Given.projectionRepo(); + repository.initStorage(storageFactory(context.isMultitenant())); + + // Dispatch an update from projection repo + repository.dispatch(EventEnvelope.of(Given.validEvent())); }; } private static StorageFactory storageFactory(boolean multitenant) { - final BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(multitenant) - .build(); + BoundedContext bc = BoundedContext.newBuilder() + .setMultitenant(multitenant) + .build(); return bc.getStorageFactory(); } - @SuppressWarnings("MethodWithMultipleLoops") + @Test + public void deliver_updates() { + AggregateRepository repository = + Given.aggregateRepo(); + ProjectId entityId = ProjectId + .newBuilder() + .setId("PRJ-001") + .build(); + Given.StandTestAggregate entity = repository.create(entityId); + StringValue state = entity.getState(); + Version version = entity.getVersion(); + + Stand innerStand = Stand.newBuilder() + .build(); + Stand stand = spy(innerStand); + + stand.post(requestFactory.createCommandContext() + .getActorContext() + .getTenantId(), entity); + + ArgumentMatcher> argumentMatcher = + argument -> { + boolean entityIdMatches = argument.getEntityId() + .equals(entityId); + boolean versionMatches = version.equals(argument.getEntityVersion() + .orNull()); + boolean stateMatches = argument.getMessage() + .equals(state); + return entityIdMatches && + versionMatches && + stateMatches; + }; + verify(stand).update(ArgumentMatchers.argThat(argumentMatcher)); + } + + @Test + public void deliver_updates_from_projection_repository() { + checkUpdatesDelivery(false, projectionRepositoryDispatch()); + } + + @Test + public void deliver_updates_from_aggregate_repository() { + checkUpdatesDelivery(false, aggregateRepositoryDispatch()); + } + + @Test + public void deliver_updates_from_several_repositories_in_single_thread() { + checkUpdatesDelivery(false, getSeveralRepositoryDispatchCalls()); + } + + @Test + public void deliver_updates_from_several_repositories_in_multiple_threads() { + checkUpdatesDelivery(true, getSeveralRepositoryDispatchCalls()); + } + @Test public void deliver_updates_through_several_threads() throws InterruptedException { - final int threadsCount = Given.THREADS_COUNT_IN_POOL_EXECUTOR; - @SuppressWarnings("LocalVariableNamingConvention") // Too long variable name - final int threadExecutionMaxAwaitSeconds = Given.AWAIT_SECONDS; - - final Set threadInvocationRegistry = new ConcurrentSet<>(); - - final Stand stand = Stand.newBuilder() - .build(); - - final ExecutorService executor = Executors.newFixedThreadPool(threadsCount); - - final Runnable task = new Runnable() { - @Override - public void run() { - final String threadName = Thread.currentThread() - .getName(); - Assert.assertFalse(threadInvocationRegistry.contains(threadName)); - final ProjectId enitityId = ProjectId.newBuilder() - .setId(Identifier.newUuid()) - .build(); - final Given.StandTestAggregate entity = Given.aggregateRepo() - .create(enitityId); - stand.post(requestFactory.createCommandContext() - .getActorContext() - .getTenantId(), entity); - - threadInvocationRegistry.add(threadName); - } + int threadsCount = Given.THREADS_COUNT_IN_POOL_EXECUTOR; + + Set threadInvocationRegistry = new ConcurrentSet<>(); + + Stand stand = Stand.newBuilder() + .build(); + + ExecutorService executor = Executors.newFixedThreadPool(threadsCount); + + Runnable task = () -> { + String threadName = Thread.currentThread() + .getName(); + Assert.assertFalse(threadInvocationRegistry.contains(threadName)); + ProjectId entityId = ProjectId + .newBuilder() + .setId(Identifier.newUuid()) + .build(); + Given.StandTestAggregate entity = Given.aggregateRepo() + .create(entityId); + stand.post(requestFactory.createCommandContext() + .getActorContext() + .getTenantId(), entity); + + threadInvocationRegistry.add(threadName); }; for (int i = 0; i < threadsCount; i++) { executor.execute(task); } - executor.awaitTermination(threadExecutionMaxAwaitSeconds, TimeUnit.SECONDS); + executor.awaitTermination(Given.AWAIT_SECONDS, TimeUnit.SECONDS); Assert.assertEquals(threadInvocationRegistry.size(), threadsCount); - } private interface BoundedContextAction { + void perform(BoundedContext context); } } diff --git a/server/src/test/java/io/spine/server/stand/StandShould.java b/server/src/test/java/io/spine/server/stand/StandShould.java index 7dfb087865d..dcf1bed5837 100644 --- a/server/src/test/java/io/spine/server/stand/StandShould.java +++ b/server/src/test/java/io/spine/server/stand/StandShould.java @@ -70,12 +70,12 @@ import io.spine.type.TypeUrl; import io.spine.validate.Validate; import io.spine.validate.ValidationError; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentMatcher; import org.mockito.ArgumentMatchers; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -156,9 +156,10 @@ public void setUp() { } protected static ActorRequestFactory createRequestFactory(@Nullable TenantId tenant) { - final ActorRequestFactory.Builder builder = ActorRequestFactory.newBuilder() - .setActor(of(newUuid())) - .setZoneOffset(ZoneOffsets.UTC); + ActorRequestFactory.Builder builder = ActorRequestFactory + .newBuilder() + .setActor(of(newUuid())) + .setZoneOffset(ZoneOffsets.UTC); if (tenant != null) { builder.setTenantId(tenant); } diff --git a/server/src/test/java/io/spine/server/storage/OperatorEvaluatorShould.java b/server/src/test/java/io/spine/server/storage/OperatorEvaluatorShould.java index 42f075bc25b..f37cb1ac91d 100644 --- a/server/src/test/java/io/spine/server/storage/OperatorEvaluatorShould.java +++ b/server/src/test/java/io/spine/server/storage/OperatorEvaluatorShould.java @@ -23,7 +23,9 @@ import com.google.common.testing.NullPointerTester; import com.google.protobuf.Duration; import com.google.protobuf.Timestamp; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static com.google.common.testing.NullPointerTester.Visibility.PACKAGE; import static com.google.protobuf.util.Timestamps.add; @@ -44,11 +46,17 @@ /** * @author Dmytro Dashenkov */ -@SuppressWarnings({"Duplicates", "ClassWithTooManyMethods"}) - // 1 - Comparison tests are similar but cannot be simplified to one. - // 2 - Many test cases required. +@SuppressWarnings({ + "Duplicates", + "ClassWithTooManyMethods" + /* 1 - Comparison tests are similar but cannot be simplified to one. + 2 - Many test cases required. */ +}) public class OperatorEvaluatorShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void not_accept_nulls() { new NullPointerTester() @@ -58,9 +66,9 @@ public void not_accept_nulls() { @SuppressWarnings("RedundantStringConstructorCall") // We need an equal but not the same object @Test public void compare_equal_instances() { - final String left = "myobject"; - final Object right = new String(left); - final Object third = new String(left); + String left = "myobject"; + Object right = new String(left); + Object third = new String(left); // The checks taken from the java.lang.Object.equals Javadoc assertTrue("basic", eval(left, EQUAL, right)); @@ -73,8 +81,8 @@ public void compare_equal_instances() { @Test public void compare_not_equal_instances() { - final Object left = "one!"; - final Object right = "another!"; + Object left = "one!"; + Object right = "another!"; assertFalse("direct order check", eval(left, EQUAL, right)); assertFalse("reverse order check", eval(right, EQUAL, left)); @@ -82,10 +90,10 @@ public void compare_not_equal_instances() { @Test public void compare_timestamps_by_GT() { - final Duration delta = seconds(5); - final Timestamp small = getCurrentTime(); - final Timestamp medium = add(small, delta); - final Timestamp big = add(medium, delta); + Duration delta = seconds(5); + Timestamp small = getCurrentTime(); + Timestamp medium = add(small, delta); + Timestamp big = add(medium, delta); assertTrue(eval(medium, GREATER_THAN, small)); assertTrue(eval(big, GREATER_THAN, medium)); @@ -98,10 +106,10 @@ public void compare_timestamps_by_GT() { @Test public void compare_timestamps_by_GE() { - final Duration delta = seconds(5); - final Timestamp small = getCurrentTime(); - final Timestamp medium = add(small, delta); - final Timestamp big = add(medium, delta); + Duration delta = seconds(5); + Timestamp small = getCurrentTime(); + Timestamp medium = add(small, delta); + Timestamp big = add(medium, delta); assertTrue(eval(medium, GREATER_OR_EQUAL, small)); assertTrue(eval(big, GREATER_OR_EQUAL, medium)); @@ -114,10 +122,10 @@ public void compare_timestamps_by_GE() { @Test public void compare_timestamps_by_LT() { - final Duration delta = seconds(5); - final Timestamp small = getCurrentTime(); - final Timestamp medium = add(small, delta); - final Timestamp big = add(medium, delta); + Duration delta = seconds(5); + Timestamp small = getCurrentTime(); + Timestamp medium = add(small, delta); + Timestamp big = add(medium, delta); assertTrue(eval(medium, LESS_THAN, big)); assertTrue(eval(small, LESS_THAN, medium)); @@ -130,10 +138,10 @@ public void compare_timestamps_by_LT() { @Test public void compare_timestamps_by_LE() { - final Duration delta = seconds(5); - final Timestamp small = getCurrentTime(); - final Timestamp medium = add(small, delta); - final Timestamp big = add(medium, delta); + Duration delta = seconds(5); + Timestamp small = getCurrentTime(); + Timestamp medium = add(small, delta); + Timestamp big = add(medium, delta); assertTrue(eval(medium, LESS_OR_EQUAL, big)); assertTrue(eval(small, LESS_OR_EQUAL, medium)); @@ -204,35 +212,39 @@ public void compare_doubles_by_LE() { assertLessOrEqual(42.999, 43.0); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_unsupported_types_by_GT() { + thrown.expect(IllegalArgumentException.class); eval(FaultyComparisonType.INSTANCE, GREATER_THAN, FaultyComparisonType.INSTANCE); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_unsupported_types_by_GE() { + thrown.expect(IllegalArgumentException.class); eval(FaultyComparisonType.INSTANCE, GREATER_OR_EQUAL, FaultyComparisonType.INSTANCE); - } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_unsupported_types_by_LT() { + thrown.expect(IllegalArgumentException.class); eval(FaultyComparisonType.INSTANCE, LESS_THAN, FaultyComparisonType.INSTANCE); - } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_unsupported_types_by_LE() { + thrown.expect(IllegalArgumentException.class); eval(FaultyComparisonType.INSTANCE, LESS_OR_EQUAL, FaultyComparisonType.INSTANCE); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_different_types() { + thrown.expect(IllegalArgumentException.class); eval("7", GREATER_THAN, 6); } - @Test(expected = IllegalArgumentException.class) + @Test public void fail_to_compare_by_an_invalid_operator() { + thrown.expect(IllegalArgumentException.class); eval("a", CFO_UNDEFINED, "b"); } diff --git a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java index 20a7171f528..58c555e3655 100644 --- a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java +++ b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java @@ -25,6 +25,7 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Any; import com.google.protobuf.Descriptors; import com.google.protobuf.FieldMask; @@ -57,10 +58,9 @@ import io.spine.test.storage.Project; import io.spine.test.storage.ProjectVBuilder; import io.spine.testdata.Sample; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; -import org.mockito.ArgumentMatcher; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -107,15 +107,46 @@ public abstract class RecordStorageShould> extends AbstractStorageShould, S> { - private static final Function RECORD_EXTRACTOR_FUNCTION = - new Function() { - @Override - public EntityRecord apply( - @Nullable EntityRecordWithColumns entityRecord) { - assertNotNull(entityRecord); - return entityRecord.getRecord(); - } - }; + private static EntityRecord newStorageRecord(Message state) { + Any wrappedState = pack(state); + EntityRecord record = EntityRecord.newBuilder() + .setState(wrappedState) + .setVersion(GivenVersion.withNumber(0)) + .build(); + return record; + } + + protected static EntityRecordWithColumns withLifecycleColumns(EntityRecord record) { + LifecycleFlags flags = record.getLifecycleFlags(); + Map columns = ImmutableMap.of( + LifecycleColumns.ARCHIVED.columnName(), + booleanColumn(LifecycleColumns.ARCHIVED.column(), flags.getArchived()), + LifecycleColumns.DELETED.columnName(), + booleanColumn(LifecycleColumns.DELETED.column(), flags.getDeleted()) + ); + EntityRecordWithColumns result = createRecord(record, columns); + return result; + } + + private static MemoizedValue booleanColumn(EntityColumn column, boolean value) { + MemoizedValue memoizedValue = mock(MemoizedValue.class); + when(memoizedValue.getSourceColumn()).thenReturn(column); + when(memoizedValue.getValue()).thenReturn(value); + return memoizedValue; + } + + private static EntityRecordWithColumns withRecordAndNoFields(EntityRecord record) { + return argThat(argument -> argument.getRecord() + .equals(record) + && !argument.hasColumns()); + } + + private static void assertSingleRecord(EntityRecord expected, Iterator actual) { + assertTrue(actual.hasNext()); + EntityRecord singleRecord = actual.next(); + assertFalse(actual.hasNext()); + assertEquals(expected, singleRecord); + } /** * Creates an unique {@code Message} with the specified ID. @@ -137,26 +168,22 @@ protected RecordReadRequest newReadRequest(I id) { return new RecordReadRequest<>(id); } - private EntityRecord newStorageRecord(I id) { - return newStorageRecord(newState(id)); + @Override + protected Class getTestEntityClass() { + return TestCounterEntity.class; } - private static EntityRecord newStorageRecord(Message state) { - final Any wrappedState = pack(state); - final EntityRecord record = EntityRecord.newBuilder() - .setState(wrappedState) - .setVersion(GivenVersion.withNumber(0)) - .build(); - return record; + private EntityRecord newStorageRecord(I id) { + return newStorageRecord(newState(id)); } private EntityRecord newStorageRecord(I id, Message state) { - final Any wrappedState = pack(state); - final EntityRecord record = EntityRecord.newBuilder() - .setEntityId(pack(id)) - .setState(wrappedState) - .setVersion(GivenVersion.withNumber(0)) - .build(); + Any wrappedState = pack(state); + EntityRecord record = EntityRecord.newBuilder() + .setEntityId(pack(id)) + .setState(wrappedState) + .setVersion(GivenVersion.withNumber(0)) + .build(); return record; } @@ -164,31 +191,26 @@ private EntityRecord newStorageRecord(I id, Message state) { // Converter nullability issues and Optional getting @Test public void write_and_read_record_by_Message_id() { - final RecordStorage storage = getStorage(); - final I id = newId(); - final EntityRecord expected = newStorageRecord(id); + RecordStorage storage = getStorage(); + I id = newId(); + EntityRecord expected = newStorageRecord(id); storage.write(id, expected); - final RecordReadRequest readRequest = newReadRequest(id); - final EntityRecord actual = storage.read(readRequest) - .get(); + RecordReadRequest readRequest = newReadRequest(id); + EntityRecord actual = storage.read(readRequest) + .get(); assertEquals(expected, actual); close(storage); } - @Override - protected Class getTestEntityClass() { - return TestCounterEntity.class; - } - @Test public void retrieve_empty_iterator_if_storage_is_empty() { - final FieldMask nonEmptyFieldMask = FieldMask.newBuilder() - .addPaths("invalid-path") - .build(); - final RecordStorage storage = getStorage(); - final Iterator empty = storage.readAll(nonEmptyFieldMask); + FieldMask nonEmptyFieldMask = FieldMask.newBuilder() + .addPaths("invalid-path") + .build(); + RecordStorage storage = getStorage(); + Iterator empty = storage.readAll(nonEmptyFieldMask); assertNotNull(empty); assertFalse("Iterator is not empty!", empty.hasNext()); @@ -197,20 +219,20 @@ public void retrieve_empty_iterator_if_storage_is_empty() { @SuppressWarnings("ConstantConditions") // Converter nullability issues @Test public void read_single_record_with_mask() { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); - final RecordStorage storage = getStorage(); + I id = newId(); + EntityRecord record = newStorageRecord(id); + RecordStorage storage = getStorage(); storage.write(id, record); - final Descriptors.Descriptor descriptor = newState(id).getDescriptorForType(); - final FieldMask idMask = FieldMasks.maskOf(descriptor, 1); + Descriptors.Descriptor descriptor = newState(id).getDescriptorForType(); + FieldMask idMask = FieldMasks.maskOf(descriptor, 1); - final RecordReadRequest readRequest = new RecordReadRequest<>(id); - final Optional optional = storage.read(readRequest, idMask); + RecordReadRequest readRequest = new RecordReadRequest<>(id); + Optional optional = storage.read(readRequest, idMask); assertTrue(optional.isPresent()); - final EntityRecord entityRecord = optional.get(); + EntityRecord entityRecord = optional.get(); - final Message unpacked = unpack(entityRecord.getState()); + Message unpacked = unpack(entityRecord.getState()); assertFalse(isDefault(unpacked)); } @@ -218,15 +240,15 @@ public void read_single_record_with_mask() { // Converter nullability issues @Test public void read_multiple_records_with_field_mask() { - final RecordStorage storage = getStorage(); - final int count = 10; - final List ids = new LinkedList<>(); + RecordStorage storage = getStorage(); + int count = 10; + List ids = new LinkedList<>(); Descriptors.Descriptor typeDescriptor = null; for (int i = 0; i < count; i++) { - final I id = newId(); - final Message state = newState(id); - final EntityRecord record = newStorageRecord(state); + I id = newId(); + Message state = newState(id); + EntityRecord record = newStorageRecord(state); storage.write(id, record); ids.add(id); @@ -235,15 +257,15 @@ public void read_multiple_records_with_field_mask() { } } - final int bulkCount = count / 2; - final FieldMask fieldMask = FieldMasks.maskOf(typeDescriptor, 2); - final Iterator readRecords = storage.readMultiple( + int bulkCount = count / 2; + FieldMask fieldMask = FieldMasks.maskOf(typeDescriptor, 2); + Iterator readRecords = storage.readMultiple( ids.subList(0, bulkCount), fieldMask); - final List readList = newArrayList(readRecords); + List readList = newArrayList(readRecords); assertSize(bulkCount, readList); for (EntityRecord record : readList) { - final Message state = unpack(record.getState()); + Message state = unpack(record.getState()); assertMatchesMask(state, fieldMask); } } @@ -251,9 +273,9 @@ public void read_multiple_records_with_field_mask() { @SuppressWarnings("ConstantConditions") // converter nullability issues @Test public void delete_record() { - final RecordStorage storage = getStorage(); - final I id = newId(); - final EntityRecord record = newStorageRecord(id); + RecordStorage storage = getStorage(); + I id = newId(); + EntityRecord record = newStorageRecord(id); // Write the record. storage.write(id, record); @@ -262,17 +284,17 @@ public void delete_record() { assertTrue(storage.delete(id)); // There's no record with such ID. - final RecordReadRequest readRequest = newReadRequest(id); + RecordReadRequest readRequest = newReadRequest(id); assertFalse(storage.read(readRequest) .isPresent()); } @Test public void write_none_storage_fields_is_none_passed() { - final RecordStorage storage = spy(getStorage()); - final I id = newId(); - final Any state = pack(Sample.messageOfType(Project.class)); - final EntityRecord record = + RecordStorage storage = spy(getStorage()); + I id = newId(); + Any state = pack(Sample.messageOfType(Project.class)); + EntityRecord record = Sample.builderForType(EntityRecord.class) .setState(state) .build(); @@ -282,23 +304,23 @@ public void write_none_storage_fields_is_none_passed() { @Test public void write_record_bulk() { - final RecordStorage storage = getStorage(); - final int bulkSize = 5; + RecordStorage storage = getStorage(); + int bulkSize = 5; - final Map initial = new HashMap<>(bulkSize); + Map initial = new HashMap<>(bulkSize); for (int i = 0; i < bulkSize; i++) { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); + I id = newId(); + EntityRecord record = newStorageRecord(id); initial.put(id, EntityRecordWithColumns.of(record)); } storage.write(initial); - final Collection actual = newArrayList( + Collection actual = newArrayList( storage.readMultiple(initial.keySet()) ); - final Collection expected = Collections2.transform(initial.values(), - RECORD_EXTRACTOR_FUNCTION); + Collection expected = + Collections2.transform(initial.values(), EntityRecordWithColumns::getRecord); assertEquals(expected.size(), actual.size()); assertTrue(actual.containsAll(expected)); @@ -308,71 +330,70 @@ public void write_record_bulk() { @Test public void rewrite_records_in_bulk() { - final int recordCount = 3; - final RecordStorage storage = getStorage(); + int recordCount = 3; + RecordStorage storage = getStorage(); - final Function recordPacker = + Function recordPacker = new Function() { - @Nullable @Override - public EntityRecordWithColumns apply(@Nullable EntityRecord record) { + public @Nullable EntityRecordWithColumns apply(@Nullable EntityRecord record) { if (record == null) { return null; } return withLifecycleColumns(record); } }; - final Map v1Records = new HashMap<>(recordCount); - final Map v2Records = new HashMap<>(recordCount); + Map v1Records = new HashMap<>(recordCount); + Map v2Records = new HashMap<>(recordCount); for (int i = 0; i < recordCount; i++) { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); + I id = newId(); + EntityRecord record = newStorageRecord(id); // Some records are changed and some are not - final EntityRecord alternateRecord = (i % 2 == 0) - ? record - : newStorageRecord(id); + EntityRecord alternateRecord = (i % 2 == 0) + ? record + : newStorageRecord(id); v1Records.put(id, record); v2Records.put(id, alternateRecord); } storage.write(Maps.transformValues(v1Records, recordPacker)); - final Iterator firstRevision = storage.readAll(); + Iterator firstRevision = storage.readAll(); assertIteratorsEqual(v1Records.values() .iterator(), firstRevision); storage.write(Maps.transformValues(v2Records, recordPacker)); - final Iterator secondRevision = storage.readAll(); + Iterator secondRevision = storage.readAll(); assertIteratorsEqual(v2Records.values() .iterator(), secondRevision); } @Test(expected = IllegalStateException.class) public void fail_to_write_visibility_to_non_existing_record() { - final I id = newId(); - final RecordStorage storage = getStorage(); + I id = newId(); + RecordStorage storage = getStorage(); storage.writeLifecycleFlags(id, archived()); } @Test public void return_absent_visibility_for_missing_record() { - final I id = newId(); - final RecordStorage storage = getStorage(); - final Optional optional = storage.readLifecycleFlags(id); + I id = newId(); + RecordStorage storage = getStorage(); + Optional optional = storage.readLifecycleFlags(id); assertFalse(optional.isPresent()); } @SuppressWarnings("ConstantConditions") // Converter nullability issues @Test public void return_default_visibility_for_new_record() { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); - final RecordStorage storage = getStorage(); + I id = newId(); + EntityRecord record = newStorageRecord(id); + RecordStorage storage = getStorage(); storage.write(id, record); - final Optional optional = storage.readLifecycleFlags(id); + Optional optional = storage.readLifecycleFlags(id); assertTrue(optional.isPresent()); assertEquals(LifecycleFlags.getDefaultInstance(), optional.get()); } @@ -380,14 +401,14 @@ public void return_default_visibility_for_new_record() { @SuppressWarnings("OptionalGetWithoutIsPresent") // We verify in assertion. @Test public void load_visibility_when_updated() { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); - final RecordStorage storage = getStorage(); + I id = newId(); + EntityRecord record = newStorageRecord(id); + RecordStorage storage = getStorage(); storage.write(id, EntityRecordWithColumns.of(record)); storage.writeLifecycleFlags(id, archived()); - final Optional optional = storage.readLifecycleFlags(id); + Optional optional = storage.readLifecycleFlags(id); assertTrue(optional.isPresent()); assertTrue(optional.get() .getArchived()); @@ -395,30 +416,30 @@ public void load_visibility_when_updated() { @Test public void accept_records_with_empty_storage_fields() { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); - final EntityRecordWithColumns recordWithStorageFields = EntityRecordWithColumns.of(record); + I id = newId(); + EntityRecord record = newStorageRecord(id); + EntityRecordWithColumns recordWithStorageFields = EntityRecordWithColumns.of(record); assertFalse(recordWithStorageFields.hasColumns()); - final RecordStorage storage = getStorage(); + RecordStorage storage = getStorage(); storage.write(id, recordWithStorageFields); - final RecordReadRequest readRequest = newReadRequest(id); - final Optional actualRecord = storage.read(readRequest); + RecordReadRequest readRequest = newReadRequest(id); + Optional actualRecord = storage.read(readRequest); assertTrue(actualRecord.isPresent()); assertEquals(record, actualRecord.get()); } @Test public void write_record_with_columns() { - final I id = newId(); - final EntityRecord record = newStorageRecord(id); - final TestCounterEntity testEntity = new TestCounterEntity<>(id); - final RecordStorage storage = getStorage(); - final EntityRecordWithColumns recordWithColumns = create(record, testEntity, storage); + I id = newId(); + EntityRecord record = newStorageRecord(id); + TestCounterEntity testEntity = new TestCounterEntity<>(id); + RecordStorage storage = getStorage(); + EntityRecordWithColumns recordWithColumns = create(record, testEntity, storage); storage.write(id, recordWithColumns); - final RecordReadRequest readRequest = newReadRequest(id); - final Optional readRecord = storage.read(readRequest); + RecordReadRequest readRequest = newReadRequest(id); + Optional readRecord = storage.read(readRequest); assertTrue(readRecord.isPresent()); assertEquals(record, readRecord.get()); } @@ -426,35 +447,39 @@ public void write_record_with_columns() { @SuppressWarnings("OverlyLongMethod") // Complex test case (still tests a single operation) @Test public void filter_records_by_columns() { - final Project.Status requiredValue = DONE; - final Int32Value wrappedValue = Int32Value.newBuilder() - .setValue(requiredValue.getNumber()) - .build(); - final Version versionValue = Version.newBuilder() - .setNumber(2) // Value of the counter after one columns - .build(); // scan (incremented 2 times internally) - - final ColumnFilter status = eq("projectStatusValue", wrappedValue); - final ColumnFilter version = eq("counterVersion", versionValue); - final CompositeColumnFilter aggregatingFilter = CompositeColumnFilter.newBuilder() - .setOperator(ALL) - .addFilter(status) - .addFilter(version) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(aggregatingFilter) - .build(); - - final RecordStorage storage = getStorage(); - - final EntityQuery query = EntityQueries.from(filters, storage); - final I idMatching = newId(); - final I idWrong1 = newId(); - final I idWrong2 = newId(); - - final TestCounterEntity matchingEntity = new TestCounterEntity<>(idMatching); - final TestCounterEntity wrongEntity1 = new TestCounterEntity<>(idWrong1); - final TestCounterEntity wrongEntity2 = new TestCounterEntity<>(idWrong2); + Project.Status requiredValue = DONE; + Int32Value wrappedValue = Int32Value + .newBuilder() + .setValue(requiredValue.getNumber()) + .build(); + Version versionValue = Version + .newBuilder() + .setNumber(2) // Value of the counter after one columns + .build(); // scan (incremented 2 times internally) + + ColumnFilter status = eq("projectStatusValue", wrappedValue); + ColumnFilter version = eq("counterVersion", versionValue); + CompositeColumnFilter aggregatingFilter = CompositeColumnFilter + .newBuilder() + .setOperator(ALL) + .addFilter(status) + .addFilter(version) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .addFilter(aggregatingFilter) + .build(); + + RecordStorage storage = getStorage(); + + EntityQuery query = EntityQueries.from(filters, storage); + I idMatching = newId(); + I idWrong1 = newId(); + I idWrong2 = newId(); + + TestCounterEntity matchingEntity = new TestCounterEntity<>(idMatching); + TestCounterEntity wrongEntity1 = new TestCounterEntity<>(idWrong1); + TestCounterEntity wrongEntity2 = new TestCounterEntity<>(idWrong2); // 2 of 3 have required values matchingEntity.setStatus(requiredValue); @@ -466,87 +491,89 @@ public void filter_records_by_columns() { // After the mutation above the single matching record is the one under the `idMatching` ID - final EntityRecord fineRecord = newStorageRecord(idMatching, newState(idMatching)); - final EntityRecord notFineRecord1 = newStorageRecord(idWrong1, newState(idWrong1)); - final EntityRecord notFineRecord2 = newStorageRecord(idWrong2, newState(idWrong2)); + EntityRecord fineRecord = newStorageRecord(idMatching, newState(idMatching)); + EntityRecord notFineRecord1 = newStorageRecord(idWrong1, newState(idWrong1)); + EntityRecord notFineRecord2 = newStorageRecord(idWrong2, newState(idWrong2)); - final EntityRecordWithColumns recordRight = create(fineRecord, matchingEntity, storage); - final EntityRecordWithColumns recordWrong1 = create(notFineRecord1, wrongEntity1, storage); - final EntityRecordWithColumns recordWrong2 = create(notFineRecord2, wrongEntity2, storage); + EntityRecordWithColumns recordRight = create(fineRecord, matchingEntity, storage); + EntityRecordWithColumns recordWrong1 = create(notFineRecord1, wrongEntity1, storage); + EntityRecordWithColumns recordWrong2 = create(notFineRecord2, wrongEntity2, storage); storage.write(idMatching, recordRight); storage.write(idWrong1, recordWrong1); storage.write(idWrong2, recordWrong2); - final Iterator readRecords = storage.readAll(query, - FieldMask.getDefaultInstance()); + Iterator readRecords = storage.readAll(query, + FieldMask.getDefaultInstance()); assertSingleRecord(fineRecord, readRecords); } @Test public void update_entity_column_values() { - final Project.Status initialStatus = DONE; + Project.Status initialStatus = DONE; @SuppressWarnings("UnnecessaryLocalVariable") // is used for documentation purposes. - final Project.Status statusAfterUpdate = CANCELLED; - final Int32Value initialStatusValue = Int32Value.newBuilder() - .setValue(initialStatus.getNumber()) - .build(); - final ColumnFilter status = eq("projectStatusValue", initialStatusValue); - final CompositeColumnFilter aggregatingFilter = CompositeColumnFilter.newBuilder() - .setOperator(ALL) - .addFilter(status) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(aggregatingFilter) - .build(); - - final RecordStorage storage = getStorage(); - - final EntityQuery query = EntityQueries.from(filters, storage); - - final I id = newId(); - final TestCounterEntity entity = new TestCounterEntity<>(id); + Project.Status statusAfterUpdate = CANCELLED; + Int32Value initialStatusValue = Int32Value.newBuilder() + .setValue(initialStatus.getNumber()) + .build(); + ColumnFilter status = eq("projectStatusValue", initialStatusValue); + CompositeColumnFilter aggregatingFilter = CompositeColumnFilter + .newBuilder() + .setOperator(ALL) + .addFilter(status) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .addFilter(aggregatingFilter) + .build(); + + RecordStorage storage = getStorage(); + + EntityQuery query = EntityQueries.from(filters, storage); + + I id = newId(); + TestCounterEntity entity = new TestCounterEntity<>(id); entity.setStatus(initialStatus); - final EntityRecord record = newStorageRecord(id, newState(id)); - final EntityRecordWithColumns recordWithColumns = create(record, entity, storage); + EntityRecord record = newStorageRecord(id, newState(id)); + EntityRecordWithColumns recordWithColumns = create(record, entity, storage); - final FieldMask fieldMask = FieldMask.getDefaultInstance(); + FieldMask fieldMask = FieldMask.getDefaultInstance(); // Create the record. storage.write(id, recordWithColumns); - final Iterator recordsBefore = storage.readAll(query, fieldMask); + Iterator recordsBefore = storage.readAll(query, fieldMask); assertSingleRecord(record, recordsBefore); // Update the entity columns of the record. entity.setStatus(statusAfterUpdate); - final EntityRecordWithColumns updatedRecordWithColumns = create(record, entity, storage); + EntityRecordWithColumns updatedRecordWithColumns = create(record, entity, storage); storage.write(id, updatedRecordWithColumns); - final Iterator recordsAfter = storage.readAll(query, fieldMask); + Iterator recordsAfter = storage.readAll(query, fieldMask); assertFalse(recordsAfter.hasNext()); } @Test public void allow_by_single_id_queries_with_no_columns() { // Create the test data - final I idMatching = newId(); - final I idWrong1 = newId(); - final I idWrong2 = newId(); + I idMatching = newId(); + I idWrong1 = newId(); + I idWrong2 = newId(); - final TestCounterEntity matchingEntity = new TestCounterEntity<>(idMatching); - final TestCounterEntity wrongEntity1 = new TestCounterEntity<>(idWrong1); - final TestCounterEntity wrongEntity2 = new TestCounterEntity<>(idWrong2); + TestCounterEntity matchingEntity = new TestCounterEntity<>(idMatching); + TestCounterEntity wrongEntity1 = new TestCounterEntity<>(idWrong1); + TestCounterEntity wrongEntity2 = new TestCounterEntity<>(idWrong2); - final EntityRecord fineRecord = newStorageRecord(idMatching, newState(idMatching)); - final EntityRecord notFineRecord1 = newStorageRecord(idWrong1, newState(idWrong1)); - final EntityRecord notFineRecord2 = newStorageRecord(idWrong2, newState(idWrong2)); + EntityRecord fineRecord = newStorageRecord(idMatching, newState(idMatching)); + EntityRecord notFineRecord1 = newStorageRecord(idWrong1, newState(idWrong1)); + EntityRecord notFineRecord2 = newStorageRecord(idWrong2, newState(idWrong2)); - final RecordStorage storage = getStorage(); + RecordStorage storage = getStorage(); - final EntityRecordWithColumns recordRight = create(fineRecord, matchingEntity, storage); - final EntityRecordWithColumns recordWrong1 = create(notFineRecord1, wrongEntity1, storage); - final EntityRecordWithColumns recordWrong2 = create(notFineRecord2, wrongEntity2, storage); + EntityRecordWithColumns recordRight = create(fineRecord, matchingEntity, storage); + EntityRecordWithColumns recordWrong1 = create(notFineRecord1, wrongEntity1, storage); + EntityRecordWithColumns recordWrong2 = create(notFineRecord2, wrongEntity2, storage); // Fill the storage storage.write(idWrong1, recordWrong1); @@ -554,91 +581,96 @@ public void allow_by_single_id_queries_with_no_columns() { storage.write(idWrong2, recordWrong2); // Prepare the query - final Any matchingIdPacked = TypeConverter.toAny(idMatching); - final EntityId entityId = EntityId.newBuilder() - .setId(matchingIdPacked) - .build(); - final EntityIdFilter idFilter = EntityIdFilter.newBuilder() - .addIds(entityId) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .setIdFilter(idFilter) - .build(); - final EntityQuery query = EntityQueries.from(filters, storage); + Any matchingIdPacked = TypeConverter.toAny(idMatching); + EntityId entityId = EntityId + .newBuilder() + .setId(matchingIdPacked) + .build(); + EntityIdFilter idFilter = EntityIdFilter + .newBuilder() + .addIds(entityId) + .build(); + EntityFilters filters = EntityFilters + .newBuilder() + .setIdFilter(idFilter) + .build(); + EntityQuery query = EntityQueries.from(filters, storage); // Perform the query - final Iterator readRecords = storage.readAll(query, - FieldMask.getDefaultInstance()); + Iterator readRecords = + storage.readAll(query, FieldMask.getDefaultInstance()); // Check results assertSingleRecord(fineRecord, readRecords); } @Test public void read_archived_records_if_specified() { - final I activeRecordId = newId(); - final I archivedRecordId = newId(); - - final EntityRecord activeRecord = newStorageRecord(activeRecordId, - newState(activeRecordId)); - final EntityRecord archivedRecord = newStorageRecord(archivedRecordId, - newState(archivedRecordId)); - final TestCounterEntity activeEntity = new TestCounterEntity<>(activeRecordId); - final TestCounterEntity archivedEntity = new TestCounterEntity<>(archivedRecordId); + I activeRecordId = newId(); + I archivedRecordId = newId(); + + EntityRecord activeRecord = + newStorageRecord(activeRecordId, newState(activeRecordId)); + EntityRecord archivedRecord = + newStorageRecord(archivedRecordId, newState(archivedRecordId)); + TestCounterEntity activeEntity = new TestCounterEntity<>(activeRecordId); + TestCounterEntity archivedEntity = new TestCounterEntity<>(archivedRecordId); archivedEntity.archive(); - final RecordStorage storage = getStorage(); + RecordStorage storage = getStorage(); storage.write(activeRecordId, create(activeRecord, activeEntity, storage)); storage.write(archivedRecordId, create(archivedRecord, archivedEntity, storage)); - final EntityFilters filters = EntityFilters.newBuilder() - .addFilter(all(eq(archived.toString(), true))) - .build(); - final EntityQuery query = EntityQueries.from(filters, storage); - final Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); + EntityFilters filters = EntityFilters + .newBuilder() + .addFilter(all(eq(archived.toString(), true))) + .build(); + EntityQuery query = EntityQueries.from(filters, storage); + Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); assertSingleRecord(archivedRecord, read); } @Test public void filter_archived_or_deleted_records_on_by_ID_bulk_read() { - final I activeId = newId(); - final I archivedId = newId(); - final I deletedId = newId(); + I activeId = newId(); + I archivedId = newId(); + I deletedId = newId(); - final TestCounterEntity activeEntity = new TestCounterEntity<>(activeId); - final TestCounterEntity archivedEntity = new TestCounterEntity<>(archivedId); + TestCounterEntity activeEntity = new TestCounterEntity<>(activeId); + TestCounterEntity archivedEntity = new TestCounterEntity<>(archivedId); archivedEntity.archive(); - final TestCounterEntity deletedEntity = new TestCounterEntity<>(deletedId); + TestCounterEntity deletedEntity = new TestCounterEntity<>(deletedId); deletedEntity.delete(); - final EntityRecord activeRecord = newStorageRecord(activeId, activeEntity.getState()); - final EntityRecord archivedRecord = newStorageRecord(archivedId, archivedEntity.getState()); - final EntityRecord deletedRecord = newStorageRecord(deletedId, deletedEntity.getState()); + EntityRecord activeRecord = newStorageRecord(activeId, activeEntity.getState()); + EntityRecord archivedRecord = newStorageRecord(archivedId, archivedEntity.getState()); + EntityRecord deletedRecord = newStorageRecord(deletedId, deletedEntity.getState()); - final RecordStorage storage = getStorage(); + RecordStorage storage = getStorage(); storage.write(deletedId, create(deletedRecord, deletedEntity, storage)); storage.write(activeId, create(activeRecord, activeEntity, storage)); storage.write(archivedId, create(archivedRecord, archivedEntity, storage)); - final EntityIdFilter idFilter = EntityIdFilter.newBuilder() - .addIds(toEntityId(activeId)) - .addIds(toEntityId(archivedId)) - .addIds(toEntityId(deletedId)) - .build(); - final EntityFilters filters = EntityFilters.newBuilder() - .setIdFilter(idFilter) - .build(); - final EntityQuery query = EntityQueries.from(filters, storage) - .withLifecycleFlags(storage); - final Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); + EntityIdFilter idFilter = EntityIdFilter + .newBuilder() + .addIds(toEntityId(activeId)) + .addIds(toEntityId(archivedId)) + .addIds(toEntityId(deletedId)) + .build(); + EntityFilters filters = EntityFilters.newBuilder() + .setIdFilter(idFilter) + .build(); + EntityQuery query = EntityQueries.from(filters, storage) + .withLifecycleFlags(storage); + Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); assertSingleRecord(activeRecord, read); } @Test public void read_both_by_columns_and_IDs() { - final I targetId = newId(); - final TestCounterEntity targetEntity = new TestCounterEntity<>(targetId); - final TestCounterEntity noMatchEntity = new TestCounterEntity<>(newId()); - final TestCounterEntity noMatchIdEntity = new TestCounterEntity<>(newId()); - final TestCounterEntity deletedEntity = new TestCounterEntity<>(newId()); + I targetId = newId(); + TestCounterEntity targetEntity = new TestCounterEntity<>(targetId); + TestCounterEntity noMatchEntity = new TestCounterEntity<>(newId()); + TestCounterEntity noMatchIdEntity = new TestCounterEntity<>(newId()); + TestCounterEntity deletedEntity = new TestCounterEntity<>(newId()); targetEntity.setStatus(CANCELLED); deletedEntity.setStatus(CANCELLED); @@ -651,22 +683,24 @@ public void read_both_by_columns_and_IDs() { write(noMatchIdEntity); write(deletedEntity); - final EntityIdFilter idFilter = EntityIdFilter.newBuilder() - .addIds(toEntityId(targetId)) - .build(); - final CompositeColumnFilter columnFilter = all(eq("projectStatusValue", - CANCELLED.getNumber())); - final EntityFilters filters = EntityFilters.newBuilder() - .setIdFilter(idFilter) - .addFilter(columnFilter) - .build(); - final RecordStorage storage = getStorage(); - final EntityQuery query = EntityQueries.from(filters, storage) - .withLifecycleFlags(storage); - final Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); - final List readRecords = newArrayList(read); + EntityIdFilter idFilter = EntityIdFilter + .newBuilder() + .addIds(toEntityId(targetId)) + .build(); + CompositeColumnFilter columnFilter = + all(eq("projectStatusValue", CANCELLED.getNumber())); + EntityFilters filters = EntityFilters + .newBuilder() + .setIdFilter(idFilter) + .addFilter(columnFilter) + .build(); + RecordStorage storage = getStorage(); + EntityQuery query = EntityQueries.from(filters, storage) + .withLifecycleFlags(storage); + Iterator read = storage.readAll(query, FieldMask.getDefaultInstance()); + List readRecords = newArrayList(read); assertEquals(1, readRecords.size()); - final EntityRecord readRecord = readRecords.get(0); + EntityRecord readRecord = readRecords.get(0); assertEquals(targetEntity.getState(), unpack(readRecord.getState())); assertEquals(targetId, Identifier.unpack(readRecord.getEntityId())); } @@ -675,72 +709,72 @@ public void read_both_by_columns_and_IDs() { checking via #contains(Object). */) @Test public void create_unique_states_for_same_ID() { - final int checkCount = 10; - final I id = newId(); - final Set states = newHashSet(); + int checkCount = 10; + I id = newId(); + Set states = newHashSet(); for (int i = 0; i < checkCount; i++) { - final Message newState = newState(id); + Message newState = newState(id); if (states.contains(newState)) { fail("RecordStorageShould.newState() should return unique messages."); } } } - protected static EntityRecordWithColumns withLifecycleColumns(EntityRecord record) { - final LifecycleFlags flags = record.getLifecycleFlags(); - final Map columns = ImmutableMap.of( - LifecycleColumns.ARCHIVED.columnName(), - booleanColumn(LifecycleColumns.ARCHIVED.column(), flags.getArchived()), - LifecycleColumns.DELETED.columnName(), - booleanColumn(LifecycleColumns.DELETED.column(), flags.getDeleted()) - ); - final EntityRecordWithColumns result = createRecord(record, columns); - return result; + private EntityId toEntityId(I id) { + Any packed = Identifier.pack(id); + EntityId entityId = EntityId.newBuilder() + .setId(packed) + .build(); + return entityId; } - private static MemoizedValue booleanColumn(EntityColumn column, boolean value) { - final MemoizedValue memoizedValue = mock(MemoizedValue.class); - when(memoizedValue.getSourceColumn()).thenReturn(column); - when(memoizedValue.getValue()).thenReturn(value); - return memoizedValue; + private void write(Entity entity) { + RecordStorage storage = getStorage(); + EntityRecord record = newStorageRecord(entity.getId(), entity.getState()); + storage.write(entity.getId(), create(record, entity, storage)); } - private static EntityRecordWithColumns withRecordAndNoFields(final EntityRecord record) { - return argThat(new ArgumentMatcher() { - @Override - public boolean matches(EntityRecordWithColumns argument) { - return argument.getRecord() - .equals(record) - && !argument.hasColumns(); - } - }); - } + /** + * Entity columns representing lifecycle flags, {@code archived} and {@code deleted}. + * + *

These columns are present in each {@link EntityWithLifecycle} entity. For the purpose of + * tests being as close to the real production environment as possible, these columns are stored + * with the entity records, even if an actual entity is missing. + * + *

Note that there are cases, when a {@code RecordStorage} stores entity records with no such + * columns, e.g. the {@linkplain io.spine.server.event.EEntity event entity}. Thus, do not rely + * on these columns being present in all the entities by default when implementing + * a {@code RecordStorage}. + */ + enum LifecycleColumns { - private static void assertSingleRecord(EntityRecord expected, Iterator actual) { - assertTrue(actual.hasNext()); - final EntityRecord singleRecord = actual.next(); - assertFalse(actual.hasNext()); - assertEquals(expected, singleRecord); - } + ARCHIVED("isArchived"), + DELETED("isDeleted"); - private EntityId toEntityId(I id) { - final Any packed = Identifier.pack(id); - final EntityId entityId = EntityId.newBuilder() - .setId(packed) - .build(); - return entityId; - } + private final EntityColumn column; - private void write(Entity entity) { - final RecordStorage storage = getStorage(); - final EntityRecord record = newStorageRecord(entity.getId(), entity.getState()); - storage.write(entity.getId(), create(record, entity, storage)); + LifecycleColumns(String getterName) { + try { + this.column = EntityColumn.from( + EntityWithLifecycle.class.getDeclaredMethod(getterName) + ); + } catch (NoSuchMethodException e) { + throw illegalStateWithCauseOf(e); + } + } + + EntityColumn column() { + return column; + } + + String columnName() { + return column.getStoredName(); + } } @SuppressWarnings("unused") // Reflective access - public static class TestCounterEntity extends EventPlayingEntity { + public static class TestCounterEntity + extends EventPlayingEntity { private int counter = 0; @@ -748,6 +782,7 @@ protected TestCounterEntity(I id) { super(id); } + @CanIgnoreReturnValue @Column public int getCounter() { counter++; @@ -807,42 +842,4 @@ private void delete() { TestTransaction.delete(this); } } - - /** - * Entity columns representing lifecycle flags, {@code archived} and {@code deleted}. - * - *

These columns are present in each {@link EntityWithLifecycle} entity. For the purpose of - * tests being as close to the real production environment as possible, these columns are stored - * with the entity records, even if an actual entity is missing. - * - *

Note that there are cases, when a {@code RecordStorage} stores entity records with no such - * columns, e.g. the {@linkplain io.spine.server.event.EEntity event entity}. Thus, do not rely - * on these columns being present in all the entities by default when implementing - * a {@code RecordStorage}. - */ - enum LifecycleColumns { - - ARCHIVED("isArchived"), - DELETED("isDeleted"); - - private final EntityColumn column; - - LifecycleColumns(String getterName) { - try { - this.column = EntityColumn.from( - EntityWithLifecycle.class.getDeclaredMethod(getterName) - ); - } catch (NoSuchMethodException e) { - throw illegalStateWithCauseOf(e); - } - } - - EntityColumn column() { - return column; - } - - String columnName() { - return column.getStoredName(); - } - } } diff --git a/server/src/test/java/io/spine/server/storage/StorageFactorySwitchShould.java b/server/src/test/java/io/spine/server/storage/StorageFactorySwitchShould.java index 0d164df40cb..ca6690aa0d1 100644 --- a/server/src/test/java/io/spine/server/storage/StorageFactorySwitchShould.java +++ b/server/src/test/java/io/spine/server/storage/StorageFactorySwitchShould.java @@ -28,7 +28,9 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.server.BoundedContext.newName; import static org.junit.Assert.assertEquals; @@ -46,37 +48,23 @@ */ public class StorageFactorySwitchShould { - // Environment protection START + /** + * Cached {@code Environment value} remembered {@linkplain #storeEnvironment() before all tests} + * and restored {@linkplain #restoreEnvironment() after all tests}. + */ @SuppressWarnings("StaticVariableMayNotBeInitialized") - // OK as we use the field after the initialization in storeEnvironment(). + // OK as we use the field after the initialization in storeEnvironment(). private static Environment storedEnvironment; - @BeforeClass - public static void storeEnvironment() { - storedEnvironment = Environment.getInstance().createCopy(); - } - - @SuppressWarnings("StaticVariableUsedBeforeInitialization") - // OK as we invoke after the initialization in storeEnvironment(). - @AfterClass - public static void restoreEnvironment() { - Environment.getInstance() - .restoreFrom(storedEnvironment); - } - // Environment protection END - - private StorageFactorySwitch storageFactorySwitch; - private final boolean multitenant; - private final BoundedContextName boundedContextName = newName(getClass().getSimpleName()); + private final Supplier testsSupplier = new Supplier() { @Override public StorageFactory get() { return InMemoryStorageFactory.newInstance(boundedContextName, multitenant); } }; - private final Supplier productionSupplier = new Supplier() { @Override public StorageFactory get() { @@ -84,7 +72,12 @@ public StorageFactory get() { } }; - protected StorageFactorySwitchShould(boolean multitenant) { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private StorageFactorySwitch storageFactorySwitch; + + StorageFactorySwitchShould(boolean multitenant) { this.multitenant = multitenant; } @@ -92,15 +85,30 @@ public StorageFactorySwitchShould() { this(false); } + @BeforeClass + public static void storeEnvironment() { + storedEnvironment = Environment.getInstance() + .createCopy(); + } + + @SuppressWarnings("StaticVariableUsedBeforeInitialization") + // OK as we invoke after the initialization in storeEnvironment(). + @AfterClass + public static void restoreEnvironment() { + Environment.getInstance() + .restoreFrom(storedEnvironment); + } + @Before - public void setUp() throws NoSuchFieldException, IllegalAccessException { + public void setUp() { storageFactorySwitch = StorageFactorySwitch.newInstance(boundedContextName, multitenant); } @After - public void cleanUp() throws NoSuchFieldException, IllegalAccessException { + public void cleanUp() { clearSwitch(); - Environment.getInstance().reset(); + Environment.getInstance() + .reset(); } /** @@ -112,7 +120,7 @@ private void clearSwitch() { @Test public void return_InMemoryStorageFactory_in_tests_if_tests_supplier_was_not_set() { - final StorageFactory storageFactory = storageFactorySwitch.get(); + StorageFactory storageFactory = storageFactorySwitch.get(); assertNotNull(storageFactory); assertTrue(storageFactory instanceof InMemoryStorageFactory); @@ -127,43 +135,43 @@ public void return_custom_test_StorageFactory_if_supplier_for_tests_was_set() { // Having this call avoids the problem. storageFactorySwitch.reset(); - final StorageFactory custom = mock(StorageFactory.class); + StorageFactory custom = mock(StorageFactory.class); - storageFactorySwitch.init(testsSupplier, new Supplier() { - @Override - public StorageFactory get() { - return custom; - } - }); + storageFactorySwitch.init(testsSupplier, () -> custom); // These calls ensure that we're under the testing mode and we get the supplier for tests. - assertTrue(Environment.getInstance().isTests()); + assertTrue(Environment.getInstance() + .isTests()); assertTrue(storageFactorySwitch.testsSupplier() .isPresent()); // Get the StorageFactory from the switch. - final StorageFactory obtained = storageFactorySwitch.get(); + StorageFactory obtained = storageFactorySwitch.get(); assertEquals(custom, obtained); } @SuppressWarnings("AccessOfSystemProperties") // OK for this test. - @Test(expected = IllegalStateException.class) - public void throw_IllegalStateException_if_production_supplier_is_non_tests_mode() - throws NoSuchFieldException, IllegalAccessException { + @Test + public void throw_IllegalStateException_if_production_supplier_is_non_tests_mode() { // Clear cached value for tests mode that may be left from the previous tests. - Environment.getInstance().reset(); + Environment.getInstance() + .reset(); // Pretend that we are not under tests for the `Environment`. - Environment.getInstance().setToProduction(); + Environment.getInstance() + .setToProduction(); assertFalse(storageFactorySwitch.productionSupplier() .isPresent()); + + thrown.expect(IllegalStateException.class); storageFactorySwitch.get(); } + @SuppressWarnings("CheckReturnValue") // ignore value of get() since we tests caching @Test public void cache_instance_of_StorageFactory_in_testing() { - final Supplier testingSupplier = spy(testsSupplier); + Supplier testingSupplier = spy(testsSupplier); storageFactorySwitch.init(productionSupplier, testingSupplier); @@ -176,9 +184,10 @@ public void cache_instance_of_StorageFactory_in_testing() { verify(testingSupplier, times(1)).get(); } + @SuppressWarnings("CheckReturnValue") // ignore value of get() since we tests caching @Test public void cache_instance_of_StorageFactory_in_production() { - final Supplier prodSupplier = spy(productionSupplier); + Supplier prodSupplier = spy(productionSupplier); storageFactorySwitch.init(prodSupplier, testsSupplier); @@ -193,7 +202,7 @@ public void cache_instance_of_StorageFactory_in_production() { @Test public void return_itself_on_init() { - final StorageFactorySwitch result = storageFactorySwitch.init(testsSupplier, testsSupplier); + StorageFactorySwitch result = storageFactorySwitch.init(testsSupplier, testsSupplier); assertSame(storageFactorySwitch, result); } } From 95e2f77d9f4d9f95935cb166e0b84ec9a1bc6292 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 02:44:49 +0300 Subject: [PATCH 14/53] Handle ignored return values --- .../projection/ProjectionRepository.java | 119 ++++++----- .../entity/ThrowingValidatingBuilder.java | 4 +- .../server/event/EventBusBuilderShould.java | 121 +++++------ .../server/event/EventFactoryShould.java | 18 +- .../event/EventStoreServiceBuilderShould.java | 33 ++- .../ProjectionRepositoryShould.java | 191 ++++++++++-------- .../ProjectionTransactionShould.java | 40 ++-- 7 files changed, 282 insertions(+), 244 deletions(-) diff --git a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java index 71411cd19f7..e8ef66f3c4a 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java @@ -21,7 +21,6 @@ package io.spine.server.projection; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.protobuf.Message; @@ -55,6 +54,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Set; +import java.util.function.Supplier; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Suppliers.memoize; @@ -73,14 +73,7 @@ public abstract class ProjectionRepository, S e implements Shardable { private final Supplier> eventDeliverySupplier = - memoize(new Supplier>() { - @Override - public ProjectionEventDelivery get() { - final ProjectionEventDelivery result - = new ProjectionEventDelivery<>(ProjectionRepository.this); - return result; - } - }); + memoize(() -> new ProjectionEventDelivery<>(this)); /** An underlying entity storage used to store projections. */ private RecordStorage recordStorage; @@ -89,7 +82,14 @@ public ProjectionEventDelivery get() { * Creates a new {@code ProjectionRepository}. */ protected ProjectionRepository() { - super(EventProducers.fromContext()); + super(EventProducers.fromContext()); + } + + @VisibleForTesting + static Timestamp nullToDefault(@Nullable Timestamp timestamp) { + return timestamp == null + ? Timestamp.getDefaultInstance() + : timestamp; } /** Obtains {@link EventStore} from which to get events during catch-up. */ @@ -99,7 +99,8 @@ EventStore getEventStore() { } /** Obtains class information of projection managed by this repository. */ - @SuppressWarnings("unchecked") // The cast is ensured by generic parameters of the repository. + @SuppressWarnings("unchecked") + // The cast is ensured by generic parameters of the repository. ProjectionClass

projectionClass() { return (ProjectionClass

) entityClass(); } @@ -112,8 +113,11 @@ protected final ProjectionClass

getModelClass(Class

cls) { } @Override - public ProjectionClass

getShardedModelClass() { - return projectionClass(); + public void close() { + ServerEnvironment.getInstance() + .getSharding() + .unregister(this); + super.close(); } /** @@ -126,10 +130,11 @@ public ProjectionClass

getShardedModelClass() { public void onRegistered() { super.onRegistered(); - final boolean noEventSubscriptions = getMessageClasses().isEmpty(); + boolean noEventSubscriptions = getMessageClasses().isEmpty(); if (noEventSubscriptions) { - final boolean noExternalSubscriptions = getExternalEventDispatcher().getMessageClasses() - .isEmpty(); + boolean noExternalSubscriptions = + getExternalEventDispatcher().getMessageClasses() + .isEmpty(); if (noExternalSubscriptions) { throw newIllegalStateException( "Projections of the repository %s have neither domestic nor external " + @@ -142,15 +147,20 @@ public void onRegistered() { .register(this); } + @Override + protected ExternalMessageDispatcher getExternalEventDispatcher() { + return new ProjectionExternalEventDispatcher(); + } + /** * Obtains event filters for event classes handled by projections of this repository. */ private Set createEventFilters() { - final ImmutableSet.Builder builder = ImmutableSet.builder(); - final Set eventClasses = getMessageClasses(); + ImmutableSet.Builder builder = ImmutableSet.builder(); + Set eventClasses = getMessageClasses(); for (EventClass eventClass : eventClasses) { - final String typeName = TypeName.of(eventClass.value()) - .value(); + String typeName = TypeName.of(eventClass.value()) + .value(); builder.add(EventFilter.newBuilder() .setEventType(typeName) .build()); @@ -158,13 +168,6 @@ private Set createEventFilters() { return builder.build(); } - @VisibleForTesting - static Timestamp nullToDefault(@Nullable Timestamp timestamp) { - return timestamp == null - ? Timestamp.getDefaultInstance() - : timestamp; - } - /** Opens access to the {@link BoundedContext} of the repository to the package. */ BoundedContext boundedContext() { return getBoundedContext(); @@ -182,11 +185,24 @@ protected final Stand getStand() { * *

Overrides to open the method to the package. */ + @SuppressWarnings("RedundantMethodOverride") // see Javadoc @Override protected EntityStorageConverter entityConverter() { return super.entityConverter(); } + /** + * Ensures that the repository has the storage. + * + * @return storage instance + * @throws IllegalStateException if the storage is null + */ + @Override + @SuppressWarnings("MethodDoesntCallSuperMethod") + protected RecordStorage recordStorage() { + return checkStorage(recordStorage); + } + @Override @SuppressWarnings("MethodDoesntCallSuperMethod" /* We do not call super.createStorage() because we create a specific type of a storage, not a regular entity storage created @@ -200,15 +216,13 @@ protected RecordStorage createStorage(StorageFactory factory) { } /** - * Ensures that the repository has the storage. + * {@inheritDoc} * - * @return storage instance - * @throws IllegalStateException if the storage is null + *

Overrides to expose the method to the package. */ @Override - @SuppressWarnings("MethodDoesntCallSuperMethod") - protected RecordStorage recordStorage() { - return checkStorage(recordStorage); + protected P findOrCreate(I id) { + return super.findOrCreate(id); } /** @@ -219,7 +233,7 @@ protected RecordStorage recordStorage() { */ protected ProjectionStorage projectionStorage() { @SuppressWarnings("unchecked") // OK as we control the creation in createStorage(). - final ProjectionStorage storage = (ProjectionStorage) getStorage(); + ProjectionStorage storage = (ProjectionStorage) getStorage(); return storage; } @@ -227,29 +241,28 @@ protected ProjectionStorage projectionStorage() { @Override public Set getMessageClasses() { return projectionClass().getEventSubscriptions(); - } - - @Override + } @Override public Set dispatch(EventEnvelope envelope) { return ProjectionEndpoint.handle(this, envelope); } @Internal public void writeLastHandledEventTime(Timestamp timestamp) { + checkNotNull(timestamp); projectionStorage().writeLastHandledEventTime(timestamp); } @Internal public Timestamp readLastHandledEventTime() { - return projectionStorage().readLastHandledEventTime(); + Timestamp timestamp = projectionStorage().readLastHandledEventTime(); + return nullToDefault(timestamp); } EventStreamQuery createStreamQuery() { - final Set eventFilters = createEventFilters(); + Set eventFilters = createEventFilters(); // Get the timestamp of the last event. This also ensures we have the storage. - final Timestamp timestamp = nullToDefault( - projectionStorage().readLastHandledEventTime()); + Timestamp timestamp = readLastHandledEventTime(); return EventStreamQuery.newBuilder() .setAfter(timestamp) .addAllFilter(eventFilters) @@ -272,26 +285,11 @@ protected ProjectionEventDelivery getEndpointDelivery() { return eventDeliverySupplier.get(); } - /** - * {@inheritDoc} - * - *

Overrides to expose the method to the package. - */ - @Override - protected P findOrCreate(I id) { - return super.findOrCreate(id); - } - /** Exposes routing to the package. */ EventRouting eventRouting() { return getEventRouting(); } - @Override - protected ExternalMessageDispatcher getExternalEventDispatcher() { - return new ProjectionExternalEventDispatcher(); - } - @Override public ShardingStrategy getShardingStrategy() { return UniformAcrossTargets.singleShard(); @@ -300,7 +298,7 @@ public ShardingStrategy getShardingStrategy() { @Override public Iterable> getMessageConsumers() { final Iterable> result = - ImmutableList.>of(getEndpointDelivery().getConsumer()); + ImmutableList.of(getEndpointDelivery().getConsumer()); return result; } @@ -311,11 +309,8 @@ public BoundedContextName getBoundedContextName() { } @Override - public void close() { - ServerEnvironment.getInstance() - .getSharding() - .unregister(this); - super.close(); + public ProjectionClass

getShardedModelClass() { + return projectionClass(); } /** diff --git a/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java b/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java index d12cd2908a1..7b1317ad45f 100644 --- a/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java +++ b/server/src/test/java/io/spine/server/entity/ThrowingValidatingBuilder.java @@ -22,7 +22,6 @@ import com.google.protobuf.Message; import io.spine.validate.AbstractValidatingBuilder; import io.spine.validate.ValidationException; - import org.checkerframework.checker.nullness.qual.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -36,8 +35,7 @@ public abstract class ThrowingValidatingBuilder extends AbstractValidatingBuilder { - @Nullable - private RuntimeException shouldThrow; + private @Nullable RuntimeException shouldThrow; @Override public M build() throws ValidationException { diff --git a/server/src/test/java/io/spine/server/event/EventBusBuilderShould.java b/server/src/test/java/io/spine/server/event/EventBusBuilderShould.java index 30817d519b0..4e38bb9a124 100644 --- a/server/src/test/java/io/spine/server/event/EventBusBuilderShould.java +++ b/server/src/test/java/io/spine/server/event/EventBusBuilderShould.java @@ -30,7 +30,9 @@ import io.spine.test.Tests; import io.spine.validate.MessageValidator; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -49,6 +51,9 @@ public class EventBusBuilderShould extends BusBuilderShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private StorageFactory storageFactory; @Override @@ -58,15 +63,17 @@ protected EventBus.Builder builder() { @Before public void setUp() { - final BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(true) - .build(); + BoundedContext bc = BoundedContext + .newBuilder() + .setMultitenant(true) + .build(); this.storageFactory = bc.getStorageFactory(); } - @Test(expected = NullPointerException.class) + @Test public void do_not_accept_null_EventStore() { - builder().setEventStore(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setEventStore(Tests.nullRef()); } @Test @@ -78,7 +85,7 @@ public void return_set_StorageFactory() { @Test public void return_EventStore_if_set() { - final EventStore mock = mock(EventStore.class); + EventStore mock = mock(EventStore.class); assertEquals(mock, builder().setEventStore(mock) .getEventStore() .get()); @@ -86,15 +93,16 @@ public void return_EventStore_if_set() { @Test public void return_stream_Executor_for_EventStore_if_set() { - final Executor mock = mock(Executor.class); + Executor mock = mock(Executor.class); assertEquals(mock, builder().setEventStoreStreamExecutor(mock) .getEventStoreStreamExecutor() .get()); } - @Test(expected = NullPointerException.class) + @Test public void do_not_accept_null_EventValidator() { - builder().setEventValidator(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder().setEventValidator(Tests.nullRef()); } @Test @@ -105,8 +113,9 @@ public void return_set_EventValidator() { .get()); } - @Test(expected = IllegalStateException.class) + @Test public void require_set_EventStore_or_StorageFactory() { + thrown.expect(IllegalStateException.class); EventBus.newBuilder() .build(); } @@ -120,14 +129,14 @@ public void set_event_validator_if_not_set_explicitly() { @Test public void accept_null_Enricher() { - assertNull(builder().setEnricher(Tests.nullRef()) + assertNull(builder().setEnricher(Tests.nullRef()) .getEnricher() .orNull()); } @Test public void return_set_Enricher() { - final EventEnricher enricher = mock(EventEnricher.class); + EventEnricher enricher = mock(EventEnricher.class); assertEquals(enricher, builder().setStorageFactory(storageFactory) .setEnricher(enricher) @@ -135,62 +144,60 @@ public void return_set_Enricher() { .get()); } - @Test(expected = IllegalStateException.class) + @Test public void not_accept_StorageFactory_if_EventStore_already_specified() { - final EventBus.Builder builder = builder().setEventStore(mock(EventStore.class)); + EventBus.Builder builder = builder().setEventStore(mock(EventStore.class)); + thrown.expect(IllegalStateException.class); builder.setStorageFactory(storageFactory); } - @Test(expected = IllegalStateException.class) + @Test public void not_accept_EventStore_if_StorageFactory_already_specified() { - final EventBus.Builder builder = builder().setStorageFactory(mock(StorageFactory.class)); + EventBus.Builder builder = builder().setStorageFactory(mock(StorageFactory.class)); + thrown.expect(IllegalStateException.class); builder.setEventStore(mock(EventStore.class)); } - @Test(expected = IllegalStateException.class) + @Test public void not_accept_EventStore_if_EventStoreStreamExecutor_already_specified() { - final EventBus.Builder builder = builder().setEventStoreStreamExecutor( - mock(Executor.class)); + EventBus.Builder builder = builder().setEventStoreStreamExecutor(mock(Executor.class)); + thrown.expect(IllegalStateException.class); builder.setEventStore(mock(EventStore.class)); } - @Test(expected = IllegalStateException.class) + @Test public void not_accept_EventStoreStreamExecutor_if_EventStore_already_specified() { - final EventBus.Builder builder = builder().setEventStore(mock(EventStore.class)); + EventBus.Builder builder = builder().setEventStore(mock(EventStore.class)); + thrown.expect(IllegalStateException.class); builder.setEventStoreStreamExecutor(mock(Executor.class)); } @Test public void use_directExecutor_if_EventStoreStreamExecutor_not_set() { - final EventBus.Builder builder = builder().setStorageFactory(storageFactory); - final EventBus build = builder.build(); - final Executor streamExecutor = build.getEventStore() - .getStreamExecutor(); + EventBus build = builder() + .setStorageFactory(storageFactory) + .build(); + Executor streamExecutor = build.getEventStore() + .getStreamExecutor(); ensureExecutorDirect(streamExecutor); } @Test public void use_passed_executor() { - final CountDownLatch executorUsageLatch = new CountDownLatch(1); - final Executor simpleExecutor = new Executor() { - @Override - public void execute(Runnable command) { - - // Decrease the counter to ensure this method has been called. - executorUsageLatch.countDown(); - } - }; - final EventBus.Builder builder = builder().setStorageFactory(storageFactory) - .setEventStoreStreamExecutor(simpleExecutor); - final EventBus build = builder.build(); - final Executor streamExecutor = build.getEventStore() - .getStreamExecutor(); + CountDownLatch executorUsageLatch = new CountDownLatch(1); + + // Decrease the counter to ensure this method has been called. + Executor simpleExecutor = command -> executorUsageLatch.countDown(); + EventBus.Builder builder = builder().setStorageFactory(storageFactory) + .setEventStoreStreamExecutor(simpleExecutor); + EventBus build = builder.build(); + Executor streamExecutor = build.getEventStore() + .getStreamExecutor(); streamExecutor.execute(mock(Runnable.class)); try { - /** - * The executor configured to operate synchronously, - * so the latch should already be {@code zero} at this point. - **/ + /* The executor configured to operate synchronously, + so the latch should already be zero at this point. + */ executorUsageLatch.await(0, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { fail("The specified executor was not used."); @@ -199,13 +206,14 @@ public void execute(Runnable command) { @Test public void allow_custom_message_validators() { - final StorageFactory storageFactory = + StorageFactory storageFactory = StorageFactorySwitch.newInstance(newName("test"), false) .get(); - final MessageValidator validator = mock(MessageValidator.class); - final EventBus eventBus = builder().setEventValidator(validator) - .setStorageFactory(storageFactory) - .build(); + MessageValidator validator = mock(MessageValidator.class); + EventBus eventBus = builder() + .setEventValidator(validator) + .setStorageFactory(storageFactory) + .build(); assertEquals(validator, eventBus.getMessageValidator()); } @@ -215,23 +223,20 @@ public void allow_configuring_logging_level_for_post_operations() { assertEquals(LoggingObserver.Level.TRACE, builder().getLogLevelForPost()); // Check setting new value. - final EventBus.Builder builder = builder(); - final LoggingObserver.Level newLevel = LoggingObserver.Level.DEBUG; + EventBus.Builder builder = builder(); + LoggingObserver.Level newLevel = LoggingObserver.Level.DEBUG; assertSame(builder, builder.setLogLevelForPost(newLevel)); assertEquals(newLevel, builder.getLogLevelForPost()); } private static void ensureExecutorDirect(Executor streamExecutor) { - final long mainThreadId = Thread.currentThread() + long mainThreadId = Thread.currentThread() .getId(); - streamExecutor.execute(new Runnable() { - @Override - public void run() { - final long runnableThreadId = Thread.currentThread() - .getId(); - assertEquals(mainThreadId, runnableThreadId); - } + streamExecutor.execute(() -> { + long runnableThreadId = Thread.currentThread() + .getId(); + assertEquals(mainThreadId, runnableThreadId); }); } } diff --git a/server/src/test/java/io/spine/server/event/EventFactoryShould.java b/server/src/test/java/io/spine/server/event/EventFactoryShould.java index f8482e49c05..8c00c876907 100644 --- a/server/src/test/java/io/spine/server/event/EventFactoryShould.java +++ b/server/src/test/java/io/spine/server/event/EventFactoryShould.java @@ -27,7 +27,9 @@ import io.spine.test.command.event.MandatoryFieldEvent; import io.spine.validate.ValidationException; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.base.Identifier.pack; import static io.spine.test.TestValues.newUuidValue; @@ -37,6 +39,9 @@ */ public class EventFactoryShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private final TestActorRequestFactory requestFactory = TestActorRequestFactory.newInstance(getClass()); @@ -49,19 +54,22 @@ public void setUp() { origin = requestFactory.generateEnvelope(); } - @Test(expected = NullPointerException.class) + @Test public void require_producer_id() { - EventFactory.on(origin, Tests.nullRef()); + thrown.expect(NullPointerException.class); + EventFactory.on(origin, Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void require_origin() { + thrown.expect(NullPointerException.class); EventFactory.on(Tests.nullRef(), producerId); } - @Test(expected = ValidationException.class) + @Test public void validate_event_messages_before_creation() { - final EventFactory factory = EventFactory.on(origin, producerId); + EventFactory factory = EventFactory.on(origin, producerId); + thrown.expect(ValidationException.class); factory.createEvent(MandatoryFieldEvent.getDefaultInstance(), null); } } diff --git a/server/src/test/java/io/spine/server/event/EventStoreServiceBuilderShould.java b/server/src/test/java/io/spine/server/event/EventStoreServiceBuilderShould.java index 2e3091ed852..02d92ebcfb4 100644 --- a/server/src/test/java/io/spine/server/event/EventStoreServiceBuilderShould.java +++ b/server/src/test/java/io/spine/server/event/EventStoreServiceBuilderShould.java @@ -25,7 +25,9 @@ import io.spine.server.storage.StorageFactory; import io.spine.test.Tests; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.concurrent.Executor; @@ -34,44 +36,53 @@ public class EventStoreServiceBuilderShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private StorageFactory storageFactory; private EventStore.ServiceBuilder builder; @Before public void setUp() { - final BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(true) - .build(); + BoundedContext bc = BoundedContext + .newBuilder() + .setMultitenant(true) + .build(); storageFactory = bc.getStorageFactory(); builder = EventStore.newServiceBuilder(); } - @Test(expected = NullPointerException.class) + @Test public void throw_NPE_on_null_executor() { - builder.setStreamExecutor(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder.setStreamExecutor(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_NPE_on_null_EventStorage() { - builder.setStreamExecutor(Tests.nullRef()); + thrown.expect(NullPointerException.class); + builder.setStreamExecutor(Tests.nullRef()); } - @Test(expected = NullPointerException.class) + @Test public void throw_NPE_on_non_set_streamExecutor() { + thrown.expect(NullPointerException.class); builder.setStorageFactory(storageFactory) .build(); } - @Test(expected = NullPointerException.class) + @Test public void throw_NPE_on_non_set_eventStorage() { + thrown.expect(NullPointerException.class); builder.setStreamExecutor(newExecutor()) .build(); } @Test public void return_set_streamExecutor() { - final Executor executor = newExecutor(); - assertEquals(executor, builder.setStreamExecutor(executor).getStreamExecutor()); + Executor executor = newExecutor(); + assertEquals(executor, builder.setStreamExecutor(executor) + .getStreamExecutor()); } @Test diff --git a/server/src/test/java/io/spine/server/projection/ProjectionRepositoryShould.java b/server/src/test/java/io/spine/server/projection/ProjectionRepositoryShould.java index 88672cdb0c4..22325269a49 100644 --- a/server/src/test/java/io/spine/server/projection/ProjectionRepositoryShould.java +++ b/server/src/test/java/io/spine/server/projection/ProjectionRepositoryShould.java @@ -20,6 +20,7 @@ package io.spine.server.projection; +import com.google.common.collect.Lists; import com.google.protobuf.Any; import com.google.protobuf.Message; import com.google.protobuf.StringValue; @@ -57,10 +58,11 @@ import io.spine.test.projection.event.PrjTaskAdded; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -79,10 +81,44 @@ public class ProjectionRepositoryShould extends RecordBasedRepositoryShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private static final Any PRODUCER_ID = Identifier.pack(GivenEventMessage.ENTITY_ID); private BoundedContext boundedContext; + private static TestEventFactory newEventFactory(TenantId tenantId, Any producerId) { + TestActorRequestFactory requestFactory = + TestActorRequestFactory.newInstance(ProjectionRepositoryShould.class, tenantId); + return TestEventFactory.newInstance(producerId, requestFactory); + } + + private static Event createEvent(TenantId tenantId, + Message eventMessage, + Any producerId, + Timestamp when) { + Version version = Versions.increment(Versions.zero()); + return newEventFactory(tenantId, producerId).createEvent(eventMessage, + version, + when); + } + + /** + * Simulates updating TenantIndex, which occurs during command processing + * in multi-tenant context. + */ + private static void keepTenantIdFromEvent(BoundedContext boundedContext, Event event) { + TenantId tenantId = event.getContext() + .getCommandContext() + .getActorContext() + .getTenantId(); + if (boundedContext.isMultitenant()) { + boundedContext.getTenantIndex() + .keep(tenantId); + } + } + private ProjectionRepository repository() { return (ProjectionRepository) repository; } @@ -94,22 +130,23 @@ protected RecordBasedRepository createReposi @Override protected TestProjection createEntity() { - final TestProjection projection = Given.projectionOfClass(TestProjection.class) - .withId(ProjectId.newBuilder() - .setId(newUuid()) - .build()) - .build(); + TestProjection projection = + Given.projectionOfClass(TestProjection.class) + .withId(ProjectId.newBuilder() + .setId(newUuid()) + .build()) + .build(); return projection; } @Override protected List createEntities(int count) { - final List projections = new LinkedList<>(); + List projections = Lists.newArrayList(); for (int i = 0; i < count; i++) { - final TestProjection projection = Given.projectionOfClass(TestProjection.class) - .withId(createId(i)) - .build(); + TestProjection projection = Given.projectionOfClass(TestProjection.class) + .withId(createId(i)) + .build(); projections.add(projection); } @@ -126,10 +163,11 @@ protected ProjectId createId(int i) { @Override @Before public void setUp() { - boundedContext = BoundedContext.newBuilder() - .setName(getClass().getSimpleName()) - .setMultitenant(true) - .build(); + boundedContext = BoundedContext + .newBuilder() + .setName(getClass().getSimpleName()) + .setMultitenant(true) + .build(); super.setUp(); boundedContext.register(repository); @@ -137,6 +175,10 @@ public void setUp() { TestProjection.clearMessageDeliveryHistory(); } + /* + * Tests + ************/ + /** * Closes the BoundedContest and shuts down the gRPC service. * @@ -148,29 +190,9 @@ public void shutDown() throws Exception { boundedContext.close(); } - private static TestEventFactory newEventFactory(TenantId tenantId, Any producerId) { - final TestActorRequestFactory requestFactory = - TestActorRequestFactory.newInstance(ProjectionRepositoryShould.class, tenantId); - return TestEventFactory.newInstance(producerId, requestFactory); - } - - private static Event createEvent(TenantId tenantId, - Message eventMessage, - Any producerId, - Timestamp when) { - final Version version = Versions.increment(Versions.zero()); - return newEventFactory(tenantId, producerId).createEvent(eventMessage, - version, - when); - } - - /* - * Tests - ************/ - @Test public void dispatch_event_and_load_projection() { - final PrjProjectStarted msg = GivenEventMessage.projectStarted(); + PrjProjectStarted msg = GivenEventMessage.projectStarted(); // Ensure no instances are present in the repository now. assertFalse(repository().loadAll() @@ -181,15 +203,15 @@ public void dispatch_event_and_load_projection() { // Post an event message and grab the ID of the projection, which processed it. checkDispatchesEvent(msg); - final Set projectIds = TestProjection.whoProcessed(msg); - assertTrue(projectIds.size() == 1); - final ProjectId receiverId = projectIds.iterator() - .next(); + Set projectIds = TestProjection.whoProcessed(msg); + assertEquals(1, projectIds.size()); + ProjectId receiverId = projectIds.iterator() + .next(); // Check that the projection item has actually been stored and now can be loaded. - final Iterator allItems = repository().loadAll(); + Iterator allItems = repository().loadAll(); assertTrue(allItems.hasNext()); - final TestProjection storedProjection = allItems.next(); + TestProjection storedProjection = allItems.next(); assertFalse(allItems.hasNext()); // Check that the stored instance has the same ID as the instance that handled the event. @@ -205,17 +227,17 @@ public void dispatch_several_events() { @Test public void dispatch_event_to_archived_projection() { - final PrjProjectArchived projectArchived = GivenEventMessage.projectArchived(); + PrjProjectArchived projectArchived = GivenEventMessage.projectArchived(); checkDispatchesEvent(projectArchived); - final ProjectId projectId = projectArchived.getProjectId(); + ProjectId projectId = projectArchived.getProjectId(); TestProjection projection = repository().findOrCreate(projectId); assertTrue(projection.isArchived()); // Dispatch an event to the archived projection. checkDispatchesEvent(GivenEventMessage.taskAdded()); projection = repository().findOrCreate(projectId); - final List addedTasks = projection.getState() - .getTaskList(); + List addedTasks = projection.getState() + .getTaskList(); assertFalse(addedTasks.isEmpty()); // Check that the projection was not re-created before dispatching. @@ -224,62 +246,53 @@ public void dispatch_event_to_archived_projection() { @Test public void dispatch_event_to_deleted_projection() { - final PrjProjectDeleted projectDeleted = GivenEventMessage.projectDeleted(); + PrjProjectDeleted projectDeleted = GivenEventMessage.projectDeleted(); checkDispatchesEvent(projectDeleted); - final ProjectId projectId = projectDeleted.getProjectId(); + ProjectId projectId = projectDeleted.getProjectId(); TestProjection projection = repository().findOrCreate(projectId); assertTrue(projection.isDeleted()); // Dispatch an event to the deleted projection. checkDispatchesEvent(GivenEventMessage.taskAdded()); projection = repository().findOrCreate(projectId); - final List addedTasks = projection.getState() - .getTaskList(); + List addedTasks = projection.getState() + .getTaskList(); assertTrue(projection.isDeleted()); // Check that the projection was not re-created before dispatching. assertFalse(addedTasks.isEmpty()); } + @SuppressWarnings("CheckReturnValue") // can ignore dispatch() result in this test + private void dispatchEvent(Event event) { + repository().dispatch(EventEnvelope.of(event)); + } + private void checkDispatchesEvent(Message eventMessage) { - final TestEventFactory eventFactory = newEventFactory(tenantId(), PRODUCER_ID); - final Event event = eventFactory.createEvent(eventMessage); + TestEventFactory eventFactory = newEventFactory(tenantId(), PRODUCER_ID); + Event event = eventFactory.createEvent(eventMessage); keepTenantIdFromEvent(boundedContext, event); - repository().dispatch(EventEnvelope.of(event)); + dispatchEvent(event); assertTrue(TestProjection.processed(eventMessage)); } - /** - * Simulates updating TenantIndex, which occurs during command processing - * in multi-tenant context. - */ - private static void keepTenantIdFromEvent(BoundedContext boundedContext, Event event) { - final TenantId tenantId = event.getContext() - .getCommandContext() - .getActorContext() - .getTenantId(); - if (boundedContext.isMultitenant()) { - boundedContext.getTenantIndex() - .keep(tenantId); - } - } - @Test public void log_error_if_dispatch_unknown_event() { - final StringValue unknownEventMessage = StringValue.getDefaultInstance(); + StringValue unknownEventMessage = StringValue.getDefaultInstance(); - final Event event = GivenEvent.withMessage(unknownEventMessage); + Event event = GivenEvent.withMessage(unknownEventMessage); - repository().dispatch(EventEnvelope.of(event)); + dispatchEvent(event); - TestProjectionRepository testRepo = (TestProjectionRepository)repository(); + TestProjectionRepository testRepo = (TestProjectionRepository) repository(); assertTrue(testRepo.getLastErrorEnvelope() instanceof EventEnvelope); assertEquals(Events.getMessage(event), testRepo.getLastErrorEnvelope() .getMessage()); - assertEquals(event, testRepo.getLastErrorEnvelope().getOuterObject()); + assertEquals(event, testRepo.getLastErrorEnvelope() + .getOuterObject()); // It must be "illegal argument type" since projections of this repository // do not handle such events. @@ -288,7 +301,7 @@ public void log_error_if_dispatch_unknown_event() { @Test public void return_event_classes() { - final Set eventClasses = repository().getMessageClasses(); + Set eventClasses = repository().getMessageClasses(); TestEventClasses.assertContains(eventClasses, PrjProjectCreated.class, PrjTaskAdded.class, @@ -297,32 +310,33 @@ public void return_event_classes() { @Test public void return_entity_storage() { - final RecordStorage recordStorage = repository().recordStorage(); + RecordStorage recordStorage = repository().recordStorage(); assertNotNull(recordStorage); } @Test public void convert_null_timestamp_to_default() { - final Timestamp timestamp = getCurrentTime(); + Timestamp timestamp = getCurrentTime(); assertEquals(timestamp, ProjectionRepository.nullToDefault(timestamp)); assertEquals(Timestamp.getDefaultInstance(), ProjectionRepository.nullToDefault(null)); } + @SuppressWarnings("CheckReturnValue") // can ignore dispatch() result in this test @Test public void do_not_create_record_if_entity_is_not_updated() { - final NoOpTaskNamesRepository repo = new NoOpTaskNamesRepository(); + NoOpTaskNamesRepository repo = new NoOpTaskNamesRepository(); boundedContext.register(repo); assertFalse(repo.loadAll() .hasNext()); - final Event event = createEvent(tenantId(), - GivenEventMessage.projectCreated(), - PRODUCER_ID, - getCurrentTime()); + Event event = createEvent(tenantId(), + GivenEventMessage.projectCreated(), + PRODUCER_ID, + getCurrentTime()); repo.dispatch(EventEnvelope.of(event)); - final Iterator items = repo.loadAll(); + Iterator items = repo.loadAll(); assertFalse(items.hasNext()); } @@ -333,7 +347,7 @@ public void do_not_create_record_if_entity_is_not_updated() { */ @Test public void expose_read_and_write_methods_for_last_handled_event_timestamp() { - repository().readLastHandledEventTime(); + assertNotNull(repository().readLastHandledEventTime()); repository().writeLastHandledEventTime(Time.getCurrentTime()); } @@ -364,13 +378,16 @@ public void expose_bounded_context_to_package() { assertNotNull(repository().boundedContext()); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_on_attempt_to_register_in_bc_with_no_messages_handled() { - final SensoryDeprivedProjectionRepository repo = new SensoryDeprivedProjectionRepository(); - final BoundedContext boundedContext = BoundedContext.newBuilder() - .setMultitenant(false) - .build(); + SensoryDeprivedProjectionRepository repo = new SensoryDeprivedProjectionRepository(); + BoundedContext boundedContext = BoundedContext + .newBuilder() + .setMultitenant(false) + .build(); repo.setBoundedContext(boundedContext); + + thrown.expect(IllegalStateException.class); repo.onRegistered(); } } diff --git a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java index 929d9af276b..ff2c49d3e2d 100644 --- a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java +++ b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java @@ -34,10 +34,10 @@ import io.spine.test.projection.event.PrjProjectCreated; import io.spine.test.projection.event.PrjTaskAdded; import io.spine.validate.ConstraintViolation; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Ignore; import org.junit.Test; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collections; import java.util.List; @@ -52,10 +52,10 @@ */ public class ProjectionTransactionShould extends TransactionShould, - Project, - ProjectionTransactionShould.PatchedProjectBuilder> { + Projection, + Project, + ProjectionTransactionShould.PatchedProjectBuilder> { private static final ProjectId ID = ProjectId.newBuilder() .setId("projection-transaction-should-project") @@ -118,8 +118,8 @@ protected void checkEventReceived( Projection entity, Event event) { - final TestProjection aggregate = (TestProjection) entity; - final Message actualMessage = unpack(event.getMessage()); + TestProjection aggregate = (TestProjection) entity; + Message actualMessage = unpack(event.getMessage()); assertTrue(aggregate.getReceivedEvents() .contains(actualMessage)); } @@ -127,15 +127,15 @@ protected void checkEventReceived( @Override protected Message createEventMessage() { return PrjProjectCreated.newBuilder() - .setProjectId(ID) - .build(); + .setProjectId(ID) + .build(); } @Override protected Message createEventMessageThatFailsInHandler() { return PrjTaskAdded.newBuilder() - .setProjectId(ID) - .build(); + .setProjectId(ID) + .build(); } @Override @@ -156,7 +156,8 @@ protected void breakEntityValidation( @Ignore @Test @Override - public void advance_version_from_event() {} + public void advance_version_from_event() { + } /** * Tests the version advancement strategy for the {@link Projection}s. @@ -166,15 +167,18 @@ public void advance_version_from_event() {} * case substitutes {@link #advance_version_from_event()}, which tested the behavior of * {@link io.spine.server.entity.EntityVersioning#FROM_EVENT FROM_EVENT} strategy. */ + @SuppressWarnings("CheckReturnValue") // can ignore value of play() in this test @Test public void increment_version_on_event() { - final Projection entity = createEntity(); - final Version oldVersion = entity.getVersion(); - final Event event = createEvent(createEventMessage()); + Projection entity = createEntity(); + Version oldVersion = entity.getVersion(); + Event event = createEvent(createEventMessage()); Projection.play(entity, Collections.singleton(event)); - final Version expected = Versions.increment(oldVersion); - assertEquals(expected.getNumber(), entity.getVersion().getNumber()); - assertNotEquals(event.getContext().getVersion(), entity.getVersion()); + Version expected = Versions.increment(oldVersion); + assertEquals(expected.getNumber(), entity.getVersion() + .getNumber()); + assertNotEquals(event.getContext() + .getVersion(), entity.getVersion()); } @SuppressWarnings({"MethodMayBeStatic", "unused"}) // Methods accessed via reflection. From 4721160c8abce31e1b13e5bbec840ae57a8e8322 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 02:55:55 +0300 Subject: [PATCH 15/53] Fix tests --- .../spine/server/bc/BoundedContextShould.java | 13 ++++++------- .../tenant/TenantAwareFunction0Should.java | 18 ++---------------- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java index 5e13c9a20ef..7f0ad6e2896 100644 --- a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java +++ b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java @@ -301,15 +301,14 @@ public void do_not_set_storage_factory_if_EventStore_is_set() { @SuppressWarnings("unchecked") // OK for the purpose of the created Matcher. @Test public void propagate_registered_repositories_to_stand() { - final BoundedContext boundedContext = BoundedContext.newBuilder() - .build(); - final Stand stand = Spy.ofClass(Stand.class) - .on(boundedContext); + BoundedContext boundedContext = BoundedContext.newBuilder() + .build(); + Stand stand = Spy.ofClass(Stand.class) + .on(boundedContext); - final Repository any = any(Repository.class); - verify(stand, never()).registerTypeSupplier(any); + verify(stand, never()).registerTypeSupplier(any()); - final ProjectAggregateRepository repository = + ProjectAggregateRepository repository = new ProjectAggregateRepository(); boundedContext.register(repository); verify(stand).registerTypeSupplier(eq(repository)); diff --git a/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java b/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java index 0fc790dc45c..94291a5bede 100644 --- a/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java +++ b/server/src/test/java/io/spine/server/tenant/TenantAwareFunction0Should.java @@ -26,8 +26,6 @@ import org.junit.Test; import org.junit.rules.ExpectedException; -import static io.spine.core.given.GivenTenantId.newUuid; - /** * @author Alexander Yevsyukov */ @@ -38,24 +36,12 @@ public class TenantAwareFunction0Should { @Test public void require_current_tenant_set() { - final TenantAwareFunction0 whichTime = new TenantAwareFunction0() { + thrown.expect(IllegalStateException.class); + new TenantAwareFunction0() { @Override public Timestamp apply() { return Time.getCurrentTime(); } }; - - // This should pass since we're executing the operation with the current tenant ID set. - new TenantAwareOperation(newUuid()) { - @SuppressWarnings("CheckReturnValue") // can ignore in this test. - @Override - public void run() { - whichTime.execute(); - } - }.execute(); - - thrown.expect(IllegalStateException.class); - // This should fail. - whichTime.execute(); } } From 6b27e92d5904a058bb5404c051ef74bfd702a69d Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 02:58:28 +0300 Subject: [PATCH 16/53] Fix test --- .../storage/ColumnValueExtractorShould.java | 29 ++++++++++--------- .../server/procman/ProcessManagerShould.java | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnValueExtractorShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnValueExtractorShould.java index 4c7a56701b6..ac11c30a887 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnValueExtractorShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnValueExtractorShould.java @@ -54,8 +54,8 @@ public void pass_null_check() { @Test public void extract_column_values_from_entity() { - final EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); - final Map columnValues = extractColumnValues(entity); + EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); + Map columnValues = extractColumnValues(entity); assertSize(3, columnValues); assertEquals(entity.getSomeMessage(), @@ -65,18 +65,18 @@ public void extract_column_values_from_entity() { @Test public void handle_null_column_values() { - final EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); - final Map columnValues = extractColumnValues(entity); + EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); + Map columnValues = extractColumnValues(entity); - final EntityColumn.MemoizedValue memoizedFloatNull = columnValues.get("floatNull"); + EntityColumn.MemoizedValue memoizedFloatNull = columnValues.get("floatNull"); assertNotNull(memoizedFloatNull); assertNull(memoizedFloatNull.getValue()); } @Test public void allow_to_access_values_by_custom_column_name() { - final EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); - final Map columnValues = extractColumnValues(entity); + EntityWithManyGetters entity = new EntityWithManyGetters(TEST_ENTITY_ID); + Map columnValues = extractColumnValues(entity); assertEquals(entity.getIntegerFieldValue(), columnValues.get(CUSTOM_COLUMN_NAME) @@ -85,8 +85,8 @@ public void allow_to_access_values_by_custom_column_name() { @Test public void extract_no_fields_if_none_defined() { - final Entity entity = new EntityWithNoStorageFields(TEST_ENTITY_ID); - final Map columnValues = extractColumnValues(entity); + Entity entity = new EntityWithNoStorageFields(TEST_ENTITY_ID); + Map columnValues = extractColumnValues(entity); assertNotNull(columnValues); assertEmpty(columnValues); @@ -94,17 +94,18 @@ public void extract_no_fields_if_none_defined() { @Test public void handle_non_public_entity_class() { - final Entity entity = new PrivateEntity(TEST_ENTITY_ID); - final Map columnValues = extractColumnValues(entity); + Entity entity = new PrivateEntity(TEST_ENTITY_ID); + Map columnValues = extractColumnValues(entity); assertNotNull(columnValues); assertEmpty(columnValues); } - private static > Map extractColumnValues(E entity) { - final Collection entityColumns = getAllColumns(entity.getClass()); - final ColumnValueExtractor columnValueExtractor = ColumnValueExtractor.create(entity, entityColumns); + private static > + Map extractColumnValues(E entity) { + Collection entityColumns = getAllColumns(entity.getClass()); + ColumnValueExtractor columnValueExtractor = ColumnValueExtractor.create(entity, entityColumns); return columnValueExtractor.extractColumnValues(); } diff --git a/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java b/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java index cf9d808cee8..646e285a1b5 100644 --- a/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java +++ b/server/src/test/java/io/spine/server/procman/ProcessManagerShould.java @@ -264,7 +264,7 @@ public void throw_exception_if_dispatch_unknown_command() { processManager.dispatchCommand(envelope); } - @Test(expected = IllegalStateException.class) + @Test public void throw_exception_if_dispatch_unknown_event() { StringValue unknownEvent = StringValue.getDefaultInstance(); EventEnvelope envelope = EventEnvelope.of(eventFactory.createEvent(unknownEvent)); From 9eb65ce567c1ae27f36abf3ab6f2ec297c222084 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 03:04:54 +0300 Subject: [PATCH 17/53] Fix test --- .../spine/server/event/ERepositoryShould.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/server/src/test/java/io/spine/server/event/ERepositoryShould.java b/server/src/test/java/io/spine/server/event/ERepositoryShould.java index 1b0188cc0f3..d5f6fec8326 100644 --- a/server/src/test/java/io/spine/server/event/ERepositoryShould.java +++ b/server/src/test/java/io/spine/server/event/ERepositoryShould.java @@ -42,47 +42,49 @@ public class ERepositoryShould { @Test public void convert_empty_query_to_empty_EntityFilters() { - final EventStreamQuery query = EventStreamQuery.newBuilder() - .build(); - final EntityFilters entityFilters = toEntityFilters(query); + EventStreamQuery query = EventStreamQuery.newBuilder() + .build(); + EntityFilters entityFilters = toEntityFilters(query); assertTrue(entityFilters.getFilterList() .isEmpty()); } @Test public void convert_time_query_to_EntityFilters() { - final EventStreamQuery query = EventStreamQuery.newBuilder() - .setAfter(Timestamps.MIN_VALUE) - .setBefore(Timestamps.MAX_VALUE) - .build(); - final EntityFilters entityFilters = toEntityFilters(query); + EventStreamQuery query = EventStreamQuery + .newBuilder() + .setAfter(Timestamps.MIN_VALUE) + .setBefore(Timestamps.MAX_VALUE) + .build(); + EntityFilters entityFilters = toEntityFilters(query); assertEquals(1, entityFilters.getFilterCount()); - final CompositeColumnFilter compositeFilter = entityFilters.getFilter(0); - final List columnFilters = compositeFilter.getFilterList(); + CompositeColumnFilter compositeFilter = entityFilters.getFilter(0); + List columnFilters = compositeFilter.getFilterList(); assertEquals(CompositeOperator.ALL, compositeFilter.getOperator()); assertEquals(2, columnFilters.size()); } @Test public void convert_type_query_to_EntityFilters() { - final String typeName = " com.example.EventType "; - final EventFilter validFilter = filterForType(typeName); - final EventFilter invalidFilter = filterForType(" "); - final EventStreamQuery query = EventStreamQuery.newBuilder() - .addFilter(validFilter) - .addFilter(invalidFilter) - .build(); - final EntityFilters entityFilters = toEntityFilters(query); + String typeName = " com.example.EventType "; + EventFilter validFilter = filterForType(typeName); + EventFilter invalidFilter = filterForType(" "); + EventStreamQuery query = EventStreamQuery + .newBuilder() + .addFilter(validFilter) + .addFilter(invalidFilter) + .build(); + EntityFilters entityFilters = toEntityFilters(query); assertEquals(1, entityFilters.getFilterCount()); - final CompositeColumnFilter compositeFilter = entityFilters.getFilter(0); - final List columnFilters = compositeFilter.getFilterList(); + CompositeColumnFilter compositeFilter = entityFilters.getFilter(0); + List columnFilters = compositeFilter.getFilterList(); assertEquals(CompositeOperator.EITHER, compositeFilter.getOperator()); assertEquals(1, columnFilters.size()); - final Any typeNameAsAny = columnFilters.get(0) - .getValue(); - assertEquals(typeName, toObject(typeNameAsAny, String.class)); + Any typeNameAsAny = columnFilters.get(0) + .getValue(); + assertEquals(typeName.trim(), toObject(typeNameAsAny, String.class)); } private static EventFilter filterForType(String typeName) { From 735dd14de45bbf36c53f99bc8f590c3cf71cc830 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 03:15:03 +0300 Subject: [PATCH 18/53] Fix tests --- .../io/spine/server/entity/storage/ColumnRecords.java | 10 +++++----- .../java/io/spine/server/entity/storage/Columns.java | 2 ++ .../io/spine/server/entity/storage/EntityColumn.java | 8 +++++--- .../server/entity/storage/given/ColumnsTestEnv.java | 4 +--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java index 5520b5dc7d8..350bc8a2089 100644 --- a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java +++ b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java @@ -104,16 +104,16 @@ public static void feedColumnsTo( * in the scanned classes */ static Optional getAnnotatedVersion(Method method) { - final Set annotatedVersions = newHashSet(); + Set annotatedVersions = newHashSet(); if (method.isAnnotationPresent(Column.class)) { annotatedVersions.add(method); } - final Class declaringClass = method.getDeclaringClass(); - final Iterable> ascendants = getSuperClassesAndInterfaces(declaringClass); + Class declaringClass = method.getDeclaringClass(); + Iterable> ascendants = getSuperClassesAndInterfaces(declaringClass); for (Class ascendant : ascendants) { - final Optional optionalMethod = getMethodBySignature(ascendant, method); + Optional optionalMethod = getMethodBySignature(ascendant, method); if (optionalMethod.isPresent()) { - final Method ascendantMethod = optionalMethod.get(); + Method ascendantMethod = optionalMethod.get(); if (ascendantMethod.isAnnotationPresent(Column.class)) { annotatedVersions.add(ascendantMethod); } diff --git a/server/src/main/java/io/spine/server/entity/storage/Columns.java b/server/src/main/java/io/spine/server/entity/storage/Columns.java index 0286950f834..3b506ee79e7 100644 --- a/server/src/main/java/io/spine/server/entity/storage/Columns.java +++ b/server/src/main/java/io/spine/server/entity/storage/Columns.java @@ -110,6 +110,8 @@ static void checkColumnName(String columnName) { static IllegalArgumentException couldNotFindColumn(Class entityClass, String columnName) { + checkNotNull(entityClass); + checkNotNull(columnName); throw new IllegalArgumentException( format("Could not find an EntityColumn description for %s.%s.", entityClass.getCanonicalName(), diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java index 1af243dd139..4899d5cdaa7 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java @@ -215,9 +215,11 @@ private EntityColumn(Method getter, String name, String storedName, boolean null */ public static EntityColumn from(Method getter) { checkGetter(getter); - final String nameForQuery = nameFromGetter(getter); - final String nameForStore = nameFromAnnotation(getter).or(nameForQuery); - final boolean nullable = getter.isAnnotationPresent(Nullable.class); + String nameForQuery = nameFromGetter(getter); + String nameForStore = nameFromAnnotation(getter).or(nameForQuery); + + boolean nullable = getter.getAnnotatedReturnType() + .isAnnotationPresent(Nullable.class); return new EntityColumn(getter, nameForQuery, nameForStore, nullable); } diff --git a/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java b/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java index b2fe9121ea9..f29c37187cc 100644 --- a/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java +++ b/server/src/test/java/io/spine/server/entity/storage/given/ColumnsTestEnv.java @@ -29,7 +29,6 @@ import io.spine.test.entity.Project; import io.spine.test.entity.ProjectId; import io.spine.testdata.Sample; - import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -68,9 +67,8 @@ public int getIntegerFieldValue() { return 0; } - @Nullable @Column - public Float getFloatNull() { + public @Nullable Float getFloatNull() { return null; } From e50ddd3fc00ca880e71575dd2406e60e2043ba16 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 03:37:34 +0300 Subject: [PATCH 19/53] Fix tests --- .../server/command/CommandTestShould.java | 107 ++++++++++-------- .../spine/server/model/ModelTestsShould.java | 12 +- 2 files changed, 69 insertions(+), 50 deletions(-) diff --git a/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java b/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java index cbb65c4fb5f..6fee6f11229 100644 --- a/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java +++ b/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java @@ -28,10 +28,13 @@ import io.spine.core.Command; import io.spine.core.Commands; import io.spine.core.TenantId; +import io.spine.test.Tests; import io.spine.test.TimeTests; import io.spine.time.ZoneOffsets; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static io.spine.core.given.GivenUserId.newUuid; import static io.spine.test.TestValues.newUuidValue; @@ -44,6 +47,9 @@ */ public class CommandTestShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + private CommandTest commandTest; /** @@ -53,14 +59,34 @@ public class CommandTestShould { * has correctly working {@link ActorRequestFactory}. */ private static void createAndAssertCommand(CommandTest commandTest) { - final StringValue commandMessage = newUuidValue(); - final Command command = commandTest.createCommand(commandMessage); + StringValue commandMessage = newUuidValue(); + Command command = commandTest.createCommand(commandMessage); checkNotDefault(command); assertEquals(commandMessage, Commands.getMessage(command)); checkNotDefault(command.getContext()); } + /** + * Creates a test instance of {@code ActorRequestFactory}. + * + *

The factory gets: + *

+ */ + static ActorRequestFactory newRequestFactory(Class clazz) { + return ActorRequestFactory.newBuilder() + .setActor(newUuid()) + .setZoneOffset(ZoneOffsets.UTC) + .setTenantId(TenantId.newBuilder() + .setValue(clazz.getSimpleName()) + .build()) + .build(); + } + @Before public void setUp() { commandTest = new TestCommandTest(); @@ -80,82 +106,68 @@ public void do_not_allow_null_ActorRequestFactory() { @Test public void accept_custom_ActorRequestFactory() { - final Class clazz = getClass(); - final CommandTest commandTestWithFactory = + Class clazz = getClass(); + CommandTest commandTestWithFactory = new TestCommandTest(newRequestFactory(clazz)); createAndAssertCommand(commandTestWithFactory); } - /** - * Creates a test instance of {@code ActorRequestFactory}. - * - *

The factory gets: - *

    - *
  • generated {@code UserId} for the actor. - *
  • UTC zone offset - *
  • {@code TenantId} based on the simple name of the passed class. - *
- */ - static ActorRequestFactory newRequestFactory(Class clazz) { - return ActorRequestFactory.newBuilder() - .setActor(newUuid()) - .setZoneOffset(ZoneOffsets.UTC) - .setTenantId(TenantId.newBuilder() - .setValue(clazz.getSimpleName()) - .build()) - .build(); - } - @Test public void have_empty_state_before_command_creation() { - assertFalse(commandTest.commandMessage().isPresent()); - assertFalse(commandTest.commandContext().isPresent()); - assertFalse(commandTest.command().isPresent()); + assertFalse(commandTest.commandMessage() + .isPresent()); + assertFalse(commandTest.commandContext() + .isPresent()); + assertFalse(commandTest.command() + .isPresent()); } @SuppressWarnings("OptionalGetWithoutIsPresent") // This test verifies that Optionals - // are initialized. + // are initialized. @Test public void stores_command_after_creation() { - final StringValue commandMessage = newUuidValue(); - final Command command = commandTest.createCommand(commandMessage); - - assertEquals(commandMessage, commandTest.commandMessage().get()); - assertEquals(command.getContext(), commandTest.commandContext().get()); - assertEquals(command, commandTest.command().get()); + StringValue commandMessage = newUuidValue(); + Command command = commandTest.createCommand(commandMessage); + + assertEquals(commandMessage, commandTest.commandMessage() + .get()); + assertEquals(command.getContext(), commandTest.commandContext() + .get()); + assertEquals(command, commandTest.command() + .get()); } @Test public void create_command_with_custom_Timestamp() { - final StringValue commandMessage = newUuidValue(); - final Timestamp timestamp = TimeTests.Past.minutesAgo(5); - final Command command = commandTest.createCommand(commandMessage, timestamp); + StringValue commandMessage = newUuidValue(); + Timestamp timestamp = TimeTests.Past.minutesAgo(5); + Command command = commandTest.createCommand(commandMessage, timestamp); assertEquals(timestamp, command.getContext() .getActorContext() .getTimestamp()); } - @SuppressWarnings("ConstantConditions") // Passing `null` is the purpose of the test. - @Test(expected = NullPointerException.class) + @Test public void do_not_accept_null_command_message_for_different_command() { - commandTest.createDifferentCommand(null); + thrown.expect(NullPointerException.class); + commandTest.createDifferentCommand(Tests.nullRef()); } @Test public void create_different_command() { - final Message anotherCommandMsg = Time.getCurrentTime(); - final Command anotherCommand = commandTest.createDifferentCommand(anotherCommandMsg); + Message anotherCommandMsg = Time.getCurrentTime(); + Command anotherCommand = commandTest.createDifferentCommand(anotherCommandMsg); assertEquals(anotherCommandMsg, Commands.getMessage(anotherCommand)); } @Test public void create_different_command_with_timestamp() { - final Message anotherCommandMsg = Time.getCurrentTime(); - final Timestamp timestamp = TimeTests.Past.minutesAgo(30); - final Command anotherCommand = + Message anotherCommandMsg = Time.getCurrentTime(); + Timestamp timestamp = TimeTests.Past.minutesAgo(30); + Command anotherCommand = commandTest.createDifferentCommand(anotherCommandMsg, timestamp); assertEquals(anotherCommandMsg, Commands.getMessage(anotherCommand)); @@ -168,11 +180,12 @@ public void create_different_command_with_timestamp() { * The test class for verifying the behaviour of the abstract parent. */ private static class TestCommandTest extends CommandTest { - protected TestCommandTest(ActorRequestFactory requestFactory) { + + private TestCommandTest(ActorRequestFactory requestFactory) { super(requestFactory); } - protected TestCommandTest() { + private TestCommandTest() { super(); } diff --git a/testutil-server/src/test/java/io/spine/server/model/ModelTestsShould.java b/testutil-server/src/test/java/io/spine/server/model/ModelTestsShould.java index d94bb3b02e7..3ac3d50752c 100644 --- a/testutil-server/src/test/java/io/spine/server/model/ModelTestsShould.java +++ b/testutil-server/src/test/java/io/spine/server/model/ModelTestsShould.java @@ -24,11 +24,15 @@ import com.google.protobuf.Timestamp; import io.spine.server.command.Assign; import io.spine.server.command.CommandHandler; +import io.spine.server.command.CommandHandlerClass; import io.spine.server.event.EventBus; import io.spine.test.Tests; import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + /** * @author Alexander Yevsyukov */ @@ -49,15 +53,17 @@ public void have_utility_ctor() { @Test public void clear_the_model() { - // This adds a command handler for `com.google.protobuf.Timestamp`. - model.asCommandHandlerClass(TestCommandHandler.class); + final CommandHandlerClass cls1 = model.asCommandHandlerClass(TestCommandHandler.class); + assertNotNull(cls1); ModelTests.clearModel(); // This should pass as we cleared the model, // i.e. there is no registered command handler for `com.google.protobuf.Timestamp`. - model.asCommandHandlerClass(DuplicatedCommandHandler.class); + CommandHandlerClass cls2 = model.asCommandHandlerClass(DuplicatedCommandHandler.class); + assertNotNull(cls2); + assertNotEquals(cls1, cls2); } private static class TestCommandHandler extends CommandHandler { From f50ab3f6a6f658f6eef32e6d3cc5347163ea180e Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 04:18:05 +0300 Subject: [PATCH 20/53] Merge remote-tracking branch 'remotes/origin/master' into error-prone Conflicts: client/src/test/java/io/spine/client/ColumnFiltersShould.java ext.gradle server/src/main/java/io/spine/server/entity/storage/EntityColumn.java server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java server/src/test/java/io/spine/server/storage/RecordStorageShould.java --- .../server/entity/storage/EntityColumn.java | 4 +- .../entity/storage/ColumnRecordsShould.java | 2 +- .../server/entity/storage/ColumnShould.java | 63 ++++++++++--------- .../storage/ColumnTypeRegistryShould.java | 2 +- .../storage/ColumnValueConverterShould.java | 30 +++++---- .../entity/storage/given/ColumnTestEnv.java | 1 - .../server/stand/StandStorageShould.java | 2 +- .../io/spine/server/tuple/ElementShould.java | 5 +- 8 files changed, 58 insertions(+), 51 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java index 33f11fd629b..ea82346d658 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java @@ -322,13 +322,13 @@ public boolean isNullable() { * @param source the {@link Entity} to get the Columns from * @return the value of the column represented by this instance */ - public Serializable getFor(Entity source) { + public @Nullable Serializable getFor(Entity source) { try { final Serializable result = (Serializable) getter.invoke(source); if (!nullable) { checkNotNull(result, format("Not null getter %s returned null.", getter.getName())); } - \Serializable value = toPersistedValue(result); + Serializable value = toPersistedValue(result); return value; } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException( diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java index 22815668740..50998ffeaab 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnRecordsShould.java @@ -24,9 +24,9 @@ import com.google.common.testing.NullPointerTester; import io.spine.server.entity.EntityRecord; import io.spine.test.Tests; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java index c6b07652ea7..1923418c5bf 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnShould.java @@ -243,85 +243,86 @@ public void not_allow_redefine_column_annotation() { @Test public void be_constructed_from_enumerated_type_getter() { - final EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); - final Class expectedType = Integer.class; - final Class actualType = column.getPersistedType(); + EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); + Class expectedType = Integer.class; + Class actualType = column.getPersistedType(); assertEquals(expectedType, actualType); } @Test public void return_same_persisted_type_for_non_enum_getter() { - final EntityColumn column = forMethod("getLong", TestEntity.class); + EntityColumn column = forMethod("getLong", TestEntity.class); assertEquals(column.getType(), column.getPersistedType()); } @Test public void return_persistence_type_for_ordinal_enumerated_value() { - final EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); - final Class expectedType = Integer.class; - final Class actualType = column.getPersistedType(); + EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); + Class expectedType = Integer.class; + Class actualType = column.getPersistedType(); assertEquals(expectedType, actualType); } @Test public void return_persistence_type_for_string_enumerated_value() { - final EntityColumn column = forMethod("getEnumString", TestEntity.class); - final Class expectedType = String.class; - final Class actualType = column.getPersistedType(); + EntityColumn column = forMethod("getEnumString", TestEntity.class); + Class expectedType = String.class; + Class actualType = column.getPersistedType(); assertEquals(expectedType, actualType); } @Test public void memoize_value_of_enumerated_ordinal_column() { - final EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); - final TestEntity entity = new TestEntity(""); - final MemoizedValue actualValue = column.memoizeFor(entity); - final int expectedValue = entity.getEnumOrdinal() + EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); + TestEntity entity = new TestEntity(""); + MemoizedValue actualValue = column.memoizeFor(entity); + int expectedValue = entity.getEnumOrdinal() .ordinal(); assertEquals(expectedValue, actualValue.getValue()); } @Test public void memoize_value_of_enumerated_string_column() { - final EntityColumn column = forMethod("getEnumString", TestEntity.class); - final TestEntity entity = new TestEntity(""); - final MemoizedValue actualValue = column.memoizeFor(entity); - final String expectedValue = entity.getEnumOrdinal() + EntityColumn column = forMethod("getEnumString", TestEntity.class); + TestEntity entity = new TestEntity(""); + MemoizedValue actualValue = column.memoizeFor(entity); + String expectedValue = entity.getEnumOrdinal() .name(); assertEquals(expectedValue, actualValue.getValue()); } @Test public void convert_enumerated_value_to_persistence_type() { - final EntityColumn columnOrdinal = forMethod("getEnumOrdinal", TestEntity.class); - final Object ordinalValue = columnOrdinal.toPersistedValue(SUCCESS); + EntityColumn columnOrdinal = forMethod("getEnumOrdinal", TestEntity.class); + Object ordinalValue = columnOrdinal.toPersistedValue(SUCCESS); assertEquals(SUCCESS.ordinal(), ordinalValue); - final EntityColumn columnString = forMethod("getEnumString", TestEntity.class); - final Object stringValue = columnString.toPersistedValue(SUCCESS); + EntityColumn columnString = forMethod("getEnumString", TestEntity.class); + Object stringValue = columnString.toPersistedValue(SUCCESS); assertEquals(SUCCESS.name(), stringValue); } @Test public void do_identity_conversion_for_non_enum_values() { - final EntityColumn column = forMethod("getLong", TestEntity.class); - final Object value = 15L; - final Object converted = column.toPersistedValue(value); + EntityColumn column = forMethod("getLong", TestEntity.class); + Object value = 15L; + Object converted = column.toPersistedValue(value); assertEquals(value, converted); } @Test public void return_null_on_null_conversion() { - final EntityColumn column = forMethod("getLong", TestEntity.class); - final Object value = null; - final Object converted = column.toPersistedValue(value); + EntityColumn column = forMethod("getLong", TestEntity.class); + Object value = null; + Object converted = column.toPersistedValue(value); assertNull(converted); } - @Test(expected = IllegalArgumentException.class) + @Test public void allow_conversion_only_for_type_stored_in_column() { - final EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); - final String value = "test"; + EntityColumn column = forMethod("getEnumOrdinal", TestEntity.class); + String value = "test"; + thrown.expect(IllegalArgumentException.class); column.toPersistedValue(value); } diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java index 8bb7c56cf83..66ab3033181 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnTypeRegistryShould.java @@ -44,7 +44,7 @@ public class ColumnTypeRegistryShould { private static EntityColumn mockProperty(Class cls) { - final EntityColumn column = mock(EntityColumn.class); + EntityColumn column = mock(EntityColumn.class); when(column.getType()).thenReturn(cls); when(column.getPersistedType()).thenReturn(cls); return column; diff --git a/server/src/test/java/io/spine/server/entity/storage/ColumnValueConverterShould.java b/server/src/test/java/io/spine/server/entity/storage/ColumnValueConverterShould.java index 7d40f6b7a0a..6194c8fa9f8 100644 --- a/server/src/test/java/io/spine/server/entity/storage/ColumnValueConverterShould.java +++ b/server/src/test/java/io/spine/server/entity/storage/ColumnValueConverterShould.java @@ -22,7 +22,9 @@ import com.google.common.testing.NullPointerTester; import io.spine.server.entity.storage.given.ColumnTestEnv.TaskStatus; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.io.Serializable; @@ -34,6 +36,9 @@ */ public class ColumnValueConverterShould { + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Test public void not_accept_nulls() { ColumnValueConverter converter = new IdentityConverter(TaskStatus.class); @@ -46,32 +51,33 @@ public void not_accept_nulls() { @Test public void perform_identity_conversion() { - final String value = "stringValue"; - final ColumnValueConverter converter = new IdentityConverter(value.getClass()); - final Serializable convertedObject = converter.convert(value); + String value = "stringValue"; + ColumnValueConverter converter = new IdentityConverter(value.getClass()); + Serializable convertedObject = converter.convert(value); assertEquals(value, convertedObject); } @Test public void convert_enum_to_ordinal_value() { - final TaskStatus value = SUCCESS; - final ColumnValueConverter converter = new OrdinalEnumConverter(value.getClass()); - final Serializable convertedValue = converter.convert(value); + TaskStatus value = SUCCESS; + ColumnValueConverter converter = new OrdinalEnumConverter(value.getClass()); + Serializable convertedValue = converter.convert(value); assertEquals(value.ordinal(), convertedValue); } @Test public void convert_enum_to_string_value() { - final TaskStatus value = SUCCESS; - final ColumnValueConverter converter = new StringEnumConverter(value.getClass()); - final Serializable convertedValue = converter.convert(value); + TaskStatus value = SUCCESS; + ColumnValueConverter converter = new StringEnumConverter(value.getClass()); + Serializable convertedValue = converter.convert(value); assertEquals(value.name(), convertedValue); } - @Test(expected = IllegalArgumentException.class) + @Test public void not_support_wrong_value_type_conversion() { - final String value = "unsupportedValue"; - final ColumnValueConverter converter = new OrdinalEnumConverter(TaskStatus.class); + String value = "unsupportedValue"; + ColumnValueConverter converter = new OrdinalEnumConverter(TaskStatus.class); + thrown.expect(IllegalArgumentException.class); converter.convert(value); } } diff --git a/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java b/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java index cb857495a6e..d47e936e378 100644 --- a/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java +++ b/server/src/test/java/io/spine/server/entity/storage/given/ColumnTestEnv.java @@ -27,7 +27,6 @@ import io.spine.server.entity.VersionableEntity; import io.spine.server.entity.storage.Column; import io.spine.server.entity.storage.Enumerated; - import org.checkerframework.checker.nullness.qual.Nullable; import static io.spine.server.entity.storage.EnumType.STRING; diff --git a/server/src/test/java/io/spine/server/stand/StandStorageShould.java b/server/src/test/java/io/spine/server/stand/StandStorageShould.java index ea9751fbd61..2383e2a8c05 100644 --- a/server/src/test/java/io/spine/server/stand/StandStorageShould.java +++ b/server/src/test/java/io/spine/server/stand/StandStorageShould.java @@ -38,9 +38,9 @@ import io.spine.test.storage.Task; import io.spine.test.storage.TaskId; import io.spine.type.TypeUrl; +import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; -import org.checkerframework.checker.nullness.qual.Nullable; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; diff --git a/server/src/test/java/io/spine/server/tuple/ElementShould.java b/server/src/test/java/io/spine/server/tuple/ElementShould.java index b304f8d082a..d870e28989b 100644 --- a/server/src/test/java/io/spine/server/tuple/ElementShould.java +++ b/server/src/test/java/io/spine/server/tuple/ElementShould.java @@ -22,6 +22,7 @@ import com.google.common.base.Optional; import com.google.common.testing.EqualsTester; +import com.google.protobuf.Timestamp; import io.spine.base.Time; import io.spine.test.TestValues; import org.junit.Test; @@ -35,8 +36,8 @@ public class ElementShould { @Test public void support_equality() { - new EqualsTester().addEqualityGroup(new Element(Time.getCurrentTime()), - new Element(Time.getCurrentTime())) + Timestamp time = Time.getCurrentTime(); + new EqualsTester().addEqualityGroup(new Element(time), new Element(time)) .addEqualityGroup(new Element(TestValues.newUuidValue())) .addEqualityGroup(new Element(Optional.absent())) .testEquals(); From 474130ff89b66111b32461a4d1cc072a4b00e111 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 04:37:08 +0300 Subject: [PATCH 21/53] Improve code layout --- .../server/entity/storage/ColumnRecords.java | 86 +++++++++++-------- 1 file changed, 50 insertions(+), 36 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java index fdb135c5765..76fc71e9761 100644 --- a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java +++ b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java @@ -33,6 +33,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Sets.newHashSet; +import static java.lang.String.format; /** * A utility for dealing with the {@linkplain EntityRecordWithColumns} and @@ -42,8 +43,8 @@ */ public final class ColumnRecords { + /** Prevent initialization of the utility class */ private ColumnRecords() { - // Prevent initialization of the utility class } /** @@ -53,45 +54,58 @@ private ColumnRecords() { * The {@link io.spine.server.entity.EntityRecord EntityRecord} should be handled separately * while persisting a record. * - * @param destination the representation of a record in the database; implementation - * specific - * @param recordWithColumns the {@linkplain EntityRecordWithColumns} to persist - * @param columnTypeRegistry the {@link io.spine.server.storage.Storage Storage} - * {@link ColumnTypeRegistry} - * @param mapColumnIdentifier a {@linkplain Function} mapping the column name - * {@linkplain EntityColumn#getStoredName()} for storing} - * to the database specific column identifier - * @param the type of the database record - * @param the type of the column identifier + * @param destination + * the representation of a record in the database; implementation specific + * @param record + * the {@linkplain EntityRecordWithColumns} to persist + * @param registry + * the {@link io.spine.server.storage.Storage Storage} {@link ColumnTypeRegistry} + * @param mapColumnIdentifier + * a {@linkplain Function} mapping the column name + * {@linkplain EntityColumn#getStoredName()} for storing} to the database specific + * column identifier + * @param + * the type of the database record + * @param + * the type of the column identifier */ public static void feedColumnsTo( D destination, - EntityRecordWithColumns recordWithColumns, - ColumnTypeRegistry> columnTypeRegistry, + EntityRecordWithColumns record, + ColumnTypeRegistry> registry, Function mapColumnIdentifier) { checkNotNull(destination); - checkNotNull(recordWithColumns); - checkNotNull(columnTypeRegistry); + checkNotNull(record); + checkNotNull(registry); checkNotNull(mapColumnIdentifier); - checkArgument(recordWithColumns.hasColumns(), - "Passed record has no Entity Columns."); + checkArgument(record.hasColumns(), "Passed record has no Entity Columns."); - for (String columnName : recordWithColumns.getColumnNames()) { - final I columnIdentifier = mapColumnIdentifier.apply(columnName); - checkNotNull(columnIdentifier); - final MemoizedValue columnValue = recordWithColumns.getColumnValue(columnName); - final EntityColumn columnMetadata = columnValue.getSourceColumn(); - @SuppressWarnings("unchecked") // We don't know the exact types of the value - final ColumnType columnType = - (ColumnType) columnTypeRegistry.get(columnMetadata); - checkArgument(columnType != null, - String.format("ColumnType for %s could not be found.", - columnMetadata.getPersistedType() - .getCanonicalName())); - setValue(columnValue, destination, columnIdentifier, columnType); + for (String columnName : record.getColumnNames()) { + feedColumn(record, columnName, destination, registry, mapColumnIdentifier); } } + private static void feedColumn( + EntityRecordWithColumns record, + String columnName, + D destination, + ColumnTypeRegistry> registry, + Function mapColumnIdentifier) { + I columnIdentifier = mapColumnIdentifier.apply(columnName); + checkNotNull(columnIdentifier); + MemoizedValue columnValue = record.getColumnValue(columnName); + EntityColumn columnMetadata = columnValue.getSourceColumn(); + + @SuppressWarnings("unchecked") // We don't know the exact types of the value + ColumnType columnType = + (ColumnType) registry.get(columnMetadata); + checkArgument(columnType != null, + format("ColumnType for %s could not be found.", + columnMetadata.getPersistedType() + .getCanonicalName())); + setValue(columnValue, destination, columnIdentifier, columnType); + } + /** * Obtains the method version annotated with {@link Column} for the specified method. * @@ -125,15 +139,15 @@ static Optional getAnnotatedVersion(Method method) { if (annotatedVersions.isEmpty()) { return Optional.absent(); } else { - final Method annotatedVersion = annotatedVersions.iterator() + Method annotatedVersion = annotatedVersions.iterator() .next(); return Optional.of(annotatedVersion); } } private static Iterable> getSuperClassesAndInterfaces(Class cls) { - final Collection> interfaces = Arrays.asList(cls.getInterfaces()); - final Collection> result = newHashSet(interfaces); + Collection> interfaces = Arrays.asList(cls.getInterfaces()); + Collection> result = newHashSet(interfaces); Class currentSuper = cls.getSuperclass(); while (currentSuper != null) { result.add(currentSuper); @@ -153,7 +167,7 @@ private static Optional getMethodBySignature(Class target, Method met checkArgument(!method.getDeclaringClass() .equals(target)); try { - final Method methodFromTarget = target.getMethod(method.getName(), + Method methodFromTarget = target.getMethod(method.getName(), method.getParameterTypes()); return Optional.of(methodFromTarget); } catch (NoSuchMethodException ignored) { @@ -166,11 +180,11 @@ private static void setValue(MemoizedValue columnValue, I columnIdentifier, ColumnType columnType) { @SuppressWarnings("unchecked") // Checked at runtime - final J initialValue = (J) columnValue.getValue(); + J initialValue = (J) columnValue.getValue(); if (initialValue == null) { columnType.setNull(destination, columnIdentifier); } else { - final S storedValue = columnType.convertColumnValue(initialValue); + S storedValue = columnType.convertColumnValue(initialValue); columnType.setColumnValue(destination, storedValue, columnIdentifier); } } From 8fdda343a12ad6d8645a59beab9cd774e30480f9 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 04:40:59 +0300 Subject: [PATCH 22/53] Optimize imports --- server/src/main/java/io/spine/server/procman/PmTransaction.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/main/java/io/spine/server/procman/PmTransaction.java b/server/src/main/java/io/spine/server/procman/PmTransaction.java index f7146d0c4ec..4387ecfc766 100644 --- a/server/src/main/java/io/spine/server/procman/PmTransaction.java +++ b/server/src/main/java/io/spine/server/procman/PmTransaction.java @@ -28,8 +28,6 @@ import io.spine.server.entity.TransactionListener; import io.spine.validate.ValidatingBuilder; -import java.sql.Connection; - /** * A transaction, within which {@linkplain ProcessManager ProcessManager instances} are modified. * From 116d7df03e2c52a23f9ea9c876d8e5f624133a71 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Mon, 28 May 2018 04:41:22 +0300 Subject: [PATCH 23/53] Optimize imports --- .../src/main/java/io/spine/model/assemble/AssignLookup.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java b/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java index b5d8ace373d..497d5bd2838 100644 --- a/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java +++ b/model/model-assembler/src/main/java/io/spine/model/assemble/AssignLookup.java @@ -23,7 +23,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.ProtocolStringList; import io.spine.annotation.Internal; -import io.spine.io.Files2; import io.spine.model.CommandHandlers; import io.spine.server.command.Assign; @@ -39,7 +38,6 @@ import static com.google.common.collect.Sets.newHashSet; import static com.google.common.collect.Sets.newTreeSet; -import static com.google.common.io.Files.createParentDirs; import static io.spine.io.Files2.ensureFile; import static io.spine.io.Files2.existsNonEmpty; import static io.spine.validate.Validate.isDefault; From ea04d7a4fd9599d99add46937e1f11835c41f6f6 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 22:01:38 +0300 Subject: [PATCH 24/53] Improve code layout --- .../server/entity/RecordBasedRepository.java | 117 +++++++++--------- .../io/spine/server/entity/Repository.java | 59 +++++---- .../projection/ProjectionEventDelivery.java | 2 +- .../projection/ProjectionRepository.java | 29 +++-- 4 files changed, 106 insertions(+), 101 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index d00bae511f7..ecb071cc550 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -92,7 +92,7 @@ protected RecordBasedRepository() { */ protected RecordStorage recordStorage() { @SuppressWarnings("unchecked") // OK as we control the creation in createStorage(). - final RecordStorage storage = (RecordStorage) getStorage(); + RecordStorage storage = (RecordStorage) getStorage(); return storage; } @@ -112,29 +112,29 @@ public void onRegistered() { /** {@inheritDoc} */ @Override public E create(I id) { - final E result = entityFactory().create(id); + E result = entityFactory().create(id); return result; } /** {@inheritDoc} */ @Override public void store(E entity) { - final EntityRecordWithColumns record = toRecord(entity); - final RecordStorage storage = recordStorage(); + EntityRecordWithColumns record = toRecord(entity); + RecordStorage storage = recordStorage(); storage.write(entity.getId(), record); } @Override public Iterator iterator(Predicate filter) { - final Iterator allEntities = loadAll(); - final Iterator result = filter(allEntities, filter); + Iterator allEntities = loadAll(); + Iterator result = filter(allEntities, filter); return result; } /** {@inheritDoc} */ @Override protected RecordStorage createStorage(StorageFactory factory) { - final RecordStorage result = factory.createRecordStorage(getEntityClass()); + RecordStorage result = factory.createRecordStorage(getEntityClass()); return result; } @@ -146,9 +146,9 @@ protected RecordStorage createStorage(StorageFactory factory) { * @param entities the {@linkplain Entity Entities} to store */ public void store(Collection entities) { - final Map records = newHashMapWithExpectedSize(entities.size()); + Map records = newHashMapWithExpectedSize(entities.size()); for (E entity : entities) { - final EntityRecordWithColumns recordWithColumns = toRecord(entity); + EntityRecordWithColumns recordWithColumns = toRecord(entity); records.put(entity.getId(), recordWithColumns); } recordStorage().write(records); @@ -159,7 +159,7 @@ public void store(Collection entities) { */ @Internal public void storeRecord(EntityRecord record) { - final E entity = toEntity(record); + E entity = toEntity(record); store(entity); } @@ -177,12 +177,12 @@ public Optional find(I id) { if (!optional.isPresent()) { return Optional.absent(); } - final EntityRecord record = optional.get(); - final boolean recordVisible = isEntityVisible().apply(record.getLifecycleFlags()); + EntityRecord record = optional.get(); + boolean recordVisible = isEntityVisible().apply(record.getLifecycleFlags()); if (!recordVisible) { return Optional.absent(); } - final E entity = toEntity(record); + E entity = toEntity(record); return Optional.of(entity); } @@ -191,20 +191,20 @@ public Optional find(I id) { * {@linkplain EntityWithLifecycle.Predicates#isEntityVisible()}. */ private Optional findRecord(I id) { - final RecordStorage storage = recordStorage(); - final RecordReadRequest request = new RecordReadRequest<>(id); - final Optional found = storage.read(request); + RecordStorage storage = recordStorage(); + RecordReadRequest request = new RecordReadRequest<>(id); + Optional found = storage.read(request); if (!found.isPresent()) { return Optional.absent(); } - final EntityRecord record = found.get(); + EntityRecord record = found.get(); return Optional.of(record); } @Internal public EntityRecord findOrCreateRecord(I id) { - final E entity = findOrCreate(id); - final EntityRecordWithColumns recordWithColumns = toRecord(entity); + E entity = findOrCreate(id); + EntityRecordWithColumns recordWithColumns = toRecord(entity); return recordWithColumns.getRecord(); } @@ -225,8 +225,8 @@ protected E findOrCreate(I id) { if (!optional.isPresent()) { return create(id); } - final EntityRecord record = optional.get(); - final E entity = toEntity(record); + EntityRecord record = optional.get(); + E entity = toEntity(record); return entity; } @@ -274,12 +274,11 @@ public Iterator loadAll(Iterable ids) { * @see #loadAll(Iterable) */ public Iterator loadAll(Iterable ids, FieldMask fieldMask) { - final RecordStorage storage = recordStorage(); - final Iterator entityStorageRecords = storage.readMultiple(ids, fieldMask); - final Iterator presentRecords = filter(entityStorageRecords, - Predicates.notNull()); - final Function toEntity = entityConverter().reverse(); - final Iterator result = transform(presentRecords, toEntity); + RecordStorage storage = recordStorage(); + Iterator entityStorageRecords = storage.readMultiple(ids, fieldMask); + Iterator presentRecords = filter(entityStorageRecords, Predicates.notNull()); + Function toEntity = entityConverter().reverse(); + Iterator result = transform(presentRecords, toEntity); return result; } @@ -292,10 +291,10 @@ public Iterator loadAll(Iterable ids, FieldMask fieldMask) { * @see #loadAll(Iterable) */ public Iterator loadAll() { - final RecordStorage storage = recordStorage(); - final Iterator records = storage.readAll(); - final Function toEntity = entityConverter().reverse(); - final Iterator result = transform(records, toEntity); + RecordStorage storage = recordStorage(); + Iterator records = storage.readAll(); + Function toEntity = entityConverter().reverse(); + Iterator result = transform(records, toEntity); return result; } @@ -321,11 +320,11 @@ public Iterator find(EntityFilters filters, FieldMask fieldMask) { checkNotNull(filters); checkNotNull(fieldMask); - final EntityQuery entityQuery = EntityQueries.from(filters, recordStorage()); - final EntityQuery completeQuery = toCompleteQuery(entityQuery); - final Iterator records = recordStorage().readAll(completeQuery, fieldMask); - final Function toEntity = entityConverter().reverse(); - final Iterator result = transform(records, toEntity); + EntityQuery entityQuery = EntityQueries.from(filters, recordStorage()); + EntityQuery completeQuery = toCompleteQuery(entityQuery); + Iterator records = recordStorage().readAll(completeQuery, fieldMask); + Function toEntity = entityConverter().reverse(); + Iterator result = transform(records, toEntity); return result; } @@ -341,8 +340,8 @@ public Iterator findRecords(EntityFilters filters, FieldMask field checkNotNull(filters); checkNotNull(fieldMask); - final EntityQuery entityQuery = EntityQueries.from(filters, recordStorage()); - final EntityQuery completeQuery = toCompleteQuery(entityQuery); + EntityQuery entityQuery = EntityQueries.from(filters, recordStorage()); + EntityQuery completeQuery = toCompleteQuery(entityQuery); return recordStorage().readAll(completeQuery, fieldMask); } @@ -377,7 +376,7 @@ public Iterator findRecords(EntityFilters filters, FieldMask field * they are not supported */ private EntityQuery toCompleteQuery(EntityQuery src) { - final EntityQuery completeQuery; + EntityQuery completeQuery; if (!src.isLifecycleAttributesSet() && EntityWithLifecycle.class.isAssignableFrom(getEntityClass())) { completeQuery = src.withLifecycleFlags(recordStorage()); @@ -391,25 +390,27 @@ private EntityQuery toCompleteQuery(EntityQuery src) { * Converts the passed entity into the record. */ protected EntityRecordWithColumns toRecord(E entity) { - final EntityRecord entityRecord = entityConverter().convert(entity); + EntityRecord entityRecord = entityConverter().convert(entity); checkNotNull(entityRecord); - final EntityRecordWithColumns recordWithColumns = + EntityRecordWithColumns result = EntityRecordWithColumns.create(entityRecord, entity, recordStorage()); - return recordWithColumns; + return result; } private E toEntity(EntityRecord record) { - final E result = entityConverter().reverse() - .convert(record); + E result = entityConverter().reverse() + .convert(record); + checkNotNull(result); return result; } /** - * Retrieves the {@link EntityColumnCache} used by this repository's {@linkplain RecordStorage storage}. + * Retrieves the {@link EntityColumnCache} used by this repository's + * {@linkplain RecordStorage storage}. * * @return the entity column cache from the storage - * @throws IllegalStateException if the {@link EntityColumnCache} is not supported by this - * repository's storage + * @throws IllegalStateException + * if the {@link EntityColumnCache} is not supported by this repository's storage */ private EntityColumnCache columnCache() { return recordStorage().entityColumnCache(); @@ -419,7 +420,8 @@ private EntityColumnCache columnCache() { * Caches {@link Column} definitions of the {@link Entity} class managed by this repository. * *

The process of caching columns also acts as a check of {@link Column} definitions, - * because {@linkplain Column columns} with incorrect definitions cannot be retrieved and stored. + * because {@linkplain Column columns} with incorrect definitions cannot be retrieved and + * stored. * *

If {@link Column} definitions are incorrect, the {@link IllegalStateException} is thrown. * @@ -444,26 +446,25 @@ public EntityIdFunction(Class expectedIdClass) { this.expectedIdClass = expectedIdClass; } - @Nullable @Override - public I apply(@Nullable EntityId input) { + public @Nullable I apply(@Nullable EntityId input) { checkNotNull(input); - final Any idAsAny = input.getId(); + Any idAsAny = input.getId(); - final TypeUrl typeUrl = TypeUrl.ofEnclosed(idAsAny); - final Class messageClass = typeUrl.getJavaClass(); + TypeUrl typeUrl = TypeUrl.ofEnclosed(idAsAny); + Class messageClass = typeUrl.getJavaClass(); checkIdClass(messageClass); - final Message idAsMessage = unpack(idAsAny); + Message idAsMessage = unpack(idAsAny); - @SuppressWarnings("unchecked") - // As the message class is the same as expected, the conversion is safe. - final I id = (I) idAsMessage; + @SuppressWarnings("unchecked") /* As the message class is the same as expected, + the conversion is safe. */ + I id = (I) idAsMessage; return id; } private void checkIdClass(Class messageClass) { - final boolean classIsSame = expectedIdClass.equals(messageClass); + boolean classIsSame = expectedIdClass.equals(messageClass); if (!classIsSame) { throw newIllegalStateException("Unexpected ID class encountered: %s. Expected: %s", messageClass, expectedIdClass); diff --git a/server/src/main/java/io/spine/server/entity/Repository.java b/server/src/main/java/io/spine/server/entity/Repository.java index 73c7f4b969b..613fafc280a 100644 --- a/server/src/main/java/io/spine/server/entity/Repository.java +++ b/server/src/main/java/io/spine/server/entity/Repository.java @@ -100,8 +100,7 @@ protected Repository() { protected final EntityClass entityClass() { if (entityClass == null) { @SuppressWarnings("unchecked") // The type is ensured by the declaration of this class. - final Class cast = - (Class)ENTITY.getArgumentIn(getClass()); + Class cast = (Class) ENTITY.getArgumentIn(getClass()); entityClass = getModelClass(cast); } return entityClass; @@ -240,11 +239,26 @@ private boolean managesVersionableEntities() { */ @Override public Iterator iterator(Predicate filter) { - final Iterator unfiltered = new EntityIterator<>(this); - final Iterator filtered = Iterators.filter(unfiltered, filter); + Iterator unfiltered = new EntityIterator<>(this); + Iterator filtered = Iterators.filter(unfiltered, filter); return filtered; } + /** + * Initializes the storage using the passed factory. + * + * @param factory storage factory + * @throws IllegalStateException if the repository already has storage initialized + */ + public void initStorage(StorageFactory factory) { + if (this.storage != null) { + throw newIllegalStateException("The repository %s already has storage %s.", + this, this.storage); + } + + this.storage = createStorage(factory); + } + /** * Returns the storage assigned to this repository. * @@ -274,19 +288,9 @@ protected static S checkStorage(@Nullable S storage) { return storage; } - /** - * Initializes the storage using the passed factory. - * - * @param factory storage factory - * @throws IllegalStateException if the repository already has storage initialized - */ - public void initStorage(StorageFactory factory) { - if (this.storage != null) { - throw newIllegalStateException("The repository %s already has storage %s.", - this, this.storage); - } - - this.storage = createStorage(factory); + private Storage ensureStorage() { + checkState(storage != null, "No storage assigned in repository %s", this); + return storage; } /** @@ -320,11 +324,6 @@ public boolean isOpen() { return storage != null; } - private Storage ensureStorage() { - checkState(storage != null, "No storage assigned in repository %s", this); - return storage; - } - /** * Ensures that the repository {@linkplain #isOpen() is open}. * @@ -357,9 +356,9 @@ protected Logger log() { protected void logError(String msgFormat, MessageEnvelope envelope, RuntimeException exception) { - final MessageClass messageClass = envelope.getMessageClass(); - final String messageId = Stringifiers.toString(envelope.getId()); - final String errorMessage = format(msgFormat, messageClass, messageId); + MessageClass messageClass = envelope.getMessageClass(); + String messageId = Stringifiers.toString(envelope.getId()); + String errorMessage = format(msgFormat, messageClass, messageId); log().error(errorMessage, exception); } @@ -409,20 +408,20 @@ private EntityIterator(Repository repository) { @Override public boolean hasNext() { - final boolean result = index.hasNext(); + boolean result = index.hasNext(); return result; } @Override public E next() { - final I id = index.next(); - final Optional loaded = repository.find(id); + I id = index.next(); + Optional loaded = repository.find(id); if (!loaded.isPresent()) { - final String idStr = Identifier.toString(id); + String idStr = Identifier.toString(id); throw newIllegalStateException("Unable to load entity with ID: %s", idStr); } - final E entity = loaded.get(); + E entity = loaded.get(); return entity; } diff --git a/server/src/main/java/io/spine/server/projection/ProjectionEventDelivery.java b/server/src/main/java/io/spine/server/projection/ProjectionEventDelivery.java index 87463fdd79f..bd0e048095f 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionEventDelivery.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionEventDelivery.java @@ -45,7 +45,7 @@ public class ProjectionEventDelivery> EventShardedStream.Builder> { protected ProjectionEventDelivery(ProjectionRepository repository) { - super(new ProjectionEventConsumer(repository)); + super(new ProjectionEventConsumer<>(repository)); } private static class ProjectionEventConsumer> diff --git a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java index e8ef66f3c4a..ad51575dc5a 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java @@ -72,6 +72,8 @@ public abstract class ProjectionRepository, S e extends EventDispatchingRepository implements Shardable { + @SuppressWarnings("ThisEscapedInObjectConstruction") + // OK since `this` is referenced from the supplier private final Supplier> eventDeliverySupplier = memoize(() -> new ProjectionEventDelivery<>(this)); @@ -100,7 +102,7 @@ EventStore getEventStore() { /** Obtains class information of projection managed by this repository. */ @SuppressWarnings("unchecked") - // The cast is ensured by generic parameters of the repository. + // The cast is ensured by generic parameters of the repository. ProjectionClass

projectionClass() { return (ProjectionClass

) entityClass(); } @@ -208,9 +210,8 @@ protected RecordStorage recordStorage() { we create a specific type of a storage, not a regular entity storage created in the parent. */) protected RecordStorage createStorage(StorageFactory factory) { - final Class

projectionClass = getEntityClass(); - final ProjectionStorage projectionStorage = - factory.createProjectionStorage(projectionClass); + Class

projectionClass = getEntityClass(); + ProjectionStorage projectionStorage = factory.createProjectionStorage(projectionClass); this.recordStorage = projectionStorage.recordStorage(); return projectionStorage; } @@ -241,7 +242,10 @@ protected ProjectionStorage projectionStorage() { @Override public Set getMessageClasses() { return projectionClass().getEventSubscriptions(); - } @Override + } + + /** {@inheritDoc} */ + @Override public Set dispatch(EventEnvelope envelope) { return ProjectionEndpoint.handle(this, envelope); } @@ -263,10 +267,11 @@ EventStreamQuery createStreamQuery() { // Get the timestamp of the last event. This also ensures we have the storage. Timestamp timestamp = readLastHandledEventTime(); - return EventStreamQuery.newBuilder() - .setAfter(timestamp) - .addAllFilter(eventFilters) - .build(); + EventStreamQuery.Builder builder = EventStreamQuery + .newBuilder() + .setAfter(timestamp) + .addAllFilter(eventFilters); + return builder.build(); } /** @@ -297,14 +302,14 @@ public ShardingStrategy getShardingStrategy() { @Override public Iterable> getMessageConsumers() { - final Iterable> result = + Iterable> result = ImmutableList.of(getEndpointDelivery().getConsumer()); return result; } @Override public BoundedContextName getBoundedContextName() { - final BoundedContextName name = getBoundedContext().getName(); + BoundedContextName name = getBoundedContext().getName(); return name; } @@ -321,7 +326,7 @@ private class ProjectionExternalEventDispatcher extends AbstractExternalEventDis @Override public Set getMessageClasses() { - final Set eventClasses = projectionClass().getExternalEventSubscriptions(); + Set eventClasses = projectionClass().getExternalEventSubscriptions(); return ExternalMessageClass.fromEventClasses(eventClasses); } From dc646e0e81b4f818b93d67c61016f9ba753bd64a Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 22:02:43 +0300 Subject: [PATCH 25/53] Fix EOF --- .idea/codeStyles/Project.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index fafa9ba0439..6ad22fe911f 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -57,4 +57,4 @@ - \ No newline at end of file + From 8a9ec748cb36061bc77efb21c2f8e397738b873c Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:09:45 +0300 Subject: [PATCH 26/53] Extract aggregate reading operation as a method object --- .../server/aggregate/AggregateStorage.java | 102 ++++----------- .../spine/server/aggregate/ReadOperation.java | 117 ++++++++++++++++++ 2 files changed, 141 insertions(+), 78 deletions(-) create mode 100644 server/src/main/java/io/spine/server/aggregate/ReadOperation.java diff --git a/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java b/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java index 53feb93afd0..25be37859a5 100644 --- a/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java +++ b/server/src/main/java/io/spine/server/aggregate/AggregateStorage.java @@ -29,17 +29,13 @@ import io.spine.server.storage.AbstractStorage; import io.spine.server.storage.StorageWithLifecycleFlags; -import java.util.Deque; import java.util.Iterator; import java.util.List; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Lists.newLinkedList; -import static com.google.protobuf.TextFormat.shortDebugString; import static com.google.protobuf.util.Timestamps.checkValid; import static io.spine.core.Events.clearEnrichments; -import static io.spine.util.Exceptions.newIllegalStateException; import static io.spine.validate.Validate.checkNotEmptyOrBlank; /** @@ -57,9 +53,20 @@ protected AggregateStorage(boolean multitenant) { super(multitenant); } + /** + * {@inheritDoc} + * + *

Opens the method for the package. + */ + @SuppressWarnings("RedundantMethodOverride") + @Override + protected void checkNotClosed() throws IllegalStateException { + super.checkNotClosed(); + } + /** * Forms and returns an {@link AggregateStateRecord} based on the - * {@linkplain #historyBackward(AggregateReadRequest) aggregate histor@Vhey}. + * {@linkplain #historyBackward(AggregateReadRequest) aggregate history}. * * @param request the aggregate read request based on which to form a record * @return the record instance or {@code Optional.absent()} if the @@ -69,69 +76,8 @@ protected AggregateStorage(boolean multitenant) { @SuppressWarnings("CheckReturnValue") // calling builder method @Override public Optional read(AggregateReadRequest request) { - checkNotClosed(); - checkNotNull(request); - - final Deque history = newLinkedList(); - Snapshot snapshot = null; - - final Iterator historyBackward = historyBackward(request); - - if (!historyBackward.hasNext()) { - return Optional.absent(); - } - - while (historyBackward.hasNext() - && snapshot == null) { - - final AggregateEventRecord record = historyBackward.next(); - - switch (record.getKindCase()) { - case EVENT: - history.addFirst(record.getEvent()); - break; - case SNAPSHOT: - snapshot = record.getSnapshot(); - break; - case KIND_NOT_SET: - default: - throw newIllegalStateException("Event or snapshot missing in record: \"%s\"", - shortDebugString(record)); - } - } - - final AggregateStateRecord.Builder builder = AggregateStateRecord.newBuilder(); - if (snapshot != null) { - builder.setSnapshot(snapshot); - } - builder.addAllEvent(history); - - final AggregateStateRecord result = builder.build(); - checkAggregateStateRecord(result); - return Optional.of(result); - } - - /** - * Ensures that the {@link AggregateStateRecord} is valid. - * - *

{@link AggregateStateRecord} is considered valid when one of the following is true: - *

    - *
  • {@linkplain AggregateStateRecord#getSnapshot() snapshot} is not default; - *
  • {@linkplain AggregateStateRecord#getEventList() event list} is not empty. - *
- * - * @param record the record to check - * @throws IllegalStateException if the {@link AggregateStateRecord} is not valid - */ - private static void checkAggregateStateRecord(AggregateStateRecord record) - throws IllegalStateException { - final boolean snapshotIsNotSet = record.getSnapshot() - .equals(Snapshot.getDefaultInstance()); - if (snapshotIsNotSet && record.getEventList() - .isEmpty()) { - throw new IllegalStateException("AggregateStateRecord instance should have either " - + "snapshot or non-empty event list."); - } + ReadOperation op = new ReadOperation<>(this, request); + return op.perform(); } /** @@ -146,11 +92,11 @@ private static void checkAggregateStateRecord(AggregateStateRecord record) public void write(I id, AggregateStateRecord events) { checkNotClosedAndArguments(id, events); - final List eventList = events.getEventList(); + List eventList = events.getEventList(); checkArgument(!eventList.isEmpty(), "Event list must not be empty."); - for (final Event event : eventList) { - final AggregateEventRecord record = toStorageRecord(event); + for (Event event : eventList) { + AggregateEventRecord record = toStorageRecord(event); writeRecord(id, record); } } @@ -167,8 +113,8 @@ public void write(I id, AggregateStateRecord events) { void writeEvent(I id, Event event) { checkNotClosedAndArguments(id, event); - final Event eventWithoutEnrichments = clearEnrichments(event); - final AggregateEventRecord record = toStorageRecord(eventWithoutEnrichments); + Event eventWithoutEnrichments = clearEnrichments(event); + AggregateEventRecord record = toStorageRecord(eventWithoutEnrichments); writeRecord(id, record); } @@ -181,7 +127,7 @@ void writeEvent(I id, Event event) { void writeSnapshot(I aggregateId, Snapshot snapshot) { checkNotClosedAndArguments(aggregateId, snapshot); - final AggregateEventRecord record = toStorageRecord(snapshot); + AggregateEventRecord record = toStorageRecord(snapshot); writeRecord(aggregateId, record); } @@ -193,14 +139,14 @@ private void checkNotClosedAndArguments(I id, Object argument) { private static AggregateEventRecord toStorageRecord(Event event) { checkArgument(event.hasContext(), "Event context must be set."); - final EventContext context = event.getContext(); + EventContext context = event.getContext(); - final String eventIdStr = Identifier.toString(event.getId()); + String eventIdStr = Identifier.toString(event.getId()); checkNotEmptyOrBlank(eventIdStr, "Event ID"); checkArgument(event.hasMessage(), "Event message must be set."); - final Timestamp timestamp = checkValid(context.getTimestamp()); + Timestamp timestamp = checkValid(context.getTimestamp()); return AggregateEventRecord.newBuilder() .setTimestamp(timestamp) @@ -209,7 +155,7 @@ private static AggregateEventRecord toStorageRecord(Event event) { } private static AggregateEventRecord toStorageRecord(Snapshot snapshot) { - final Timestamp value = checkValid(snapshot.getTimestamp()); + Timestamp value = checkValid(snapshot.getTimestamp()); return AggregateEventRecord.newBuilder() .setTimestamp(value) .setSnapshot(snapshot) diff --git a/server/src/main/java/io/spine/server/aggregate/ReadOperation.java b/server/src/main/java/io/spine/server/aggregate/ReadOperation.java new file mode 100644 index 00000000000..8a09b3819a9 --- /dev/null +++ b/server/src/main/java/io/spine/server/aggregate/ReadOperation.java @@ -0,0 +1,117 @@ +/* + * Copyright 2018, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.aggregate; + +import com.google.common.base.Optional; +import io.spine.core.Event; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; + +import java.util.Deque; +import java.util.Iterator; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Lists.newLinkedList; +import static com.google.protobuf.TextFormat.shortDebugString; +import static io.spine.util.Exceptions.newIllegalStateException; + +/** + * Method object for reading {@link AggregateStateRecord}s. + * + * @param the type of aggregate IDs + * @author Alexander Yevsyukov + */ +final class ReadOperation { + + private final AggregateStorage storage; + private final AggregateReadRequest request; + private final Deque history = newLinkedList(); + + private @MonotonicNonNull Snapshot snapshot = null; + + ReadOperation(AggregateStorage storage, AggregateReadRequest request) { + storage.checkNotClosed(); + this.storage = storage; + this.request = checkNotNull(request); + } + + Optional perform() { + Iterator historyBackward = storage.historyBackward(request); + if (!historyBackward.hasNext()) { + return Optional.absent(); + } + + while (historyBackward.hasNext() + && snapshot == null) { + + AggregateEventRecord record = historyBackward.next(); + + switch (record.getKindCase()) { + case EVENT: + history.addFirst(record.getEvent()); + break; + case SNAPSHOT: + snapshot = record.getSnapshot(); + break; + case KIND_NOT_SET: + default: + throw newIllegalStateException("Event or snapshot missing in record: \"%s\"", + shortDebugString(record)); + } + } + + AggregateStateRecord result = buildRecord(); + return Optional.of(result); + } + + private AggregateStateRecord buildRecord() { + AggregateStateRecord.Builder builder = AggregateStateRecord.newBuilder(); + if (snapshot != null) { + builder.setSnapshot(snapshot); + } + builder.addAllEvent(history); + + AggregateStateRecord result = builder.build(); + checkRecord(result); + return result; + } + + /** + * Ensures that the {@link AggregateStateRecord} is valid. + * + *

{@link AggregateStateRecord} is considered valid when one of the following is true: + *

    + *
  • {@linkplain AggregateStateRecord#getSnapshot() snapshot} is not default; + *
  • {@linkplain AggregateStateRecord#getEventList() event list} is not empty. + *
+ * + * @param record the record to check + * @throws IllegalStateException if the {@link AggregateStateRecord} is not valid + */ + private static void checkRecord(AggregateStateRecord record) throws IllegalStateException { + boolean snapshotIsNotSet = !record.hasSnapshot(); + boolean noEvents = record.getEventList() + .isEmpty(); + if (noEvents && snapshotIsNotSet) { + throw new IllegalStateException("AggregateStateRecord instance should have either " + + "snapshot or non-empty event list."); + } + } +} From 2d153ea37c2d4f8d17f48169c99e2d03f258653a Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:24:24 +0300 Subject: [PATCH 27/53] Improve code layout --- .../java/io/spine/server/commandbus/CommandBus.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/io/spine/server/commandbus/CommandBus.java b/server/src/main/java/io/spine/server/commandbus/CommandBus.java index 236e81e1300..2ded8522831 100644 --- a/server/src/main/java/io/spine/server/commandbus/CommandBus.java +++ b/server/src/main/java/io/spine/server/commandbus/CommandBus.java @@ -353,8 +353,8 @@ public static class Builder extends AbstractBuilder @Override public UnsupportedCommandException handle(CommandEnvelope message) { - final Command command = message.getCommand(); - final UnsupportedCommandException exception = new UnsupportedCommandException(command); + Command command = message.getCommand(); + UnsupportedCommandException exception = new UnsupportedCommandException(command); commandStore().storeWithError(command, exception); return exception; } From 352edf0880510f681c3cb80a5378d933895d85c9 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:30:50 +0300 Subject: [PATCH 28/53] Remove redundant `inheritDoc` --- .../server/entity/RecordBasedRepository.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index ecb071cc550..98f10b3e6ae 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -109,14 +109,12 @@ public void onRegistered() { cacheEntityColumns(); } - /** {@inheritDoc} */ @Override public E create(I id) { E result = entityFactory().create(id); return result; } - /** {@inheritDoc} */ @Override public void store(E entity) { EntityRecordWithColumns record = toRecord(entity); @@ -131,7 +129,6 @@ public Iterator iterator(Predicate filter) { return result; } - /** {@inheritDoc} */ @Override protected RecordStorage createStorage(StorageFactory factory) { RecordStorage result = factory.createRecordStorage(getEntityClass()); @@ -163,6 +160,13 @@ public void storeRecord(EntityRecord record) { store(entity); } + @Internal + public EntityRecord findOrCreateRecord(I id) { + E entity = findOrCreate(id); + EntityRecordWithColumns recordWithColumns = toRecord(entity); + return recordWithColumns.getRecord(); + } + /** * Finds an entity with the passed ID if this entity is * {@linkplain EntityWithLifecycle.Predicates#isEntityVisible() visible}. @@ -201,13 +205,6 @@ private Optional findRecord(I id) { return Optional.of(record); } - @Internal - public EntityRecord findOrCreateRecord(I id) { - E entity = findOrCreate(id); - EntityRecordWithColumns recordWithColumns = toRecord(entity); - return recordWithColumns.getRecord(); - } - /** * Loads an entity by the passed ID or creates a new one, if the entity was not found. * From 203a3ad733b54aceb2c3bfe37452fec5b480d669 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:31:42 +0300 Subject: [PATCH 29/53] Remove unused methods --- .../server/entity/RecordBasedRepository.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index 98f10b3e6ae..e6e57f33e03 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -151,22 +151,6 @@ public void store(Collection entities) { recordStorage().write(records); } - /** - * Stores the passed entity record. - */ - @Internal - public void storeRecord(EntityRecord record) { - E entity = toEntity(record); - store(entity); - } - - @Internal - public EntityRecord findOrCreateRecord(I id) { - E entity = findOrCreate(id); - EntityRecordWithColumns recordWithColumns = toRecord(entity); - return recordWithColumns.getRecord(); - } - /** * Finds an entity with the passed ID if this entity is * {@linkplain EntityWithLifecycle.Predicates#isEntityVisible() visible}. From 505821b73a03797b03d7dccd7986d42bb28d4a2d Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:37:09 +0300 Subject: [PATCH 30/53] Fix Javadoc layout --- .../spine/server/entity/RecordBasedRepository.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index e6e57f33e03..662130c8afa 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -329,14 +329,14 @@ public Iterator findRecords(EntityFilters filters, FieldMask field /** * Creates an {@link EntityQuery} instance which has: *
    - *
  • All the parameters from the {@code src} Query; - *
  • At least one parameter limiting - * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns}. + *
  • All the parameters from the {@code src} Query; + *
  • At least one parameter limiting + * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns}. *
* *

If the {@code src} instance * {@linkplain EntityQuery#isLifecycleAttributesSet() contains the lifecycle attributes}, then - * it is returned with no change. Otherwise - a new instance containing the default values for + * it is returned with no change. Otherwise, a new instance containing the default values for * the Lifecycle attributes is returned. * *

The default values are: @@ -353,8 +353,8 @@ public Iterator findRecords(EntityFilters filters, FieldMask field * * @param src the source {@link EntityQuery} to take the parameters from * @return an {@link EntityQuery} which includes - * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns} unless - * they are not supported + * the {@link io.spine.server.storage.LifecycleFlagField Lifecycle Flags Columns} unless + * they are not supported */ private EntityQuery toCompleteQuery(EntityQuery src) { EntityQuery completeQuery; From ec2cab923606e623e58d3d9bc3907c33e914dae8 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:39:55 +0300 Subject: [PATCH 31/53] Improve code layout --- .../io/spine/server/entity/RecordBasedRepository.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java index 662130c8afa..c4d1f54e251 100644 --- a/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java +++ b/server/src/main/java/io/spine/server/entity/RecordBasedRepository.java @@ -358,12 +358,10 @@ public Iterator findRecords(EntityFilters filters, FieldMask field */ private EntityQuery toCompleteQuery(EntityQuery src) { EntityQuery completeQuery; - if (!src.isLifecycleAttributesSet() - && EntityWithLifecycle.class.isAssignableFrom(getEntityClass())) { - completeQuery = src.withLifecycleFlags(recordStorage()); - } else { - completeQuery = src; - } + completeQuery = !src.isLifecycleAttributesSet() + && EntityWithLifecycle.class.isAssignableFrom(getEntityClass()) + ? src.withLifecycleFlags(recordStorage()) + : src; return completeQuery; } From 425fae2dbc8910acc55ce02e1ead1392dfbae2e4 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Wed, 30 May 2018 23:41:51 +0300 Subject: [PATCH 32/53] Fix code layout --- .../main/java/io/spine/server/entity/storage/EntityColumn.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java index ea82346d658..43ec629d27f 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java @@ -235,7 +235,7 @@ public static EntityColumn from(Method getter) { Method annotatedVersion = retrieveAnnotatedVersion(getter); String nameForStore = nameFromAnnotation(annotatedVersion).or(nameForQuery); boolean nullable = getter.getAnnotatedReturnType() - .isAnnotationPresent(Nullable.class); + .isAnnotationPresent(Nullable.class); return new EntityColumn(getter, nameForQuery, nameForStore, nullable); } From 8917a707c978f583662998dd95d05192853f32cc Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 00:33:50 +0300 Subject: [PATCH 33/53] Allow several types of nullable annotations --- .../spine/server/aggregate/ReadOperation.java | 1 + .../server/entity/storage/ColumnReader.java | 2 +- .../server/entity/storage/ColumnRecords.java | 77 ------- .../server/entity/storage/EntityColumn.java | 65 +----- .../spine/server/entity/storage/Methods.java | 195 ++++++++++++++++++ .../server/entity/storage/MethodsShould.java | 36 ++++ 6 files changed, 241 insertions(+), 135 deletions(-) create mode 100644 server/src/main/java/io/spine/server/entity/storage/Methods.java create mode 100644 server/src/test/java/io/spine/server/entity/storage/MethodsShould.java diff --git a/server/src/main/java/io/spine/server/aggregate/ReadOperation.java b/server/src/main/java/io/spine/server/aggregate/ReadOperation.java index 8a09b3819a9..1339e2d7552 100644 --- a/server/src/main/java/io/spine/server/aggregate/ReadOperation.java +++ b/server/src/main/java/io/spine/server/aggregate/ReadOperation.java @@ -81,6 +81,7 @@ Optional perform() { return Optional.of(result); } + @SuppressWarnings("CheckReturnValue") // calling builder private AggregateStateRecord buildRecord() { AggregateStateRecord.Builder builder = AggregateStateRecord.newBuilder(); if (snapshot != null) { diff --git a/server/src/main/java/io/spine/server/entity/storage/ColumnReader.java b/server/src/main/java/io/spine/server/entity/storage/ColumnReader.java index d5e411d4b9e..0000d4634a0 100644 --- a/server/src/main/java/io/spine/server/entity/storage/ColumnReader.java +++ b/server/src/main/java/io/spine/server/entity/storage/ColumnReader.java @@ -32,7 +32,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Lists.newLinkedList; -import static io.spine.server.entity.storage.ColumnRecords.getAnnotatedVersion; +import static io.spine.server.entity.storage.Methods.getAnnotatedVersion; import static io.spine.util.Exceptions.newIllegalStateException; /** diff --git a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java index 76fc71e9761..67763159796 100644 --- a/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java +++ b/server/src/main/java/io/spine/server/entity/storage/ColumnRecords.java @@ -21,18 +21,10 @@ package io.spine.server.entity.storage; import com.google.common.base.Function; -import com.google.common.base.Optional; import io.spine.server.entity.storage.EntityColumn.MemoizedValue; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; - import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.Sets.newHashSet; import static java.lang.String.format; /** @@ -106,75 +98,6 @@ private static void feedColumn( setValue(columnValue, destination, columnIdentifier, columnType); } - /** - * Obtains the method version annotated with {@link Column} for the specified method. - * - *

Scans the specified method, the methods with the same signature - * from the super classes and interfaces. - * - * @param method the method to find the annotated version - * @return the annotated version of the specified method - * @throws IllegalStateException if there is more than one annotated method is found - * in the scanned classes - */ - static Optional getAnnotatedVersion(Method method) { - Set annotatedVersions = newHashSet(); - if (method.isAnnotationPresent(Column.class)) { - annotatedVersions.add(method); - } - Class declaringClass = method.getDeclaringClass(); - Iterable> ascendants = getSuperClassesAndInterfaces(declaringClass); - for (Class ascendant : ascendants) { - Optional optionalMethod = getMethodBySignature(ascendant, method); - if (optionalMethod.isPresent()) { - Method ascendantMethod = optionalMethod.get(); - if (ascendantMethod.isAnnotationPresent(Column.class)) { - annotatedVersions.add(ascendantMethod); - } - } - } - checkState(annotatedVersions.size() <= 1, - "An entity column getter should be annotated only once. " + - "Found the annotated versions: %s.", annotatedVersions); - if (annotatedVersions.isEmpty()) { - return Optional.absent(); - } else { - Method annotatedVersion = annotatedVersions.iterator() - .next(); - return Optional.of(annotatedVersion); - } - } - - private static Iterable> getSuperClassesAndInterfaces(Class cls) { - Collection> interfaces = Arrays.asList(cls.getInterfaces()); - Collection> result = newHashSet(interfaces); - Class currentSuper = cls.getSuperclass(); - while (currentSuper != null) { - result.add(currentSuper); - currentSuper = currentSuper.getSuperclass(); - } - return result; - } - - /** - * Obtains the method from the specified class with the same signature as the specified method. - * - * @param target the class to obtain the method with the signature - * @param method the method to get the signature - * @return the method with the same signature obtained from the specified class - */ - private static Optional getMethodBySignature(Class target, Method method) { - checkArgument(!method.getDeclaringClass() - .equals(target)); - try { - Method methodFromTarget = target.getMethod(method.getName(), - method.getParameterTypes()); - return Optional.of(methodFromTarget); - } catch (NoSuchMethodException ignored) { - return Optional.absent(); - } - } - private static void setValue(MemoizedValue columnValue, D destination, I columnIdentifier, diff --git a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java index 43ec629d27f..ff30066bd21 100644 --- a/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java +++ b/server/src/main/java/io/spine/server/entity/storage/EntityColumn.java @@ -22,7 +22,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; -import com.google.common.base.Optional; import io.spine.annotation.Internal; import io.spine.server.entity.Entity; import org.checkerframework.checker.nullness.qual.Nullable; @@ -32,19 +31,17 @@ import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.gson.internal.Primitives.wrap; -import static io.spine.server.entity.storage.ColumnRecords.getAnnotatedVersion; import static io.spine.server.entity.storage.ColumnValueConverters.of; +import static io.spine.server.entity.storage.Methods.checkGetter; +import static io.spine.server.entity.storage.Methods.hasNullableReturn; +import static io.spine.server.entity.storage.Methods.nameFromAnnotation; +import static io.spine.server.entity.storage.Methods.nameFromGetter; +import static io.spine.server.entity.storage.Methods.retrieveAnnotatedVersion; import static io.spine.util.Exceptions.newIllegalArgumentException; -import static io.spine.util.Exceptions.newIllegalStateException; import static java.lang.String.format; -import static java.lang.reflect.Modifier.isPublic; -import static java.lang.reflect.Modifier.isStatic; /** * The representation of a field of an {@link Entity} which is stored in the storage in the way @@ -168,9 +165,6 @@ public class EntityColumn implements Serializable { private static final long serialVersionUID = 0L; - private static final String GETTER_PREFIX_REGEX = "(get)|(is)"; - private static final Pattern GETTER_PREFIX_PATTERN = Pattern.compile(GETTER_PREFIX_REGEX); - /** *

The getter which declares this {@code EntityColumn}. * @@ -231,56 +225,13 @@ private EntityColumn(Method getter, */ public static EntityColumn from(Method getter) { checkGetter(getter); - String nameForQuery = nameFromGetter(getter); Method annotatedVersion = retrieveAnnotatedVersion(getter); + String nameForQuery = nameFromGetter(getter); String nameForStore = nameFromAnnotation(annotatedVersion).or(nameForQuery); - boolean nullable = getter.getAnnotatedReturnType() - .isAnnotationPresent(Nullable.class); + boolean nullable = hasNullableReturn(getter); return new EntityColumn(getter, nameForQuery, nameForStore, nullable); } - private static Method retrieveAnnotatedVersion(Method getter) { - Optional optionalMethod = getAnnotatedVersion(getter); - if (!optionalMethod.isPresent()) { - throw newIllegalStateException("Method `%s` is not an entity column getter.", getter); - } - return optionalMethod.get(); - } - - private static Optional nameFromAnnotation(Method getter) { - final String trimmedName = getter.getAnnotation(Column.class) - .name() - .trim(); - return trimmedName.isEmpty() - ? Optional.absent() - : Optional.of(trimmedName); - } - - private static String nameFromGetter(Method getter) { - final Matcher prefixMatcher = GETTER_PREFIX_PATTERN.matcher(getter.getName()); - final String nameWithoutPrefix = prefixMatcher.replaceFirst(""); - return Character.toLowerCase(nameWithoutPrefix.charAt(0)) + nameWithoutPrefix.substring(1); - } - - private static void checkGetter(Method getter) { - checkNotNull(getter); - checkArgument(GETTER_PREFIX_PATTERN.matcher(getter.getName()) - .find() && getter.getParameterTypes().length == 0, - "Method `%s` is not a getter.", getter); - checkArgument(getAnnotatedVersion(getter).isPresent(), - format("Entity column getter should be annotated with `%s`.", - Column.class.getName())); - final int modifiers = getter.getModifiers(); - checkArgument(isPublic(modifiers) && !isStatic(modifiers), - "Entity column getter should be public instance method."); - final Class returnType = getter.getReturnType(); - final Class wrapped = wrap(returnType); - checkArgument(Serializable.class.isAssignableFrom(wrapped), - format("Cannot create column of non-serializable type %s by method %s.", - returnType, - getter)); - } - /** * Obtains the name of the column, which is used for querying. * @@ -324,7 +275,7 @@ public boolean isNullable() { */ public @Nullable Serializable getFor(Entity source) { try { - final Serializable result = (Serializable) getter.invoke(source); + Serializable result = (Serializable) getter.invoke(source); if (!nullable) { checkNotNull(result, format("Not null getter %s returned null.", getter.getName())); } diff --git a/server/src/main/java/io/spine/server/entity/storage/Methods.java b/server/src/main/java/io/spine/server/entity/storage/Methods.java new file mode 100644 index 00000000000..7fc1975a9d5 --- /dev/null +++ b/server/src/main/java/io/spine/server/entity/storage/Methods.java @@ -0,0 +1,195 @@ +/* + * Copyright 2018, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.entity.storage; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; + +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Sets.newHashSet; +import static com.google.gson.internal.Primitives.wrap; +import static io.spine.util.Exceptions.newIllegalStateException; +import static java.lang.String.format; +import static java.lang.reflect.Modifier.isPublic; +import static java.lang.reflect.Modifier.isStatic; + +/** + * Utilities for working with methods. + * + * @author Dmytro Dashenkov + * @author Alexander Yevsyukov + */ +class Methods { + + private static final String GETTER_PREFIX_REGEX = "(get)|(is)"; + private static final Pattern GETTER_PREFIX_PATTERN = Pattern.compile(GETTER_PREFIX_REGEX); + private static final ImmutableSet NULLABLE_ANNOTATION_SIMPLE_NAMES = + ImmutableSet.of("CheckForNull", "Nullable", "NullableDecl", "NullableType"); + + /** Prevents instantiation of this utility class. */ + private Methods() { + } + + static Method retrieveAnnotatedVersion(Method getter) { + Optional optionalMethod = getAnnotatedVersion(getter); + if (!optionalMethod.isPresent()) { + throw newIllegalStateException("Method `%s` is not an entity column getter.", getter); + } + return optionalMethod.get(); + } + + static Optional nameFromAnnotation(Method getter) { + final String trimmedName = getter.getAnnotation(Column.class) + .name() + .trim(); + return trimmedName.isEmpty() + ? Optional.absent() + : Optional.of(trimmedName); + } + + static String nameFromGetter(Method getter) { + Matcher prefixMatcher = GETTER_PREFIX_PATTERN.matcher(getter.getName()); + String nameWithoutPrefix = prefixMatcher.replaceFirst(""); + String result = + Character.toLowerCase(nameWithoutPrefix.charAt(0)) + nameWithoutPrefix.substring(1); + return result; + } + + static boolean hasNullableReturn(Method getter) { + AnnotatedType type = getter.getAnnotatedReturnType(); + boolean result = isNullable(type.getAnnotations()); + return result; + } + + private static boolean isNullable(Annotation[] annotations) { + for (Annotation annotation : annotations) { + String simpleName = annotation.annotationType() + .getSimpleName(); + if (NULLABLE_ANNOTATION_SIMPLE_NAMES.contains(simpleName)) { + return true; + } + } + return false; + } + + static void checkGetter(Method getter) { + checkNotNull(getter); + checkArgument(GETTER_PREFIX_PATTERN.matcher(getter.getName()) + .find() + && getter.getParameterTypes().length == 0, + "Method `%s` is not a getter.", getter); + checkArgument(getAnnotatedVersion(getter).isPresent(), + format("Entity column getter should be annotated with `%s`.", + Column.class.getName())); + int modifiers = getter.getModifiers(); + checkArgument(isPublic(modifiers) && !isStatic(modifiers), + "Entity column getter should be public instance method."); + Class returnType = getter.getReturnType(); + Class wrapped = wrap(returnType); + checkArgument(Serializable.class.isAssignableFrom(wrapped), + format("Cannot create column of non-serializable type %s by method %s.", + returnType, + getter)); + } + + /** + * Obtains the method version annotated with {@link Column} for the specified method. + * + *

Scans the specified method, the methods with the same signature + * from the super classes and interfaces. + * + * @param method the method to find the annotated version + * @return the annotated version of the specified method + * @throws IllegalStateException if there is more than one annotated method is found + * in the scanned classes + */ + static Optional getAnnotatedVersion(Method method) { + Set annotatedVersions = newHashSet(); + if (method.isAnnotationPresent(Column.class)) { + annotatedVersions.add(method); + } + Class declaringClass = method.getDeclaringClass(); + Iterable> ascendants = getSuperClassesAndInterfaces(declaringClass); + for (Class ascendant : ascendants) { + Optional optionalMethod = getMethodBySignature(ascendant, method); + if (optionalMethod.isPresent()) { + Method ascendantMethod = optionalMethod.get(); + if (ascendantMethod.isAnnotationPresent(Column.class)) { + annotatedVersions.add(ascendantMethod); + } + } + } + + checkState(annotatedVersions.size() <= 1, + "An entity column getter should be annotated only once. " + + "Found the annotated versions: %s.", annotatedVersions); + + if (annotatedVersions.isEmpty()) { + return Optional.absent(); + } + + Method annotatedVersion = annotatedVersions.iterator() + .next(); + return Optional.of(annotatedVersion); + } + + private static Iterable> getSuperClassesAndInterfaces(Class cls) { + Collection> interfaces = Arrays.asList(cls.getInterfaces()); + Collection> result = newHashSet(interfaces); + Class currentSuper = cls.getSuperclass(); + while (currentSuper != null) { + result.add(currentSuper); + currentSuper = currentSuper.getSuperclass(); + } + return result; + } + + /** + * Obtains the method from the specified class with the same signature as the specified method. + * + * @param target the class to obtain the method with the signature + * @param method the method to get the signature + * @return the method with the same signature obtained from the specified class + */ + private static Optional getMethodBySignature(Class target, Method method) { + checkArgument(!method.getDeclaringClass() + .equals(target)); + try { + Method methodFromTarget = target.getMethod(method.getName(), + method.getParameterTypes()); + return Optional.of(methodFromTarget); + } catch (NoSuchMethodException ignored) { + return Optional.absent(); + } + } +} diff --git a/server/src/test/java/io/spine/server/entity/storage/MethodsShould.java b/server/src/test/java/io/spine/server/entity/storage/MethodsShould.java new file mode 100644 index 00000000000..23be0018597 --- /dev/null +++ b/server/src/test/java/io/spine/server/entity/storage/MethodsShould.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.server.entity.storage; + +import org.junit.Test; + +import static io.spine.test.Tests.assertHasPrivateParameterlessCtor; + +/** + * @author Alexander Yevsyukov + */ +public class MethodsShould { + + @Test + public void have_utility_ctor() { + assertHasPrivateParameterlessCtor(Methods.class); + } +} From dc9e982a72ad205c386b7bffe91b2f368ae0db4a Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 00:41:37 +0300 Subject: [PATCH 34/53] Simplify work with streams --- .../src/main/java/io/spine/server/event/EventStore.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/io/spine/server/event/EventStore.java b/server/src/main/java/io/spine/server/event/EventStore.java index f238da35100..522de0b3afb 100644 --- a/server/src/main/java/io/spine/server/event/EventStore.java +++ b/server/src/main/java/io/spine/server/event/EventStore.java @@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.base.Predicates; +import com.google.common.collect.Streams; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.TextFormat; import io.grpc.ServerServiceDefinition; @@ -42,7 +43,6 @@ import java.util.Set; import java.util.concurrent.Executor; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -84,10 +84,9 @@ public static ServiceBuilder newServiceBuilder() { private static void ensureSameTenant(Iterable events) { checkNotNull(events); - Set tenants = - StreamSupport.stream(events.spliterator(), false) - .map(Events::getTenantId) - .collect(Collectors.toSet()); + Set tenants = Streams.stream(events) + .map(Events::getTenantId) + .collect(Collectors.toSet()); checkArgument(tenants.size() == 1, TENANT_MISMATCH_ERROR_MSG, tenants); From a243fa3e71803a2ff21bb2dfac3223f85fc52ba4 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 00:46:06 +0300 Subject: [PATCH 35/53] Simplify var type --- server/src/main/java/io/spine/server/model/Model.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/io/spine/server/model/Model.java b/server/src/main/java/io/spine/server/model/Model.java index bf34749e589..e114ec128c1 100644 --- a/server/src/main/java/io/spine/server/model/Model.java +++ b/server/src/main/java/io/spine/server/model/Model.java @@ -23,7 +23,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.protobuf.Message; import io.spine.annotation.Internal; import io.spine.core.CommandClass; @@ -49,6 +48,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Sets.intersection; /** * Stores information of message handling classes. @@ -221,8 +221,7 @@ private void checkDuplicates(CommandHandlingClass candidate) if (modelClass instanceof CommandHandlingClass) { CommandHandlingClass commandHandler = (CommandHandlingClass) modelClass; Set commandClasses = commandHandler.getCommands(); - Sets.SetView intersection = - Sets.intersection(commandClasses, candidateCommands); + Set intersection = intersection(commandClasses, candidateCommands); if (intersection.size() > 0) { map.put(intersection, commandHandler); } From 860c0c20e8ece4c6f9694da4373b75c59438bd0c Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 00:48:54 +0300 Subject: [PATCH 36/53] Fix code layout --- .../io/spine/server/projection/ProjectionRepository.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java index ad51575dc5a..caee38af94a 100644 --- a/server/src/main/java/io/spine/server/projection/ProjectionRepository.java +++ b/server/src/main/java/io/spine/server/projection/ProjectionRepository.java @@ -233,18 +233,16 @@ protected P findOrCreate(I id) { * @throws IllegalStateException if the storage is null */ protected ProjectionStorage projectionStorage() { - @SuppressWarnings("unchecked") // OK as we control the creation in createStorage(). - ProjectionStorage storage = (ProjectionStorage) getStorage(); + @SuppressWarnings("unchecked") /* OK as we control the creation in createStorage(). */ + ProjectionStorage storage = (ProjectionStorage) getStorage(); return storage; } - /** {@inheritDoc} */ @Override public Set getMessageClasses() { return projectionClass().getEventSubscriptions(); } - /** {@inheritDoc} */ @Override public Set dispatch(EventEnvelope envelope) { return ProjectionEndpoint.handle(this, envelope); From 08d16b496efcc98da81b6d6d4da36cebb5760de6 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:08:53 +0300 Subject: [PATCH 37/53] Improve code layout --- .../storage/memory/InMemoryStandStorage.java | 6 +-- .../AggregatePartRepositoryLookupShould.java | 1 + .../server/aggregate/AggregateShould.java | 15 +++---- .../aggregate/AggregateStorageShould.java | 42 +++++++++---------- .../spine/server/bc/BoundedContextShould.java | 10 +++-- 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java index 511b16bc56d..6d000fbaa9e 100644 --- a/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java +++ b/server/src/main/java/io/spine/server/storage/memory/InMemoryStandStorage.java @@ -87,12 +87,12 @@ public Iterator readAllByType(final TypeUrl type, } private static Iterator filterByType(Iterator records, - final TypeUrl expectedType) { - final Iterator result = + TypeUrl expectedType) { + Iterator result = filter(records, entityRecord -> { checkNotNull(entityRecord); - final TypeUrl actualType = ofEnclosed(entityRecord.getState()); + TypeUrl actualType = ofEnclosed(entityRecord.getState()); return expectedType.equals(actualType); }); return result; diff --git a/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java b/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java index d8f0eb5db39..fa185c39e15 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregatePartRepositoryLookupShould.java @@ -179,6 +179,7 @@ public void apply(AggTaskAdded event) { private static class TaskAggregateRepository extends AggregateRepository { + private TaskAggregateRepository() { super(); } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateShould.java index 325e2f11193..7075b078481 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateShould.java @@ -69,7 +69,6 @@ import io.spine.test.aggregate.rejection.Rejections; import io.spine.test.aggregate.user.User; import io.spine.type.TypeUrl; -import io.spine.util.Exceptions; import io.spine.validate.ConstraintViolation; import org.junit.After; import org.junit.Before; @@ -109,6 +108,7 @@ import static io.spine.server.aggregate.given.aggregate.AggregateTestEnv.typeUrlOf; import static io.spine.server.entity.given.Given.aggregateOfClass; import static io.spine.test.Verify.assertSize; +import static io.spine.util.Exceptions.illegalStateWithCauseOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -180,7 +180,7 @@ private static void closeContext(BoundedContext boundedContext) { try { boundedContext.close(); } catch (Exception e) { - throw Exceptions.illegalStateWithCauseOf(e); + throw illegalStateWithCauseOf(e); } } @@ -582,8 +582,7 @@ public void propagate_RuntimeException_when_handler_throws() { dispatchCommand(faultyAggregate, env(command.getMessage())); failNotThrows(); } catch (RuntimeException e) { - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") // We need it for checking. - Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_HANDLER, cause.getMessage()); } @@ -600,9 +599,7 @@ public void propagate_RuntimeException_when_applier_throws() { dispatchCommand(faultyAggregate, env(command.getMessage())); failNotThrows(); } catch (RuntimeException e) { - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - // because we need it for checking. - Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_APPLIER, cause.getMessage()); } @@ -623,9 +620,7 @@ public void propagate_RuntimeException_when_play_raises_exception() { tx.commit(); failNotThrows(); } catch (RuntimeException e) { - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - // because we need it for checking. - Throwable cause = getRootCause(e); + Throwable cause = getRootCause(e); assertTrue(cause instanceof IllegalStateException); assertEquals(FaultyAggregate.BROKEN_APPLIER, cause.getMessage()); } diff --git a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java index 80f3bd93737..0539eeae501 100644 --- a/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java +++ b/server/src/test/java/io/spine/server/aggregate/AggregateStorageShould.java @@ -41,11 +41,11 @@ import io.spine.test.aggregate.ProjectId; import io.spine.test.aggregate.ProjectVBuilder; import io.spine.testdata.Sample; -import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newLinkedList; @@ -70,20 +70,14 @@ * @author Alexander Litus */ public abstract class AggregateStorageShould - extends AbstractStorageShould< - ProjectId, - AggregateStateRecord, - AggregateReadRequest, - AggregateStorage - > { - - protected static final Function TO_EVENT = - new Function() { - @Override // return null because an exception won't be propagated in this case - public @Nullable Event apply(@Nullable AggregateEventRecord input) { - return (input == null) ? null : input.getEvent(); - } - }; + extends AbstractStorageShould, + AggregateStorage> { + + private static final Function TO_EVENT = + record -> record != null ? record.getEvent() : null; + private final ProjectId id = Sample.messageOfType(ProjectId.class); private final TestEventFactory eventFactory = newInstance(AggregateStorageShould.class); private AggregateStorage storage; @@ -110,12 +104,14 @@ public void setUpAbstractStorageTest() { @Override protected AggregateStateRecord newStorageRecord() { List records = sequenceFor(id); - List expectedEvents = transform(records, TO_EVENT); - AggregateStateRecord aggregateStateRecord = - AggregateStateRecord.newBuilder() - .addAllEvent(expectedEvents) - .build(); - return aggregateStateRecord; + List expectedEvents = records.stream() + .map(TO_EVENT) + .collect(Collectors.toList()); + AggregateStateRecord record = AggregateStateRecord + .newBuilder() + .addAllEvent(expectedEvents) + .build(); + return record; } @Override @@ -166,9 +162,9 @@ public void return_iterator_over_empty_collection_if_read_history_from_empty_sto @Test public void return_absent_AggregateStateRecord_if_read_history_from_empty_storage() { AggregateReadRequest readRequest = newReadRequest(id); - Optional aggregateStateRecord = storage.read(readRequest); + Optional record = storage.read(readRequest); - assertFalse(aggregateStateRecord.isPresent()); + assertFalse(record.isPresent()); } @Test diff --git a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java index 7f0ad6e2896..e42c3d0226b 100644 --- a/server/src/test/java/io/spine/server/bc/BoundedContextShould.java +++ b/server/src/test/java/io/spine/server/bc/BoundedContextShould.java @@ -75,11 +75,13 @@ import static org.mockito.Mockito.when; /** - * Messages used in this test suite are defined in: + * Tests of {@link BoundedContext}. + * + *

Messages used in this test suite are defined in: *

    - *
  • spine/test/bc/project.proto - data types - *
  • spine/test/bc/command_factory_should.proto — commands - *
  • spine/test/bc/events.proto — events. + *
  • spine/test/bc/project.proto - data types + *
  • spine/test/bc/command_factory_should.proto — commands + *
  • spine/test/bc/events.proto — events. *
* * @author Alexander Litus From 621c4eb9f3cc8272b2a8448c114f08d07d1b48b5 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:12:56 +0300 Subject: [PATCH 38/53] Improve code layout --- .../server/entity/TransactionShould.java | 218 +++++++++--------- 1 file changed, 112 insertions(+), 106 deletions(-) diff --git a/server/src/test/java/io/spine/server/entity/TransactionShould.java b/server/src/test/java/io/spine/server/entity/TransactionShould.java index dbb22938e77..551a5835383 100644 --- a/server/src/test/java/io/spine/server/entity/TransactionShould.java +++ b/server/src/test/java/io/spine/server/entity/TransactionShould.java @@ -69,7 +69,33 @@ public abstract class TransactionShould someViolations() { + ConstraintViolation expectedViolation = ConstraintViolation + .newBuilder() + .setMsgFormat("Some violation %s") + .addParam("1") + .build(); + return newArrayList(expectedViolation); + } + + private static boolean checkPhase(Event event, Phase phase, boolean successful) { + Message eventMessage = Events.getMessage(event); + return eventMessage.equals(phase.getEventMessage()) + && event.getContext() + .equals(phase.getContext()) + && phase.isSuccessful() == successful; + } + + private static Version someVersion() { + return newVersion(42, getCurrentTime()); + } + protected abstract Transaction createTx(E entity); protected abstract Transaction createTxWithState(E entity, @@ -100,31 +126,33 @@ public void setUp() { @Test public void initialize_from_entity() { - final E entity = createEntity(); - final B expectedBuilder = entity.builderFromState(); - final Version expectedVersion = entity.getVersion(); - final LifecycleFlags expectedLifecycleFlags = entity.getLifecycleFlags(); + E entity = createEntity(); + B expectedBuilder = entity.builderFromState(); + Version expectedVersion = entity.getVersion(); + LifecycleFlags expectedLifecycleFlags = entity.getLifecycleFlags(); - final Transaction tx = createTx(entity); + Transaction tx = createTx(entity); assertNotNull(tx); assertEquals(entity, tx.getEntity()); // Not possible to compare `Message.Builder` instances via `equals`, so trigger `build()`. - assertEquals(expectedBuilder.build(), tx.getBuilder().build()); + assertEquals(expectedBuilder.build(), tx.getBuilder() + .build()); assertEquals(expectedVersion, tx.getVersion()); assertEquals(expectedLifecycleFlags, tx.getLifecycleFlags()); assertTrue(tx.isActive()); - assertTrue(tx.getPhases().isEmpty()); + assertTrue(tx.getPhases() + .isEmpty()); } @Test public void propagate_changes_to_entity_applier_methods() { - final E entity = createEntity(); - final Transaction tx = createTx(entity); + E entity = createEntity(); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessage()); + Event event = createEvent(createEventMessage()); applyEvent(tx, event); checkEventReceived(entity, event); @@ -132,77 +160,78 @@ public void propagate_changes_to_entity_applier_methods() { @Test public void create_phase_for_an_applied_event() { - final E entity = createEntity(); - final Transaction tx = createTx(entity); + E entity = createEntity(); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessage()); + Event event = createEvent(createEventMessage()); applyEvent(tx, event); - assertEquals(1, tx.getPhases().size()); - final Phase phase = tx.getPhases() - .get(0); + assertEquals(1, tx.getPhases() + .size()); + Phase phase = tx.getPhases() + .get(0); assertTrue(checkPhase(event, phase, true)); } @Test public void propagate_changes_to_entity_upon_commit() { - final E entity = createEntity(); + E entity = createEntity(); - final Transaction tx = createTx(entity); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessage()); + Event event = createEvent(createEventMessage()); applyEvent(tx, event); - final S stateBeforeCommit = entity.getState(); - final Version versionBeforeCommit = entity.getVersion(); + S stateBeforeCommit = entity.getState(); + Version versionBeforeCommit = entity.getVersion(); tx.commit(); - final S modifiedState = entity.getState(); - final Version modifiedVersion = entity.getVersion(); + S modifiedState = entity.getState(); + Version modifiedVersion = entity.getVersion(); assertNotEquals(stateBeforeCommit, modifiedState); assertNotEquals(versionBeforeCommit, modifiedVersion); } @Test public void not_propagate_changes_to_entity_on_rollback() { - final E entity = createEntity(); + E entity = createEntity(); - final Transaction tx = createTx(entity); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessage()); + Event event = createEvent(createEventMessage()); applyEvent(tx, event); - final S stateBeforeRollback = entity.getState(); - final Version versionBeforeRollback = entity.getVersion(); + S stateBeforeRollback = entity.getState(); + Version versionBeforeRollback = entity.getVersion(); tx.rollback(new RuntimeException("that triggers rollback")); - final S stateAfterRollback = entity.getState(); - final Version versionAfterRollback = entity.getVersion(); + S stateAfterRollback = entity.getState(); + Version versionAfterRollback = entity.getVersion(); assertEquals(stateBeforeRollback, stateAfterRollback); assertEquals(versionBeforeRollback, versionAfterRollback); } @Test public void set_txEntityVersion_from_EventContext() { - final E entity = createEntity(); + E entity = createEntity(); - final Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessage()); + Transaction tx = createTx(entity); + Event event = createEvent(createEventMessage()); - final Version ctxVersion = event.getContext() - .getVersion(); + Version ctxVersion = event.getContext() + .getVersion(); assertNotEquals(tx.getVersion(), ctxVersion); applyEvent(tx, event); - final Version modifiedVersion = tx.getVersion(); + Version modifiedVersion = tx.getVersion(); assertEquals(modifiedVersion, tx.getVersion()); } @Test @SuppressWarnings({"unchecked", "ConstantConditions"}) // OK for a test method. public void notify_listener_during_transaction_execution() { - final TransactionListener listener = mock(TransactionListener.class); - final E entity = createEntity(); - final Transaction tx = createTxWithListener(entity, listener); - final Event event = createEvent(createEventMessage()); + TransactionListener listener = mock(TransactionListener.class); + E entity = createEntity(); + Transaction tx = createTxWithListener(entity, listener); + Event event = createEvent(createEventMessage()); verifyZeroInteractions(listener); applyEvent(tx, event); @@ -211,17 +240,18 @@ public void notify_listener_during_transaction_execution() { } @Test - public void init_state_and_version_if_specified_in_ctor(){ - final E entity = createEntity(); - final S newState = createNewState(); - final Version newVersion = someVersion(); + public void init_state_and_version_if_specified_in_ctor() { + E entity = createEntity(); + S newState = createNewState(); + Version newVersion = someVersion(); assertNotEquals(entity.getState(), newState); assertNotEquals(entity.getVersion(), newVersion); - final Transaction tx = createTxWithState(entity, newState, newVersion); + Transaction tx = createTxWithState(entity, newState, newVersion); - assertEquals(newState, tx.getBuilder().build()); + assertEquals(newState, tx.getBuilder() + .build()); assertEquals(newVersion, tx.getVersion()); assertNotEquals(entity.getState(), newState); assertNotEquals(entity.getVersion(), newVersion); @@ -234,11 +264,11 @@ public void init_state_and_version_if_specified_in_ctor(){ @SuppressWarnings("CheckReturnValue") // can ignore new entity version in this test. @Test - public void not_allow_injecting_state_if_entity_has_non_zero_version_already(){ - E entity = createEntity(); + public void not_allow_injecting_state_if_entity_has_non_zero_version_already() { + E entity = createEntity(); entity.incrementVersion(); - S newState = createNewState(); - Version newVersion = someVersion(); + S newState = createNewState(); + Version newVersion = someVersion(); thrown.expect(IllegalStateException.class); createTxWithState(entity, newState, newVersion); @@ -246,11 +276,11 @@ public void not_allow_injecting_state_if_entity_has_non_zero_version_already(){ @Test public void propagate_phase_failure_exception_as_ISE() { - E entity = createEntity(); + E entity = createEntity(); - Transaction tx = createTx(entity); + Transaction tx = createTx(entity); - Event event = createEvent(createEventMessageThatFailsInHandler()); + Event event = createEvent(createEventMessageThatFailsInHandler()); thrown.expect(IllegalStateException.class); applyEvent(tx, event); @@ -258,33 +288,34 @@ public void propagate_phase_failure_exception_as_ISE() { @Test public void rollback_automatically_if_phase_failed() { - final E entity = createEntity(); - final S originalState = entity.getState(); - final Version originalVersion = entity.getVersion(); + E entity = createEntity(); + S originalState = entity.getState(); + Version originalVersion = entity.getVersion(); - final Transaction tx = createTx(entity); + Transaction tx = createTx(entity); - final Event event = createEvent(createEventMessageThatFailsInHandler()); + Event event = createEvent(createEventMessageThatFailsInHandler()); try { applyEvent(tx, event); fail("Expected an `Exception` due to a failed phase execution."); - } catch (final Exception e) { + } catch (Exception e) { checkRollback(entity, originalState, originalVersion); } } @Test public void propagate_exception_wrapped_as_ISE_if_commit_fails() { - E entity = createEntity(someViolations()); - S newState = createNewState(); - Version version = someVersion(); + E entity = createEntity(someViolations()); + S newState = createNewState(); + Version version = someVersion(); - Transaction tx = createTxWithState(entity, newState, version); + Transaction tx = createTxWithState(entity, newState, version); try { tx.commit(); fail("Expected an exception due to a failed commit."); } catch (IllegalStateException e) { - assertEquals(InvalidEntityStateException.class, e.getCause().getClass()); + assertEquals(InvalidEntityStateException.class, e.getCause() + .getClass()); } } @@ -298,21 +329,21 @@ public void throw_InvalidEntityStateException_if_constraints_violated_on_commit( Transaction tx = createTxWithState(entity, newState, version); ValidationException toThrow = validationException(); breakEntityValidation(entity, toThrow); - + thrown.expect(InvalidEntityStateException.class); tx.commit(); } @Test public void rollback_automatically_if_commit_failed() { - final E entity = createEntity(someViolations()); - final S originalState = entity.getState(); - final Version originalVersion = entity.getVersion(); + E entity = createEntity(someViolations()); + S originalState = entity.getState(); + Version originalVersion = entity.getVersion(); - final S newState = createNewState(); - final Version version = someVersion(); + S newState = createNewState(); + Version version = someVersion(); - final Transaction tx = createTxWithState(entity, newState, version); + Transaction tx = createTxWithState(entity, newState, version); try { tx.commit(); fail("Expected an IllegalStateException due to a failed commit."); @@ -323,17 +354,19 @@ public void rollback_automatically_if_commit_failed() { @Test public void advance_version_from_event() { - final E entity = createEntity(); - final Transaction tx = createTx(entity); + E entity = createEntity(); + Transaction tx = createTx(entity); assertEquals(entity.getVersion(), tx.getVersion()); - final Event event = createEvent(createEventMessage()); - final EventEnvelope envelope = EventEnvelope.of(event); + Event event = createEvent(createEventMessage()); + EventEnvelope envelope = EventEnvelope.of(event); tx.apply(envelope); - assertEquals(event.getContext().getVersion(), tx.getVersion()); + assertEquals(event.getContext() + .getVersion(), tx.getVersion()); tx.commit(); - assertEquals(event.getContext().getVersion(), entity.getVersion()); + assertEquals(event.getContext() + .getVersion(), entity.getVersion()); } protected final Event createEvent(Message eventMessage) { @@ -341,44 +374,17 @@ protected final Event createEvent(Message eventMessage) { someVersion()); } - private static ValidationException validationException() { - final ValidationException ex = new ValidationException(Lists.newLinkedList()); - return ex; - } - private void checkRollback(E entity, S originalState, Version originalVersion) { assertNull(entity.getTransaction()); assertEquals(originalState, entity.getState()); assertEquals(originalVersion, entity.getVersion()); } - private static List someViolations() { - final ConstraintViolation expectedViolation = - ConstraintViolation.newBuilder() - .setMsgFormat("Some violation %s") - .addParam("1") - .build(); - return newArrayList(expectedViolation); - } - - private ArgumentMatcher> matchesSuccessfulPhaseFor(final Event event) { + private ArgumentMatcher> matchesSuccessfulPhaseFor(Event event) { return phase -> checkPhase(event, phase, true); } - private static boolean checkPhase(Event event, Phase phase, boolean successful) { - Message eventMessage = Events.getMessage(event); - return eventMessage.equals(phase.getEventMessage()) - && event.getContext() - .equals(phase.getContext()) - && phase.isSuccessful() == successful; - } - - private void applyEvent(Transaction tx, Event event) { tx.apply(EventEnvelope.of(event)); } - - private static Version someVersion() { - return newVersion(42, getCurrentTime()); - } } From 8b881d89ecaec834d9d648c330d099e7a149b706 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:20:14 +0300 Subject: [PATCH 39/53] Improve code layout --- .../event/given/CommandHandlerTestEnv.java | 8 ++++---- .../server/model/DefaultStateRegistryShould.java | 12 ++++++------ .../outbus/enrich/EnrichmentFunctionShould.java | 5 ++--- .../given/EventMessageEnricherTestEnv.java | 16 +++------------- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java index dc3351251f5..e5695fe34c1 100644 --- a/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java +++ b/server/src/test/java/io/spine/server/event/given/CommandHandlerTestEnv.java @@ -23,7 +23,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; import com.google.protobuf.Message; import com.google.protobuf.StringValue; import io.spine.core.Command; @@ -42,13 +41,14 @@ import io.spine.test.command.event.CmdProjectCreated; import io.spine.test.command.event.CmdProjectStarted; import io.spine.test.command.event.CmdTaskAdded; +import org.checkerframework.checker.nullness.qual.Nullable; import org.slf4j.Logger; -import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.LinkedList; import java.util.List; import java.util.Set; +import static com.google.common.collect.Lists.newLinkedList; + /** * @author Alexander Yevsyukov */ @@ -60,7 +60,7 @@ private CommandHandlerTestEnv() { public static class EventCatcher implements EventDispatcher { - private final List dispatched = Lists.newLinkedList(); + private final List dispatched = newLinkedList(); @Override public Set getMessageClasses() { diff --git a/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java b/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java index 5071e30212d..522a27dfeda 100644 --- a/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java +++ b/server/src/test/java/io/spine/server/model/DefaultStateRegistryShould.java @@ -32,10 +32,11 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import static com.google.common.collect.Lists.newArrayListWithExpectedSize; import static com.google.common.collect.Maps.newConcurrentMap; +import static java.util.concurrent.Executors.callable; +import static java.util.concurrent.Executors.newFixedThreadPool; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -55,9 +56,8 @@ public class DefaultStateRegistryShould { private Map spyMap; private static void runParallel(Collection> tasks) { - ExecutorService executor = - Executors.newFixedThreadPool(Runtime.getRuntime() - .availableProcessors() * 2); + ExecutorService executor = newFixedThreadPool(Runtime.getRuntime() + .availableProcessors() * 2); try { executor.invokeAll(tasks); } catch (InterruptedException ignored) { @@ -90,7 +90,7 @@ public void invoke_put_once_when_calling_getDefaultState_in_multithreaded_enviro int numberOfEntities = 1000; Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); for (int i = 0; i < numberOfEntities; i++) { - tasks.add(Executors.callable(() -> { + tasks.add(callable(() -> { TestEntity testEntity = Given.entityOfClass(TestEntity.class) .build(); testEntity.getDefaultState(); @@ -112,7 +112,7 @@ public void invoke_put_once_when_calling_putOrGet_in_multithreaded_environment() int numberOfEntities = 1000; Collection> tasks = newArrayListWithExpectedSize(numberOfEntities); for (int i = 0; i < numberOfEntities; i++) { - tasks.add(Executors.callable(() -> { + tasks.add(callable(() -> { registry.get(TimerSnapshot.class); })); } diff --git a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java index d9a66a5f034..41f8e3c202c 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/EnrichmentFunctionShould.java @@ -56,9 +56,8 @@ public void setUp() { } ProjectCreated.Enrichment.Builder result = ProjectCreated.Enrichment .newBuilder() - .setProjectName( - input.getProjectId() - .getId()); + .setProjectName(input.getProjectId() + .getId()); return result.build(); }; this.fieldEnrichment = FieldEnrichment.of(ProjectCreated.class, diff --git a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java index 9986161ec22..bd3dc927235 100644 --- a/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java +++ b/server/src/test/java/io/spine/server/outbus/enrich/given/EventMessageEnricherTestEnv.java @@ -39,28 +39,18 @@ */ public class EventMessageEnricherTestEnv { + /** Prevent instantiation of this utility class. */ private EventMessageEnricherTestEnv() { - // Prevent instantiation of this utility class. } public static class Enrichment { private static final Function EVENT_ID_TO_STRING = - new Function() { - @Override - public @Nullable String apply(@Nullable EventId input) { - return input == null ? "" : input.getValue(); - } - }; + input -> input == null ? "" : input.getValue(); private static final Function TIMESTAMP_TO_STRING = input -> input == null ? "" : input.toString(); private static final Function CMD_CONTEXT_TO_STRING = - new Function() { - @Override - public String apply(@Nullable CommandContext input) { - return input == null ? "" : input.toString(); - } - }; + input -> input == null ? "" : input.toString(); private static final Function ANY_TO_STRING = input -> input == null ? "" : input.toString(); private static final Function VERSION_TO_STRING = From dbb62a976940643945f45abd528edf1963b94ffa Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:27:47 +0300 Subject: [PATCH 40/53] Align generic params --- .../ProjectionTransactionShould.java | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java index ff2c49d3e2d..1bd1cf296ac 100644 --- a/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java +++ b/server/src/test/java/io/spine/server/projection/ProjectionTransactionShould.java @@ -29,6 +29,7 @@ import io.spine.server.entity.Transaction; import io.spine.server.entity.TransactionListener; import io.spine.server.entity.TransactionShould; +import io.spine.server.projection.ProjectionTransactionShould.PatchedProjectBuilder; import io.spine.test.projection.Project; import io.spine.test.projection.ProjectId; import io.spine.test.projection.event.PrjProjectCreated; @@ -52,10 +53,9 @@ */ public class ProjectionTransactionShould extends TransactionShould, - Project, - ProjectionTransactionShould.PatchedProjectBuilder> { + Projection, + Project, + PatchedProjectBuilder> { private static final ProjectId ID = ProjectId.newBuilder() .setId("projection-transaction-should-project") @@ -63,34 +63,34 @@ public class ProjectionTransactionShould @Override protected Transaction, - Project, - PatchedProjectBuilder> + Projection, + Project, + PatchedProjectBuilder> createTx(Projection entity) { return new ProjectionTransaction<>(entity); } @Override protected Transaction, - Project, - PatchedProjectBuilder> createTxWithState( - Projection entity, Project state, - Version version) { + Projection, + Project, + PatchedProjectBuilder> + createTxWithState(Projection entity, + Project state, + Version version) { return new ProjectionTransaction<>(entity, state, version); } @Override protected Transaction, - Project, - PatchedProjectBuilder> + Projection, + Project, + PatchedProjectBuilder> createTxWithListener(Projection entity, TransactionListener, - Project, PatchedProjectBuilder> listener) { + Projection, + Project, + PatchedProjectBuilder> listener) { return new ProjectionTransaction<>(entity, listener); } @@ -100,8 +100,8 @@ protected Projection createEntity() { } @Override - protected Projection createEntity( - List violations) { + protected Projection + createEntity(List violations) { return new TestProjection(ID, violations); } @@ -114,9 +114,8 @@ protected Project createNewState() { } @Override - protected void checkEventReceived( - Projection entity, - Event event) { + protected void checkEventReceived(Projection entity, + Event event) { TestProjection aggregate = (TestProjection) entity; Message actualMessage = unpack(event.getMessage()); From d4039d817681f28a94c00e218b796a852cf89829 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:44:46 +0300 Subject: [PATCH 41/53] Improve code layout --- .../spine/server/stand/StandPostShould.java | 106 +++++++++--------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/server/src/test/java/io/spine/server/stand/StandPostShould.java b/server/src/test/java/io/spine/server/stand/StandPostShould.java index 2892c94ab34..2dde8eff42d 100644 --- a/server/src/test/java/io/spine/server/stand/StandPostShould.java +++ b/server/src/test/java/io/spine/server/stand/StandPostShould.java @@ -31,6 +31,7 @@ import io.spine.server.aggregate.AggregateRepository; import io.spine.server.entity.EntityStateEnvelope; import io.spine.server.projection.ProjectionRepository; +import io.spine.server.stand.Given.StandTestAggregate; import io.spine.server.storage.StorageFactory; import io.spine.test.projection.ProjectId; import org.junit.Assert; @@ -67,9 +68,9 @@ private static BoundedContextAction[] getSeveralRepositoryDispatchCalls() { BoundedContextAction[] result = new BoundedContextAction[Given.SEVERAL]; for (int i = 0; i < result.length; i++) { - result[i] = (i % 2 == 0) - ? aggregateRepositoryDispatch() - : projectionRepositoryDispatch(); + result[i] = ((i % 2) == 0) + ? StandPostShould::aggregateRepositoryDispatch + : StandPostShould::projectionRepositoryDispatch; } return result; @@ -107,64 +108,61 @@ private static void checkUpdatesDelivery(boolean isConcurrent, verify(stand, times(dispatchActions.length)).update(any(EntityStateEnvelope.class)); } - @SuppressWarnings("CheckReturnValue") // can ignore the dispatch() result - private static BoundedContextAction aggregateRepositoryDispatch() { - return context -> { - // Init repository - final AggregateRepository repository = Given.aggregateRepo(); - - repository.initStorage(storageFactory(context.isMultitenant())); + private static StorageFactory storageFactory(boolean multitenant) { + BoundedContext bc = BoundedContext + .newBuilder() + .setMultitenant(multitenant) + .build(); + return bc.getStorageFactory(); + } - try { - // Mock aggregate and mock stand are not able to handle events - // returned after command handling. - // This causes IllegalStateException to be thrown. - // Note that this is not the end of a test case, - // so we can't just "expect=IllegalStateException". - CommandEnvelope cmd = CommandEnvelope.of(Given.validCommand()); - repository.dispatch(cmd); - } catch (IllegalStateException e) { - // Handle null event dispatching after the command is handled. - - // Check if this error is caused by returning null or empty list after - // command processing. - // Proceed crash if it's not. - if (!e.getMessage() - .contains("No record found for command ID: EMPTY")) { - throw e; - } + /** + * Creates a repository and dispatches a command to it. + */ + @SuppressWarnings("CheckReturnValue") // can ignore the dispatch() result + private static void aggregateRepositoryDispatch(BoundedContext context) { + // Init repository + AggregateRepository repository = Given.aggregateRepo(); + repository.initStorage(storageFactory(context.isMultitenant())); + + try { + // Mock aggregate and mock stand are not able to handle events + // returned after command handling. + // This causes IllegalStateException to be thrown. + // Note that this is not the end of a test case, + // so we can't just "expect=IllegalStateException". + CommandEnvelope cmd = CommandEnvelope.of(Given.validCommand()); + repository.dispatch(cmd); + } catch (IllegalStateException e) { + // Handle null event dispatching after the command is handled. + + // Check if this error is caused by returning null or empty list after + // command processing. + // Proceed crash if it's not. + if (!e.getMessage() + .contains("No record found for command ID: EMPTY")) { + throw e; } - }; + } } @SuppressWarnings("CheckReturnValue") // can ignore the dispatch() result - private static BoundedContextAction projectionRepositoryDispatch() { - return context -> { - // Init repository - ProjectionRepository repository = Given.projectionRepo(); - repository.initStorage(storageFactory(context.isMultitenant())); - - // Dispatch an update from projection repo - repository.dispatch(EventEnvelope.of(Given.validEvent())); - }; - } + private static void projectionRepositoryDispatch(BoundedContext context) { + ProjectionRepository repository = Given.projectionRepo(); + repository.initStorage(storageFactory(context.isMultitenant())); - private static StorageFactory storageFactory(boolean multitenant) { - BoundedContext bc = BoundedContext.newBuilder() - .setMultitenant(multitenant) - .build(); - return bc.getStorageFactory(); + // Dispatch an update from projection repo + repository.dispatch(EventEnvelope.of(Given.validEvent())); } @Test public void deliver_updates() { - AggregateRepository repository = - Given.aggregateRepo(); + AggregateRepository repository = Given.aggregateRepo(); ProjectId entityId = ProjectId .newBuilder() .setId("PRJ-001") .build(); - Given.StandTestAggregate entity = repository.create(entityId); + StandTestAggregate entity = repository.create(entityId); StringValue state = entity.getState(); Version version = entity.getVersion(); @@ -184,21 +182,21 @@ public void deliver_updates() { .orNull()); boolean stateMatches = argument.getMessage() .equals(state); - return entityIdMatches && - versionMatches && - stateMatches; + return entityIdMatches + && versionMatches + && stateMatches; }; verify(stand).update(ArgumentMatchers.argThat(argumentMatcher)); } @Test public void deliver_updates_from_projection_repository() { - checkUpdatesDelivery(false, projectionRepositoryDispatch()); + checkUpdatesDelivery(false, StandPostShould::projectionRepositoryDispatch); } @Test public void deliver_updates_from_aggregate_repository() { - checkUpdatesDelivery(false, aggregateRepositoryDispatch()); + checkUpdatesDelivery(false, StandPostShould::aggregateRepositoryDispatch); } @Test @@ -230,8 +228,8 @@ public void deliver_updates_through_several_threads() throws InterruptedExceptio .newBuilder() .setId(Identifier.newUuid()) .build(); - Given.StandTestAggregate entity = Given.aggregateRepo() - .create(entityId); + StandTestAggregate entity = Given.aggregateRepo() + .create(entityId); stand.post(requestFactory.createCommandContext() .getActorContext() .getTenantId(), entity); From 5ba1a157b6be439eab22b77c7fd78857a41184dd Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:45:35 +0300 Subject: [PATCH 42/53] Add static import --- .../src/test/java/io/spine/server/stand/StandPostShould.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/test/java/io/spine/server/stand/StandPostShould.java b/server/src/test/java/io/spine/server/stand/StandPostShould.java index 2dde8eff42d..8d11b9ad644 100644 --- a/server/src/test/java/io/spine/server/stand/StandPostShould.java +++ b/server/src/test/java/io/spine/server/stand/StandPostShould.java @@ -38,7 +38,6 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentMatcher; -import org.mockito.ArgumentMatchers; import java.util.Set; import java.util.concurrent.Executor; @@ -48,6 +47,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -186,7 +186,7 @@ public void deliver_updates() { && versionMatches && stateMatches; }; - verify(stand).update(ArgumentMatchers.argThat(argumentMatcher)); + verify(stand).update(argThat(argumentMatcher)); } @Test From b9f1c0f99227d184810314d7e365e49e2e4f9694 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 01:58:16 +0300 Subject: [PATCH 43/53] Use streams --- .../server/storage/RecordStorageShould.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java index 07e48856ce5..dcc381cba7a 100644 --- a/server/src/test/java/io/spine/server/storage/RecordStorageShould.java +++ b/server/src/test/java/io/spine/server/storage/RecordStorageShould.java @@ -22,7 +22,6 @@ import com.google.common.base.Function; import com.google.common.base.Optional; -import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -59,7 +58,6 @@ import io.spine.test.storage.Project; import io.spine.test.storage.ProjectVBuilder; import io.spine.testdata.Sample; -import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.Test; import org.mockito.ArgumentMatcher; @@ -70,6 +68,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Sets.newHashSet; @@ -150,11 +149,12 @@ private EntityRecord newStorageRecord(I id) { private EntityRecord newStorageRecord(I id, Message state) { Any wrappedState = pack(state); - EntityRecord record = EntityRecord.newBuilder() - .setEntityId(pack(id)) - .setState(wrappedState) - .setVersion(GivenVersion.withNumber(0)) - .build(); + EntityRecord record = EntityRecord + .newBuilder() + .setEntityId(pack(id)) + .setState(wrappedState) + .setVersion(GivenVersion.withNumber(0)) + .build(); return record; } @@ -290,8 +290,14 @@ public void write_record_bulk() { Collection actual = newArrayList( storage.readMultiple(initial.keySet()) ); + Collection expected = - Collections2.transform(initial.values(), EntityRecordWithColumns::getRecord); + initial.values() + .stream() + .map(recordWithColumns -> recordWithColumns != null + ? recordWithColumns.getRecord() + : null) + .collect(Collectors.toList()); assertEquals(expected.size(), actual.size()); assertTrue(actual.containsAll(expected)); @@ -305,15 +311,9 @@ public void rewrite_records_in_bulk() { RecordStorage storage = getStorage(); Function recordPacker = - new Function() { - @Override - public @Nullable EntityRecordWithColumns apply(@Nullable EntityRecord record) { - if (record == null) { - return null; - } - return withLifecycleColumns(record); - } - }; + record -> record != null + ? withLifecycleColumns(record) + : null; Map v1Records = new HashMap<>(recordCount); Map v2Records = new HashMap<>(recordCount); @@ -894,7 +894,6 @@ enum ProjectStatus { UNRECOGNIZED } - /** * Entity columns representing lifecycle flags, {@code archived} and {@code deleted}. * From febd39eed37bcd90e5527bffe95621bd0cb9a15b Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 02:02:25 +0300 Subject: [PATCH 44/53] Fix code layout --- .../io/spine/server/entity/given/Given.java | 30 ++++++++----------- .../server/command/CommandTestShould.java | 6 ++-- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java index fd44e37d13d..f0a81fc3ee3 100644 --- a/testutil-server/src/main/java/io/spine/server/entity/given/Given.java +++ b/testutil-server/src/main/java/io/spine/server/entity/given/Given.java @@ -72,12 +72,10 @@ AggregateBuilder aggregateOfClass(Class
aggregateClass) { /** * Creates a builder for an {@code AggregatePart}. */ - public static < - A extends AggregatePart, - I, - S extends Message, - R extends AggregateRoot - > + public static , + I, + S extends Message, + R extends AggregateRoot> AggregatePartBuilder aggregatePartOfClass(Class partClass) { checkNotNull(partClass); AggregatePartBuilder result = new AggregatePartBuilder<>(); @@ -88,12 +86,10 @@ AggregatePartBuilder aggregatePartOfClass(Class partClass) { /** * Creates a builder for a {@code Projection}. */ - public static < - P extends Projection, - I, - S extends Message, - B extends ValidatingBuilder - > + public static

, + I, + S extends Message, + B extends ValidatingBuilder> ProjectionBuilder projectionOfClass(Class

projectionClass) { checkNotNull(projectionClass); ProjectionBuilder result = new ProjectionBuilder<>(); @@ -104,12 +100,10 @@ ProjectionBuilder projectionOfClass(Class

projectionClass) { /** * Creates a builder for a {@code ProcessManager}. */ - public static < - P extends ProcessManager, - I, - S extends Message, - B extends ValidatingBuilder - > + public static

, + I, + S extends Message, + B extends ValidatingBuilder> ProcessManagerBuilder processManagerOfClass(Class

pmClass) { checkNotNull(pmClass); ProcessManagerBuilder result = new ProcessManagerBuilder<>(); diff --git a/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java b/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java index 6fee6f11229..e0b84bba86a 100644 --- a/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java +++ b/testutil-server/src/test/java/io/spine/server/command/CommandTestShould.java @@ -72,9 +72,9 @@ private static void createAndAssertCommand(CommandTest commandTest) * *

The factory gets: *

    - *
  • generated {@code UserId} for the actor. - *
  • UTC zone offset - *
  • {@code TenantId} based on the simple name of the passed class. + *
  • generated {@code UserId} for the actor. + *
  • UTC zone offset + *
  • {@code TenantId} based on the simple name of the passed class. *
*/ static ActorRequestFactory newRequestFactory(Class clazz) { From 1c4823d3413603b024aaea4b70006d92b2e3593a Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Thu, 31 May 2018 03:35:48 +0300 Subject: [PATCH 45/53] Resolve Error Prone errors --- .idea/inspectionProfiles/Project_Default.xml | 7 +++ .../java/io/spine/client/CommandFactory.java | 29 +++++----- .../test/java/io/spine/core/CommandsTest.java | 17 +++--- .../io/spine/grpc/MetadataConverterTest.java | 32 +++++----- .../io/spine/grpc/StreamObserversTest.java | 58 +++++++++---------- .../server/projection/ProjectionEndpoint.java | 18 +++--- .../entity/TransactionalEntityShould.java | 3 - .../server/storage/RecordStorageShould.java | 2 +- 8 files changed, 87 insertions(+), 79 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index ce135191ae6..9e94fc79698 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -354,6 +354,13 @@